[automerger skipped] Merge "Import translations. DO NOT MERGE ANYWHERE" into qt-car-dev am: 36a4492f7d -s ours

am skip reason: subject contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Car/libs/+/13133152

Change-Id: Ie36852eb22764c6e19df6a4503c7d21dfecb16ba
diff --git a/OWNERS b/OWNERS
index c1e7ec6..15d29ad 100644
--- a/OWNERS
+++ b/OWNERS
@@ -6,6 +6,7 @@
 stenning@google.com
 yizheng@google.com
 robertoalexis@google.com
+farivar@google.com
 
 # TLMs
 johnchoi@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index a810f8e..e438129 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -3,6 +3,8 @@
 ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
 chassis_current_hook = car-ui-lib/tests/apitest/auto-generate-resources.py --sha ${PREUPLOAD_COMMIT} --compare
 chassis_findviewbyid_check = car-ui-lib/findviewbyid-preupload-hook.sh
+chassis_trailing_blank_line_check = car-ui-lib/trailing-blank-line-hook.sh
+
 [Builtin Hooks]
 commit_msg_changeid_field = true
 commit_msg_test_field = true
diff --git a/android-car-lib/Android.mk b/android-car-lib/Android.mk
deleted file mode 100644
index a7cd0b3..0000000
--- a/android-car-lib/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2015 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.
-#
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_AAPT2_ONLY := true
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-        android-car:android-car.aar
-
-include $(BUILD_MULTI_PREBUILT)
diff --git a/android-car-lib/android-car-lib.mk b/android-car-lib/android-car-lib.mk
deleted file mode 100644
index 419daab..0000000
--- a/android-car-lib/android-car-lib.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Include this make file to build your application with car ui.
-# This only applied to app which is not CarActivity based but wants to use car-ui.
-#
-# Make sure to include it after you've set all your desired LOCAL variables.
-# Note that you must explicitly set your LOCAL_RESOURCE_DIR before including this file.
-#
-# For example:
-#
-#   LOCAL_RESOURCE_DIR := \
-#        $(LOCAL_PATH)/res
-#
-#   In your .mk file, include the items in the following order, to ensure the prebuilt
-#   static libraries are included in the correct order.
-#
-#   include vendor/auto/embedded/prebuilts/android-car-lib/car-lib.mk
-#   include $(BUILD_PACKAGE)
-#   include vendor/auto/embedded/prebuilts/android-car-lib/Android.mk
-
-# Check that LOCAL_RESOURCE_DIR is defined
-ifeq (,$(LOCAL_RESOURCE_DIR))
-$(error LOCAL_RESOURCE_DIR must be defined)
-endif
-
-LOCAL_STATIC_JAVA_AAR_LIBRARIES += android-car
-
-# Work around limitations of AAR prebuilts
-LOCAL_RESOURCE_DIR += packages/apps/Car/libs/android-car-lib/res
-
-# Include support-v7-appcompat, if not already included
-ifeq (,$(findstring android-support-v7-appcompat,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v7-appcompat
-endif
-
-# Include support-v7-recyclerview, if not already included
-ifeq (,$(findstring android-support-v7-recyclerview,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v7-recyclerview
-endif
-
-# Include support-v7-cardview, if not already included
-ifeq (,$(findstring android-support-v7-cardview,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v7-cardview
-endif
-
-# Include support-design, if not already included
-ifeq (,$(findstring android-support-design,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-design
-endif
-
-# Include support-v4, if not already included
-ifeq (,$(findstring android-support-v4,$(LOCAL_STATIC_JAVA_LIBRARIES)))
-LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v4
-endif
diff --git a/android-car-lib/android-car.aar b/android-car-lib/android-car.aar
deleted file mode 100644
index ff03a9c..0000000
--- a/android-car-lib/android-car.aar
+++ /dev/null
Binary files differ
diff --git a/android-car-lib/car-release.aar b/android-car-lib/car-release.aar
deleted file mode 100644
index ff03a9c..0000000
--- a/android-car-lib/car-release.aar
+++ /dev/null
Binary files differ
diff --git a/android-car-lib/res/anim/fade_in_trans_left.xml b/android-car-lib/res/anim/fade_in_trans_left.xml
deleted file mode 100644
index 2d6bab5..0000000
--- a/android-car-lib/res/anim/fade_in_trans_left.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:duration="@android:integer/config_shortAnimTime">
-    <translate
-        android:interpolator="@android:interpolator/decelerate_quint"
-        android:fromXDelta="-10%p"
-        android:toXDelta="0" />
-
-    <alpha
-        android:fromAlpha="0.2"
-        android:toAlpha="1"
-        android:interpolator="@android:interpolator/decelerate_quint" />
-</set>
diff --git a/android-car-lib/res/anim/fade_in_trans_left_layout_anim.xml b/android-car-lib/res/anim/fade_in_trans_left_layout_anim.xml
deleted file mode 100644
index e7660db..0000000
--- a/android-car-lib/res/anim/fade_in_trans_left_layout_anim.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<layoutAnimation
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:animation="@anim/fade_in_trans_left"
-    android:delay="0%"
-    android:animationOrder="normal" />
diff --git a/android-car-lib/res/anim/fade_in_trans_right.xml b/android-car-lib/res/anim/fade_in_trans_right.xml
deleted file mode 100644
index 5cbeb59..0000000
--- a/android-car-lib/res/anim/fade_in_trans_right.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:duration="@android:integer/config_shortAnimTime">
-    <translate
-        android:interpolator="@android:interpolator/decelerate_quint"
-        android:fromXDelta="10%p"
-        android:toXDelta="0" />
-
-    <alpha
-        android:fromAlpha="0.2"
-        android:toAlpha="1"
-        android:interpolator="@android:interpolator/decelerate_quint" />
-</set>
diff --git a/android-car-lib/res/anim/fade_in_trans_right_layout_anim.xml b/android-car-lib/res/anim/fade_in_trans_right_layout_anim.xml
deleted file mode 100644
index b76de23..0000000
--- a/android-car-lib/res/anim/fade_in_trans_right_layout_anim.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<layoutAnimation
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:animation="@anim/fade_in_trans_right"
-    android:delay="0%"
-    android:animationOrder="normal" />
diff --git a/android-car-lib/res/anim/lock_out_message_bar.xml b/android-car-lib/res/anim/lock_out_message_bar.xml
deleted file mode 100644
index e70a4ef..0000000
--- a/android-car-lib/res/anim/lock_out_message_bar.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<set
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="@integer/speed_bump_lock_out_duration_ms"
-        android:propertyName="pathData"
-        android:valueFrom="M 96.5,48.5 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903411865 48.0,48.0 Z"
-        android:valueTo="M 480.5,48.5 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903259277 48.0,48.0 Z"
-        android:valueType="pathType"
-        android:interpolator="@interpolator/speed_bump_interpolator" />
-</set>
diff --git a/android-car-lib/res/anim/lock_out_message_bg_color_change.xml b/android-car-lib/res/anim/lock_out_message_bg_color_change.xml
deleted file mode 100644
index 6d56ff4..0000000
--- a/android-car-lib/res/anim/lock_out_message_bg_color_change.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<set
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:startOffset="@integer/speed_bump_lock_out_color_change_start_delay_ms"
-        android:duration="@integer/speed_bump_lock_out_color_change_ms"
-        android:propertyName="fillColor"
-        android:valueFrom="#FF029AE5"
-        android:valueTo="#FF26994B"
-        android:interpolator="@android:interpolator/linear" />
-</set>
diff --git a/android-car-lib/res/anim/lock_out_message_in.xml b/android-car-lib/res/anim/lock_out_message_in.xml
deleted file mode 100644
index aae3d17..0000000
--- a/android-car-lib/res/anim/lock_out_message_in.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <alpha
-        android:fromAlpha="0"
-        android:toAlpha="1.0"
-        android:fillEnabled="true"
-        android:fillBefore="true"
-        android:fillAfter="true"
-        android:interpolator="@android:interpolator/accelerate_quint"
-        android:duration="@integer/speed_bump_fade_duration_ms"/>
-    <translate
-        android:fromYDelta="100%"
-        android:toYDelta="0%"
-        android:fillEnabled="true"
-        android:fillBefore="true"
-        android:fillAfter="true"
-        android:interpolator="@android:interpolator/linear_out_slow_in"
-        android:duration="@integer/speed_bump_translate_y_duration_ms"/>
-</set>
diff --git a/android-car-lib/res/anim/lock_out_message_out.xml b/android-car-lib/res/anim/lock_out_message_out.xml
deleted file mode 100644
index 3044d0a..0000000
--- a/android-car-lib/res/anim/lock_out_message_out.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- Copyright (C) 2018 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <alpha
-        android:fromAlpha="1.0"
-        android:toAlpha="0"
-        android:fillEnabled="true"
-        android:fillBefore="true"
-        android:fillAfter="true"
-        android:interpolator="@android:interpolator/accelerate_quint"
-        android:duration="@integer/speed_bump_fade_duration_ms"/>
-</set>
diff --git a/android-car-lib/res/drawable/car_action_button_activated_ring_foreground.xml b/android-car-lib/res/drawable/car_action_button_activated_ring_foreground.xml
deleted file mode 100644
index cf9570b..0000000
--- a/android-car-lib/res/drawable/car_action_button_activated_ring_foreground.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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:state_activated="true">
-    <shape
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shape="oval">
-      <stroke
-          android:color="@color/car_tint"
-          android:width="@dimen/car_action_bar_activation_ring_stroke_width">
-      </stroke>
-      <size
-          android:height="@dimen/car_action_bar_activation_ring_radius"
-          android:width="@dimen/car_action_bar_activation_ring_radius"/>
-    </shape>
-  </item>
-  <!--Yes, this is a load-bearing invisible circle.-->
-  <!--Android doesn't remeasure foregrounds when state_activated changes, -->
-  <!--so we need a default drawable with the same size as the one we actually want to draw-->
-  <item>
-    <shape
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shape="oval">
-      <stroke
-          android:color="#00000000"
-          android:width="@dimen/car_action_bar_activation_ring_stroke_width">
-      </stroke>
-      <size
-          android:height="@dimen/car_action_bar_activation_ring_radius"
-          android:width="@dimen/car_action_bar_activation_ring_radius"/>
-    </shape>
-  </item>
-</selector>
diff --git a/android-car-lib/res/drawable/car_action_button_background.xml b/android-car-lib/res/drawable/car_action_button_background.xml
deleted file mode 100644
index 27e97e3..0000000
--- a/android-car-lib/res/drawable/car_action_button_background.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:inset="@dimen/car_action_button_ripple_inset" >
-    <ripple android:color="@color/car_card_ripple_background" />
-</inset>
diff --git a/android-car-lib/res/drawable/car_borderless_button_text_color.xml b/android-car-lib/res/drawable/car_borderless_button_text_color.xml
deleted file mode 100644
index 27f79f0..0000000
--- a/android-car-lib/res/drawable/car_borderless_button_text_color.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2017 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.
--->
-<!-- Default text colors for car buttons when enabled/disabled. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/car_grey_700" android:state_enabled="false"/>
-    <item android:color="?android:attr/colorButtonNormal"/>
-</selector>
diff --git a/android-car-lib/res/drawable/car_button_background.xml b/android-car-lib/res/drawable/car_button_background.xml
deleted file mode 100644
index 58aa739..0000000
--- a/android-car-lib/res/drawable/car_button_background.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2017 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.
--->
-<!-- Default background styles for car buttons when enabled/disabled. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false">
-        <shape android:shape="rectangle">
-            <corners android:radius="@dimen/car_button_radius"/>
-            <solid android:color="@color/car_grey_300"/>
-        </shape>
-    </item>
-    <item>
-        <shape android:shape="rectangle">
-            <corners android:radius="@dimen/car_button_radius"/>
-            <solid android:color="?android:attr/colorButtonNormal"/>
-        </shape>
-    </item>
-</selector>
diff --git a/android-car-lib/res/drawable/car_button_text_color.xml b/android-car-lib/res/drawable/car_button_text_color.xml
deleted file mode 100644
index bb8c681..0000000
--- a/android-car-lib/res/drawable/car_button_text_color.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2017 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.
--->
-<!-- Default text colors for car buttons when enabled/disabled. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/car_grey_700" android:state_enabled="false"/>
-    <item android:color="@color/car_action1"/>
-</selector>
diff --git a/android-car-lib/res/drawable/car_card_background.xml b/android-car-lib/res/drawable/car_card_background.xml
deleted file mode 100644
index 7caa2ff..0000000
--- a/android-car-lib/res/drawable/car_card_background.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_card_ripple_background.xml b/android-car-lib/res/drawable/car_card_ripple_background.xml
deleted file mode 100644
index ca20e0f..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background">
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_ripple_background_day.xml b/android-car-lib/res/drawable/car_card_ripple_background_day.xml
deleted file mode 100644
index 880ff7a..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background_day.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background_dark">
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_ripple_background_inverse.xml b/android-car-lib/res/drawable/car_card_ripple_background_inverse.xml
deleted file mode 100644
index e063e2c..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background_inverse.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background_inverse" >
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_ripple_background_night.xml b/android-car-lib/res/drawable/car_card_ripple_background_night.xml
deleted file mode 100644
index 5d4f2c6..0000000
--- a/android-car-lib/res/drawable/car_card_ripple_background_night.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background_light">
-    <item
-        android:id="@android:id/mask"
-        android:drawable="@android:color/white" />
-</ripple>
diff --git a/android-car-lib/res/drawable/car_card_rounded_background.xml b/android-car-lib/res/drawable/car_card_rounded_background.xml
deleted file mode 100644
index 594705b..0000000
--- a/android-car-lib/res/drawable/car_card_rounded_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-    <corners
-        android:radius="@dimen/car_radius_3"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_card_rounded_bottom_background.xml b/android-car-lib/res/drawable/car_card_rounded_bottom_background.xml
deleted file mode 100644
index 35dba13..0000000
--- a/android-car-lib/res/drawable/car_card_rounded_bottom_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-    <corners
-        android:bottomRightRadius="@dimen/car_radius_3"
-        android:bottomLeftRadius="@dimen/car_radius_3"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_card_rounded_top_background.xml b/android-car-lib/res/drawable/car_card_rounded_top_background.xml
deleted file mode 100644
index dfb5622..0000000
--- a/android-car-lib/res/drawable/car_card_rounded_top_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/car_card"/>
-    <corners
-        android:topRightRadius="@dimen/car_radius_3"
-        android:topLeftRadius="@dimen/car_radius_3"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_drawer_list_item_background.xml b/android-car-lib/res/drawable/car_drawer_list_item_background.xml
deleted file mode 100644
index c5fc36b..0000000
--- a/android-car-lib/res/drawable/car_drawer_list_item_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/car_card_ripple_background">
-    <item android:id="@android:id/mask">
-        <color android:color="#ffffffff" />
-    </item>
-</ripple>
diff --git a/android-car-lib/res/drawable/car_list_divider.xml b/android-car-lib/res/drawable/car_list_divider.xml
deleted file mode 100644
index 14a5ce1..0000000
--- a/android-car-lib/res/drawable/car_list_divider.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-
-<!-- Drawable of dividers used in lists -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <size android:height="@dimen/car_list_divider_height"/>
-    <solid android:color="@color/car_list_divider"/>
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_list_divider_dark.xml b/android-car-lib/res/drawable/car_list_divider_dark.xml
deleted file mode 100644
index 4760623..0000000
--- a/android-car-lib/res/drawable/car_list_divider_dark.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<!-- Drawable of dividers used in lists -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-  <size android:height="@dimen/car_list_divider_height"/>
-  <solid android:color="@color/car_list_divider_dark"/>
-</shape>
diff --git a/android-car-lib/res/drawable/car_list_divider_light.xml b/android-car-lib/res/drawable/car_list_divider_light.xml
deleted file mode 100644
index 07b52dd..0000000
--- a/android-car-lib/res/drawable/car_list_divider_light.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<!-- Drawable of dividers used in lists -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-  <size android:height="@dimen/car_list_divider_height"/>
-  <solid android:color="@color/car_list_divider_light"/>
-</shape>
diff --git a/android-car-lib/res/drawable/car_scrollbar_thumb.xml b/android-car-lib/res/drawable/car_scrollbar_thumb.xml
deleted file mode 100644
index 42aaebf..0000000
--- a/android-car-lib/res/drawable/car_scrollbar_thumb.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="@color/car_scrollbar_thumb" />
-    <corners android:radius="@dimen/car_radius_5"/>
-</shape>
diff --git a/android-car-lib/res/drawable/car_seekbar_thumb.xml b/android-car-lib/res/drawable/car_seekbar_thumb.xml
deleted file mode 100644
index a5c4910..0000000
--- a/android-car-lib/res/drawable/car_seekbar_thumb.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <solid android:color="@color/car_accent" />
-    <size
-        android:width="@dimen/car_seekbar_thumb_size"
-        android:height="@dimen/car_seekbar_thumb_size" />
-</shape>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/car_seekbar_track.xml b/android-car-lib/res/drawable/car_seekbar_track.xml
deleted file mode 100644
index 05700c2..0000000
--- a/android-car-lib/res/drawable/car_seekbar_track.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@android:id/background">
-        <shape android:shape="line">
-            <stroke
-                android:width="@dimen/car_seekbar_height"
-                android:color="@color/car_seekbar_track_background" />
-        </shape>
-    </item>
-    <item android:id="@android:id/progress">
-        <clip>
-            <shape android:shape="line">
-                <stroke
-                    android:width="@dimen/car_seekbar_height"
-                    android:color="@color/car_accent" />
-            </shape>
-        </clip>
-    </item>
-</layer-list>
\ No newline at end of file
diff --git a/android-car-lib/res/drawable/ic_down.xml b/android-car-lib/res/drawable/ic_down.xml
deleted file mode 100644
index cd486c1..0000000
--- a/android-car-lib/res/drawable/ic_down.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 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.
-  -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="76dp"
-        android:height="76dp"
-        android:viewportWidth="76.0"
-        android:viewportHeight="76.0">
-    <path
-        android:pathData="M38,0.96C17.01,0.96 0,17.75 0,38.47C0,59.18 17.01,75.97 38,75.97C58.99,75.97 76,59.18 76,38.47C76,17.75 58.99,0.96 38,0.96M38,3.3C57.64,3.3 73.62,19.08 73.62,38.47C73.62,57.85 57.64,73.63 38,73.63C18.36,73.63 2.38,57.86 2.38,38.47C2.38,19.08 18.36,3.3 38,3.3"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-    <path
-        android:pathData="M26.63,31.09l11.37,11.08l11.37,-11.08l3.5,3.42l-14.87,14.5l-14.87,-14.5z"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-</vector>
diff --git a/android-car-lib/res/drawable/ic_list_view_disable.xml b/android-car-lib/res/drawable/ic_list_view_disable.xml
deleted file mode 100644
index 8649423..0000000
--- a/android-car-lib/res/drawable/ic_list_view_disable.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="176dp"
-        android:height="176dp"
-        android:viewportWidth="176.0"
-        android:viewportHeight="176.0">
-    <path
-        android:pathData="M88.99,55.55l15.71,15.71l46.13,0l0,-15.71z"
-        android:fillColor="#212121"/>
-    <path
-        android:pathData="M25.19,119.06h66.5v15.71h-66.5z"
-        android:fillColor="#212121"/>
-    <path
-        android:pathData="M114.58,103.35l-15.71,-15.71l-0.12,0l-16.38,-16.38l0.12,0l-15.71,-15.71l-0.12,0l-30.29,-30.29l-11.11,11.11l19.19,19.18l-19.28,0l0,15.71l34.98,0l16.39,16.38l-51.37,0l0,15.71l67.08,0l47.38,47.39l11.11,-11.11l-36.28,-36.28z"
-        android:fillColor="#212121"/>
-    <path
-        android:pathData="M136.79,103.35l14.04,0l0,-15.71l-29.74,0z"
-        android:fillColor="#212121"/>
-</vector>
diff --git a/android-car-lib/res/drawable/ic_overflow.xml b/android-car-lib/res/drawable/ic_overflow.xml
deleted file mode 100644
index eda306c..0000000
--- a/android-car-lib/res/drawable/ic_overflow.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="56dp"
-    android:height="56dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-
-    <group
-            android:translateX="-0.750000"
-            android:translateY="-0.750000">
-        <path
-            android:strokeWidth="1"
-            android:pathData="M 0.75 24.75 L 24.75 24.75 L 24.75 0.75 L 0.75 0.75 Z" />
-        <path
-            android:fillColor="#000000"
-            android:strokeWidth="1"
-            android:pathData="M12.75,10.1666667 C13.4604167,10.1666667 14.0416667,9.58541667 14.0416667,8.875
-C14.0416667,8.16458333 13.4604167,7.58333333 12.75,7.58333333
-C12.0395833,7.58333333 11.4583333,8.16458333 11.4583333,8.875
-C11.4583333,9.58541667 12.0395833,10.1666667 12.75,10.1666667 L12.75,10.1666667
-Z M12.75,11.4583333 C12.0395833,11.4583333 11.4583333,12.0395833
-11.4583333,12.75 C11.4583333,13.4604167 12.0395833,14.0416667 12.75,14.0416667
-C13.4604167,14.0416667 14.0416667,13.4604167 14.0416667,12.75
-C14.0416667,12.0395833 13.4604167,11.4583333 12.75,11.4583333 L12.75,11.4583333
-Z M12.75,15.3333333 C12.0395833,15.3333333 11.4583333,15.9145833
-11.4583333,16.625 C11.4583333,17.3354167 12.0395833,17.9166667 12.75,17.9166667
-C13.4604167,17.9166667 14.0416667,17.3354167 14.0416667,16.625
-C14.0416667,15.9145833 13.4604167,15.3333333 12.75,15.3333333 L12.75,15.3333333
-Z" />
-    </group>
-</vector>
diff --git a/android-car-lib/res/drawable/ic_up.xml b/android-car-lib/res/drawable/ic_up.xml
deleted file mode 100644
index ec18410..0000000
--- a/android-car-lib/res/drawable/ic_up.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 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.
-  -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="76dp"
-        android:height="76dp"
-        android:viewportWidth="76.0"
-        android:viewportHeight="76.0">
-    <path
-        android:pathData="M38,75.04C58.99,75.04 76,58.27 76,37.57C76,16.88 58.99,0.11 38,0.11C17.01,0.11 0,16.88 0,37.57C0,58.27 17.01,75.04 38,75.04M38,72.7C18.36,72.7 2.38,56.94 2.38,37.57C2.38,18.21 18.36,2.45 38,2.45C57.64,2.45 73.62,18.21 73.62,37.57C73.62,56.94 57.64,72.7 38,72.7"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-    <path
-        android:pathData="M49.37,44.9l-11.37,-11.08l-11.37,11.08l-3.5,-3.42l14.87,-14.5l14.87,14.5z"
-        android:strokeColor="#00000000"
-        android:fillColor="#212121"
-        android:strokeWidth="1"/>
-</vector>
diff --git a/android-car-lib/res/drawable/lock_out_message_animation.xml b/android-car-lib/res/drawable/lock_out_message_animation.xml
deleted file mode 100644
index 42cea41..0000000
--- a/android-car-lib/res/drawable/lock_out_message_animation.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/lock_out_message_background" >
-    <target
-        android:name="bar_mask"
-        android:animation="@anim/lock_out_message_bar" />
-    <target
-        android:name="bar_path"
-        android:animation="@anim/lock_out_message_bg_color_change" />
-</animated-vector>
diff --git a/android-car-lib/res/drawable/lock_out_message_background.xml b/android-car-lib/res/drawable/lock_out_message_background.xml
deleted file mode 100644
index 26b559b..0000000
--- a/android-car-lib/res/drawable/lock_out_message_background.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="480dp"
-    android:viewportWidth="480"
-    android:height="96dp"
-    android:viewportHeight="96" >
-    <group
-        android:name="base"
-        android:translateX="240"
-        android:translateY="48"
-        android:scaleX="0.994"
-        android:scaleY="0.994" >
-        <group
-            android:name="base_pivot"
-            android:translateX="-240"
-            android:translateY="-47" >
-            <group
-                android:name="base"
-                android:scaleY="0.99" >
-                <path
-                    android:name="base_path"
-                    android:pathData="M 480.0,48.0 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903259277 48.0,48.0 Z"
-                    android:fillColor="@color/speed_bump_background" />
-            </group>
-        </group>
-    </group>
-    <group
-        android:name="bar"
-        android:translateX="240"
-        android:translateY="48" >
-        <group
-            android:name="bar_pivot"
-            android:translateX="-240"
-            android:translateY="-48" >
-            <clip-path
-                android:name="bar_mask"
-                android:pathData="M 96.5,48.5 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903411865 48.0,48.0 Z" />
-            <group
-                android:name="base" >
-                <path
-                    android:name="bar_path"
-                    android:pathData="M 480.0,48.0 c 0.0,26.5096740723 -21.4903259277,48.0 -48.0,48.0 c 0.0,0.0 -384.0,0.0 -384.0,0.0 c -26.5096740723,0.0 -48.0,-21.4903259277 -48.0,-48.0 c 0.0,-26.5096740723 21.4903259277,-48.0 48.0,-48.0 c 0.0,0.0 384.0,0.0 384.0,0.0 c 26.5096740723,0.0 48.0,21.4903259277 48.0,48.0 Z"
-                    android:fillColor="#FF029AE5" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/android-car-lib/res/drawable/speed_bump_scrim.xml b/android-car-lib/res/drawable/speed_bump_scrim.xml
deleted file mode 100644
index aacea49..0000000
--- a/android-car-lib/res/drawable/speed_bump_scrim.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle" >
-    <gradient
-        android:type="linear"
-        android:startColor="@android:color/transparent"
-        android:endColor="#8d000000"
-        android:angle="270"/>
-</shape>
diff --git a/android-car-lib/res/interpolator/speed_bump_interpolator.xml b/android-car-lib/res/interpolator/speed_bump_interpolator.xml
deleted file mode 100644
index ec7e694..0000000
--- a/android-car-lib/res/interpolator/speed_bump_interpolator.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<pathInterpolator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:pathData="M 0.0,0.0 c 1.0,0.535553908162 0.961348094524,0.999999995867 1.0,1.0" />
diff --git a/android-car-lib/res/layout/action_bar.xml b/android-car-lib/res/layout/action_bar.xml
deleted file mode 100644
index 431a2a8..0000000
--- a/android-car-lib/res/layout/action_bar.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<androidx.cardview.widget.CardView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/action_bar_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:elevation="@dimen/car_action_bar_elevation"
-    app:cardCornerRadius="@dimen/car_radius_3">
-
-    <LinearLayout
-        android:id="@+id/rows_container"
-        android:orientation="vertical"
-        android:animateLayoutChanges="true"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-        <LinearLayout
-            android:orientation="horizontal"
-            android:visibility="gone"
-            android:clipChildren="false"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_action_bar_height">
-        </LinearLayout>
-
-        <LinearLayout
-            android:orientation="horizontal"
-            android:clipChildren="false"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_action_bar_height">
-        </LinearLayout>
-
-    </LinearLayout>
-
-</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/android-car-lib/res/layout/action_bar_button.xml b/android-car-lib/res/layout/action_bar_button.xml
deleted file mode 100644
index e9d2370..0000000
--- a/android-car-lib/res/layout/action_bar_button.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<ImageButton style="@style/Widget.Car.Button.ActionBar" />
diff --git a/android-car-lib/res/layout/action_bar_slot.xml b/android-car-lib/res/layout/action_bar_slot.xml
deleted file mode 100644
index 804e356..0000000
--- a/android-car-lib/res/layout/action_bar_slot.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="0dp"
-    android:layout_height="@dimen/car_action_bar_button_height"
-    android:layout_weight="1"
-    android:visibility="visible"
-    android:foregroundGravity="center"
-    android:clipChildren="false"
-    android:foreground="@drawable/car_action_button_activated_ring_foreground">
-</FrameLayout>
\ No newline at end of file
diff --git a/android-car-lib/res/layout/car_alert_dialog.xml b/android-car-lib/res/layout/car_alert_dialog.xml
deleted file mode 100644
index d9b52a5..0000000
--- a/android-car-lib/res/layout/car_alert_dialog.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<!-- Note: the width is 0dp because ColumnCardView will automatically set a width based
-     on the number of columns it should take up. See ColumnCardView for more details. -->
-<androidx.car.widget.ColumnCardView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_gravity="center"
-    android:layout_width="0dp"
-    android:layout_height="wrap_content"
-    android:elevation="@dimen/car_dialog_elevation"
-    app:cardBackgroundColor="?attr/dialogBackgroundColor"
-    app:cardCornerRadius="@dimen/car_radius_3">
-
-    <LinearLayout
-        android:id="@+id/content_view"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_keyline_1"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        android:paddingTop="@dimen/car_padding_4"
-        android:paddingBottom="@dimen/car_padding_4"
-        android:orientation="vertical">
-
-        <TextView
-            android:id="@+id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="@dimen/car_dialog_header_height"
-            android:gravity="center_vertical|start"
-            android:visibility="gone"
-            style="?attr/dialogTitleStyle" />
-
-        <TextView
-            android:id="@+id/body"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            style="?attr/dialogBodyStyle" />
-
-        <LinearLayout
-            android:id="@+id/button_panel"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_dialog_action_bar_height"
-            android:layout_marginTop="@dimen/car_padding_2"
-            android:gravity="center_vertical"
-            android:orientation="horizontal"
-            android:visibility="gone">
-
-            <Button
-                android:id="@+id/positive_button"
-                android:layout_marginEnd="@dimen/car_padding_4"
-                android:layout_width="wrap_content"
-                android:minWidth="0dp"
-                android:padding="0dp"
-                android:textColor="@color/car_accent"
-                android:visibility="gone"
-                style="?attr/dialogButtonStyle" />
-
-            <Button
-                android:id="@+id/negative_button"
-                android:layout_width="wrap_content"
-                android:minWidth="0dp"
-                android:padding="0dp"
-                android:textColor="@color/car_accent"
-                android:visibility="gone"
-                style="?attr/dialogButtonStyle" />
-        </LinearLayout>
-    </LinearLayout>
-</androidx.car.widget.ColumnCardView>
diff --git a/android-car-lib/res/layout/car_drawer.xml b/android-car-lib/res/layout/car_drawer.xml
deleted file mode 100644
index 0629862..0000000
--- a/android-car-lib/res/layout/car_drawer.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<androidx.car.moderator.SpeedBumpView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/drawer_content"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginEnd="@dimen/car_drawer_margin_end"
-    android:background="?attr/drawerBackgroundColor"
-    android:paddingTop="@dimen/car_app_bar_height" >
-
-  <androidx.car.widget.PagedListView
-      android:id="@+id/drawer_list"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent"
-      app:listEndMargin="@dimen/car_drawer_margin_end"
-      app:gutter="start"
-      style="?attr/drawerListStyle" />
-
-  <ProgressBar
-      android:id="@+id/drawer_progress"
-      android:layout_width="@dimen/car_drawer_progress_bar_size"
-      android:layout_height="@dimen/car_drawer_progress_bar_size"
-      android:layout_gravity="center"
-      android:indeterminate="true"
-      android:visibility="gone" />
-</androidx.car.moderator.SpeedBumpView>
diff --git a/android-car-lib/res/layout/car_drawer_activity.xml b/android-car-lib/res/layout/car_drawer_activity.xml
deleted file mode 100644
index 1648d09..0000000
--- a/android-car-lib/res/layout/car_drawer_activity.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<androidx.coordinatorlayout.widget.CoordinatorLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <androidx.drawerlayout.widget.DrawerLayout
-        android:id="@+id/drawer_layout"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <!-- The main content view. Fragments will be added here. -->
-      <androidx.car.moderator.SpeedBumpView
-            android:id="@+id/content_frame"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
-
-        <include
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="start"
-            layout="@layout/car_drawer" />
-    </androidx.drawerlayout.widget.DrawerLayout>
-
-    <android.support.design.widget.AppBarLayout
-        android:id="@+id/appbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:fitsSystemWindows="true">
-        <!-- The min height of the Toolbar needs to be set to ensure that the icons in it
-             are vertically centered. -->
-        <androidx.car.widget.ClickThroughToolbar
-            android:id="@+id/car_toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/car_app_bar_height"
-            android:layout_gravity="center_vertical"
-            android:minHeight="@dimen/car_app_bar_height"
-            style="@style/Widget.Car.Toolbar" />
-    </android.support.design.widget.AppBarLayout>
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/android-car-lib/res/layout/car_drawer_list_item_empty.xml b/android-car-lib/res/layout/car_drawer_list_item_empty.xml
deleted file mode 100644
index d078a32..0000000
--- a/android-car-lib/res/layout/car_drawer_list_item_empty.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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:id="@+id/container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginStart="16dp"
-    android:focusable="false"
-    android:orientation="vertical"
-    android:background="@drawable/car_drawer_list_item_background" >
-    <FrameLayout
-        android:id="@+id/icon_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="visible">
-        <ImageView
-            android:id="@+id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginTop="48dp"
-            android:layout_marginBottom="22dp" />
-    </FrameLayout>
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="16dp"
-        android:gravity="center"
-        android:textAppearance="?attr/drawerItemTitleTextAppearance" />
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_drawer_list_item_normal.xml b/android-car-lib/res/layout/car_drawer_list_item_normal.xml
deleted file mode 100644
index a400c5a..0000000
--- a/android-car-lib/res/layout/car_drawer_list_item_normal.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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="@dimen/car_double_line_list_item_height"
-    android:focusable="true"
-    android:orientation="horizontal"
-    android:background="@drawable/car_drawer_list_item_background" >
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="@dimen/car_drawer_list_item_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_icon_size"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_icon_end_margin"
-        android:layout_gravity="center_vertical"
-        android:scaleType="centerCrop" />
-    <LinearLayout
-        android:id="@+id/text_container"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_gravity="center_vertical"
-        android:orientation="vertical" >
-        <TextView
-            android:id="@+id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/car_text_vertical_margin"
-            android:maxLines="1"
-            android:textAppearance="?attr/drawerItemTitleTextAppearance" />
-        <TextView
-            android:id="@+id/text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:maxLines="1"
-            android:textAppearance="?attr/drawerItemBodyTextAppearance" />
-    </LinearLayout>
-    <ImageView
-        android:id="@+id/end_icon"
-        android:layout_width="@dimen/car_drawer_list_item_end_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_end_icon_size"
-        android:scaleType="fitCenter"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_end_margin"
-        android:layout_gravity="center_vertical" />
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_drawer_list_item_small.xml b/android-car-lib/res/layout/car_drawer_list_item_small.xml
deleted file mode 100644
index 7ccf72b..0000000
--- a/android-car-lib/res/layout/car_drawer_list_item_small.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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="@dimen/car_single_line_list_item_height"
-    android:focusable="true"
-    android:orientation="horizontal"
-    android:background="@drawable/car_drawer_list_item_background" >
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="@dimen/car_drawer_list_item_small_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_small_icon_size"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_icon_end_margin"
-        android:layout_gravity="center_vertical"
-        android:scaleType="centerCrop" />
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_gravity="center_vertical"
-        android:layout_marginBottom="@dimen/car_text_vertical_margin"
-        android:maxLines="1"
-        android:textAppearance="?attr/drawerItemTitleTextAppearance" />
-    <ImageView
-        android:id="@+id/end_icon"
-        android:layout_width="@dimen/car_drawer_list_item_end_icon_size"
-        android:layout_height="@dimen/car_drawer_list_item_end_icon_size"
-        android:scaleType="fitCenter"
-        android:layout_marginEnd="@dimen/car_drawer_list_item_end_margin"
-        android:layout_gravity="center_vertical"/>
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_list_dialog.xml b/android-car-lib/res/layout/car_list_dialog.xml
deleted file mode 100644
index c3ff1bf..0000000
--- a/android-car-lib/res/layout/car_list_dialog.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/container"
-    android:background="@android:color/transparent"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" >
-
-    <!-- Note: the width is 0dp because ColumnCardView will automatically set a width based
-         on the number of columns it should take up. See ColumnCardView for more details. -->
-    <androidx.car.widget.ColumnCardView
-        android:layout_gravity="center"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/car_padding_4"
-        android:layout_marginBottom="@dimen/car_padding_4"
-        android:elevation="@dimen/car_dialog_elevation"
-        app:cardBackgroundColor="?attr/dialogBackgroundColor"
-        app:cardCornerRadius="@dimen/car_radius_3">
-
-        <!-- Hide the scrollbar for this PagedListView because it will be implemented by
-             @id/scrollbar. -->
-        <androidx.car.widget.PagedListView
-            android:id="@+id/list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:theme="?attr/dialogListTheme"
-            app:gutter="none"
-            app:dividerStartMargin="@dimen/car_keyline_1"
-            app:dividerEndMargin="@dimen/car_keyline_1"
-            app:showPagedListViewDivider="true"
-            app:scrollBarEnabled="false" />
-    </androidx.car.widget.ColumnCardView>
-
-    <!-- Putting this as the last child for highest z-index. It is also clickable to reduce
-         the chance of clicks on the buttons accidentally dismissing the dialog. -->
-    <androidx.car.widget.PagedScrollBarView
-        android:id="@+id/scrollbar"
-        android:layout_width="@dimen/car_margin"
-        android:layout_height="match_parent"
-        android:layout_marginTop="@dimen/car_padding_4"
-        android:layout_marginBottom="@dimen/car_padding_4"
-        android:layout_gravity="start|top"
-        android:clickable="true"
-        android:visibility="invisible" />
-</FrameLayout>
diff --git a/android-car-lib/res/layout/car_list_item_seekbar_content.xml b/android-car-lib/res/layout/car_list_item_seekbar_content.xml
deleted file mode 100644
index 2e3b165..0000000
--- a/android-car-lib/res/layout/car_list_item_seekbar_content.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2018 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.
-  -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/container"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent">
-
-    <!-- This layout should only be used by class SeekbarListItem, as it requires layout params
-         being set programmatically depending on item data/view configuration. -->
-
-    <!-- Primary Action. -->
-    <ImageView
-        android:id="@+id/primary_icon"
-        android:layout_width="@dimen/car_single_line_list_item_height"
-        android:layout_height="@dimen/car_single_line_list_item_height"/>
-
-    <!-- Slider and text. -->
-    <LinearLayout
-        android:id="@+id/seek_bar_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-        <TextView
-            android:id="@+id/text"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"/>
-        <SeekBar
-            android:id="@+id/seek_bar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:splitTrack="false"
-            style="@style/Widget.Car.SeekBar"/>
-    </LinearLayout>
-
-    <!-- Supplemental action. -->
-    <ImageView
-        android:id="@+id/supplemental_icon"
-        android:layout_width="@dimen/car_primary_icon_size"
-        android:layout_height="@dimen/car_primary_icon_size"
-        android:scaleType="fitCenter"/>
-    <View
-        android:id="@+id/supplemental_icon_divider"
-        android:layout_width="@dimen/car_vertical_line_divider_width"
-        android:layout_height="@dimen/car_vertical_line_divider_height"
-        android:background="@color/car_list_divider"/>
-</RelativeLayout>
diff --git a/android-car-lib/res/layout/car_list_item_text_content.xml b/android-car-lib/res/layout/car_list_item_text_content.xml
deleted file mode 100644
index a85a31e..0000000
--- a/android-car-lib/res/layout/car_list_item_text_content.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/container"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent"
-    android:foreground="@drawable/car_card_ripple_background">
-    <!-- Primary Action. -->
-    <ImageView
-        android:id="@+id/primary_icon"
-        android:layout_width="@dimen/car_single_line_list_item_height"
-        android:layout_height="@dimen/car_single_line_list_item_height"/>
-
-    <!-- Text. -->
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:singleLine="true"
-        android:ellipsize="end"/>
-    <TextView
-        android:id="@+id/body"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-
-    <!-- Supplemental action(s) - only one of the following groups should be visible. -->
-    <!-- End icon with divider. -->
-    <View
-        android:id="@+id/supplemental_icon_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/supplemental_icon"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <ImageView
-        android:id="@+id/supplemental_icon"
-        android:layout_centerVertical="true"
-        android:layout_width="@dimen/car_primary_icon_size"
-        android:layout_height="@dimen/car_primary_icon_size"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        android:scaleType="fitCenter"/>
-
-    <!-- Switch with divider. -->
-    <View
-        android:id="@+id/switch_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/switch_widget"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <Switch
-        android:id="@+id/switch_widget"
-        android:layout_centerVertical="true"
-        android:layout_width="@dimen/car_primary_icon_size"
-        android:layout_height="@dimen/car_primary_icon_size"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        style="@android:style/Widget.Material.CompoundButton.Switch"/>
-
-    <!-- Up to 2 action buttons with dividers. -->
-    <View
-        android:id="@+id/action2_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/action2"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <Button
-        android:id="@+id/action2"
-        android:layout_centerVertical="true"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_toStartOf="@id/action1_divider"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        android:ellipsize="end"
-        android:maxLength="@integer/car_borderless_button_text_length_limit"
-        android:maxLines="1"
-        android:background="@color/car_card"
-        android:foreground="@drawable/car_card_ripple_background"
-        style="?android:attr/borderlessButtonStyle"/>
-    <View
-        android:id="@+id/action1_divider"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/action1"
-        android:layout_marginEnd="@dimen/car_padding_4"
-        style="@style/CarListVerticalDivider"/>
-    <Button
-        android:id="@+id/action1"
-        android:layout_centerVertical="true"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="@dimen/car_keyline_1"
-        android:ellipsize="end"
-        android:maxLength="@integer/car_borderless_button_text_length_limit"
-        android:maxLines="1"
-        android:background="@color/car_card"
-        android:foreground="@drawable/car_card_ripple_background"
-        style="?android:attr/borderlessButtonStyle"/>
-</RelativeLayout>
diff --git a/android-car-lib/res/layout/car_paged_recycler_view.xml b/android-car-lib/res/layout/car_paged_recycler_view.xml
deleted file mode 100644
index 360d9a2..0000000
--- a/android-car-lib/res/layout/car_paged_recycler_view.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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.
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/recycler_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <!-- Putting this as the last child so that it can intercept any touch events on the
-         scroll buttons. -->
-    <androidx.car.widget.PagedScrollBarView
-        android:id="@+id/paged_scroll_view"
-        android:layout_width="@dimen/car_margin"
-        android:layout_height="match_parent"
-        android:paddingBottom="@dimen/car_padding_4"
-        android:paddingTop="@dimen/car_padding_4"
-        android:visibility="invisible" />
-</FrameLayout>
diff --git a/android-car-lib/res/layout/car_paged_scrollbar_buttons.xml b/android-car-lib/res/layout/car_paged_scrollbar_buttons.xml
deleted file mode 100644
index b126b48..0000000
--- a/android-car-lib/res/layout/car_paged_scrollbar_buttons.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2017 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="match_parent"
-    android:layout_gravity="center"
-    android:gravity="center"
-    android:orientation="vertical">
-
-    <ImageView
-        android:id="@+id/page_up"
-        android:layout_width="@dimen/car_scroll_bar_button_size"
-        android:layout_height="@dimen/car_scroll_bar_button_size"
-        android:background="@drawable/car_card_ripple_background"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/ic_up" />
-
-    <FrameLayout
-        android:id="@+id/filler"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:layout_marginBottom="@dimen/car_padding_2"
-        android:layout_marginTop="@dimen/car_padding_2" >
-
-        <View
-            android:id="@+id/scrollbar_thumb"
-            android:layout_width="@dimen/car_scroll_bar_thumb_width"
-            android:layout_height="0dp"
-            android:layout_gravity="center_horizontal"
-            android:background="@drawable/car_scrollbar_thumb" />
-    </FrameLayout>
-
-    <ImageView
-        android:id="@+id/page_down"
-        android:layout_width="@dimen/car_scroll_bar_button_size"
-        android:layout_height="@dimen/car_scroll_bar_button_size"
-        android:background="@drawable/car_card_ripple_background"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/ic_down" />
-</LinearLayout>
diff --git a/android-car-lib/res/layout/car_toolbar.xml b/android-car-lib/res/layout/car_toolbar.xml
deleted file mode 100644
index 3926896..0000000
--- a/android-car-lib/res/layout/car_toolbar.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/car_app_bar_height">
-    <androidx.appcompat.widget.Toolbar
-        android:id="@+id/car_toolbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        style="@style/Widget.Car.Toolbar" />
-</FrameLayout>
diff --git a/android-car-lib/res/layout/lock_out_message.xml b/android-car-lib/res/layout/lock_out_message.xml
deleted file mode 100644
index 220e1f3..0000000
--- a/android-car-lib/res/layout/lock_out_message.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/lock_out_message_container"
-    android:background="@drawable/speed_bump_scrim"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_gravity="bottom"
-    android:visibility="gone">
-
-    <ImageView
-        android:id="@+id/lock_out_drawable"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/speed_bump_lock_out_message_height"
-        android:layout_gravity="center"
-        android:layout_marginBottom="@dimen/speed_bump_lock_out_drawable_margin_bottom"
-        android:layout_alignParentBottom="true"
-        android:layout_centerHorizontal="true"
-        android:src="@drawable/lock_out_message_animation"/>
-
-    <!-- Align this TextView against the lock_out_drawable to ensure that the latter will wrap
-         this TextView. -->
-    <TextView
-        android:id="@+id/lock_out_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Car.Body1"
-        android:layout_alignStart="@id/lock_out_drawable"
-        android:layout_alignEnd="@id/lock_out_drawable"
-        android:layout_alignTop="@id/lock_out_drawable"
-        android:layout_alignBottom="@id/lock_out_drawable"
-        android:gravity="center"
-        android:text="@string/speed_bump_lockout_message"/>
-</RelativeLayout>
diff --git a/android-car-lib/res/values-af/values-af.xml b/android-car-lib/res/values-af/values-af.xml
deleted file mode 100644
index ed25d1d..0000000
--- a/android-car-lib/res/values-af/values-af.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Konsentreer op die pad"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-af/values.xml b/android-car-lib/res/values-af/values.xml
deleted file mode 100644
index 7990a8e..0000000
--- a/android-car-lib/res/values-af/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Vou knoppie in/uit"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Konsentreer op die pad"</string>
-</resources>
diff --git a/android-car-lib/res/values-am/values-am.xml b/android-car-lib/res/values-am/values-am.xml
deleted file mode 100644
index 529a04e..0000000
--- a/android-car-lib/res/values-am/values-am.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"መንገዱ ላይ ያተኩሩ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-am/values.xml b/android-car-lib/res/values-am/values.xml
deleted file mode 100644
index 8bd9ce9..0000000
--- a/android-car-lib/res/values-am/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"አዝራርን ዘርጋ/ሰብስብ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"መንገዱ ላይ ያተኩሩ"</string>
-</resources>
diff --git a/android-car-lib/res/values-ar/values-ar.xml b/android-car-lib/res/values-ar/values-ar.xml
deleted file mode 100644
index 3d64213..0000000
--- a/android-car-lib/res/values-ar/values-ar.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ركِّز في الطريق"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ar/values.xml b/android-car-lib/res/values-ar/values.xml
deleted file mode 100644
index a05692c..0000000
--- a/android-car-lib/res/values-ar/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"زر التوسيع/التصغير"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ركِّز في الطريق."</string>
-</resources>
diff --git a/android-car-lib/res/values-as/values.xml b/android-car-lib/res/values-as/values.xml
deleted file mode 100644
index db2bb2f..0000000
--- a/android-car-lib/res/values-as/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"সম্প্ৰসাৰণ/সংকোচন বুটাম"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"মনোযোগেৰে গাড়ী চলাওক"</string>
-</resources>
diff --git a/android-car-lib/res/values-az/values-az.xml b/android-car-lib/res/values-az/values-az.xml
deleted file mode 100644
index b5b0f12..0000000
--- a/android-car-lib/res/values-az/values-az.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Diqqətinizi yola yönəldin"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-az/values.xml b/android-car-lib/res/values-az/values.xml
deleted file mode 100644
index 822f446..0000000
--- a/android-car-lib/res/values-az/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Düyməni genişləndirin/yığcamlaşdırın"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Diqqətinizi yola yönəldin"</string>
-</resources>
diff --git a/android-car-lib/res/values-b+sr+Latn/values-b+sr+Latn.xml b/android-car-lib/res/values-b+sr+Latn/values-b+sr+Latn.xml
deleted file mode 100644
index 97332eb..0000000
--- a/android-car-lib/res/values-b+sr+Latn/values-b+sr+Latn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokusirajte se na put"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-b+sr+Latn/values.xml b/android-car-lib/res/values-b+sr+Latn/values.xml
deleted file mode 100644
index 1da562a..0000000
--- a/android-car-lib/res/values-b+sr+Latn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Dugme Proširi/skupi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokusirajte se na put"</string>
-</resources>
diff --git a/android-car-lib/res/values-be/values-be.xml b/android-car-lib/res/values-be/values-be.xml
deleted file mode 100644
index cd54ef9..0000000
--- a/android-car-lib/res/values-be/values-be.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Увага на дарогу"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-be/values.xml b/android-car-lib/res/values-be/values.xml
deleted file mode 100644
index a33ac9b..0000000
--- a/android-car-lib/res/values-be/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Кнопка \"Разгарнуць/згарнуць\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Увага на дарогу"</string>
-</resources>
diff --git a/android-car-lib/res/values-bg/values-bg.xml b/android-car-lib/res/values-bg/values-bg.xml
deleted file mode 100644
index 90f73ad..0000000
--- a/android-car-lib/res/values-bg/values-bg.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Съсредоточете се върху пътя"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-bg/values.xml b/android-car-lib/res/values-bg/values.xml
deleted file mode 100644
index 18a283d..0000000
--- a/android-car-lib/res/values-bg/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Бутон за разгъване/свиване"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Съсредоточете се върху пътя"</string>
-</resources>
diff --git a/android-car-lib/res/values-bn/values-bn.xml b/android-car-lib/res/values-bn/values-bn.xml
deleted file mode 100644
index 8a7d235..0000000
--- a/android-car-lib/res/values-bn/values-bn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"মনোযোগ দিয়ে গাড়ি চালান"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-bn/values.xml b/android-car-lib/res/values-bn/values.xml
deleted file mode 100644
index ad4f5a0..0000000
--- a/android-car-lib/res/values-bn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"বোতামটি বড় করুন/আড়াল করুন"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"মনোযোগ দিয়ে গাড়ি চালান"</string>
-</resources>
diff --git a/android-car-lib/res/values-bs/values-bs.xml b/android-car-lib/res/values-bs/values-bs.xml
deleted file mode 100644
index 5cb1759..0000000
--- a/android-car-lib/res/values-bs/values-bs.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokusirajte se na cestu"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-bs/values.xml b/android-car-lib/res/values-bs/values.xml
deleted file mode 100644
index f9b4431..0000000
--- a/android-car-lib/res/values-bs/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Dugme proširi/suzi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokusirajte se na cestu"</string>
-</resources>
diff --git a/android-car-lib/res/values-ca/values-ca.xml b/android-car-lib/res/values-ca/values-ca.xml
deleted file mode 100644
index 2c1c31a..0000000
--- a/android-car-lib/res/values-ca/values-ca.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentra\'t en la carretera"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ca/values.xml b/android-car-lib/res/values-ca/values.xml
deleted file mode 100644
index c9133a5..0000000
--- a/android-car-lib/res/values-ca/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botó per desplegar o replegar"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentra\'t en la carretera"</string>
-</resources>
diff --git a/android-car-lib/res/values-cs/values-cs.xml b/android-car-lib/res/values-cs/values-cs.xml
deleted file mode 100644
index 7bd877c..0000000
--- a/android-car-lib/res/values-cs/values-cs.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Soustřeďte se na silnici"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-cs/values.xml b/android-car-lib/res/values-cs/values.xml
deleted file mode 100644
index aad6789..0000000
--- a/android-car-lib/res/values-cs/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Tlačítko rozbalení/sbalení"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Soustřeďte se na silnici"</string>
-</resources>
diff --git a/android-car-lib/res/values-da/values-da.xml b/android-car-lib/res/values-da/values-da.xml
deleted file mode 100644
index 54f7632..0000000
--- a/android-car-lib/res/values-da/values-da.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Hold øjnene på vejen"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-da/values.xml b/android-car-lib/res/values-da/values.xml
deleted file mode 100644
index fb82413..0000000
--- a/android-car-lib/res/values-da/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Knappen Udvid/skjul"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Hold øjnene på vejen"</string>
-</resources>
diff --git a/android-car-lib/res/values-de/values-de.xml b/android-car-lib/res/values-de/values-de.xml
deleted file mode 100644
index d0a35b5..0000000
--- a/android-car-lib/res/values-de/values-de.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Achte auf den Verkehr"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-de/values.xml b/android-car-lib/res/values-de/values.xml
deleted file mode 100644
index fb8e1c5..0000000
--- a/android-car-lib/res/values-de/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Schaltfläche zum Maximieren/Minimieren"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Achte auf den Verkehr"</string>
-</resources>
diff --git a/android-car-lib/res/values-el/values-el.xml b/android-car-lib/res/values-el/values-el.xml
deleted file mode 100644
index 52758b1..0000000
--- a/android-car-lib/res/values-el/values-el.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Επικεντρωθείτε στον δρόμο"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-el/values.xml b/android-car-lib/res/values-el/values.xml
deleted file mode 100644
index e17e8f4..0000000
--- a/android-car-lib/res/values-el/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Κουμπί ανάπτυξης/σύμπτυξης"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Επικεντρωθείτε στον δρόμο"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rAU/values-en-rAU.xml b/android-car-lib/res/values-en-rAU/values-en-rAU.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rAU/values-en-rAU.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rAU/values.xml b/android-car-lib/res/values-en-rAU/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rAU/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rCA/values-en-rCA.xml b/android-car-lib/res/values-en-rCA/values-en-rCA.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rCA/values-en-rCA.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rCA/values.xml b/android-car-lib/res/values-en-rCA/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rCA/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rGB/values-en-rGB.xml b/android-car-lib/res/values-en-rGB/values-en-rGB.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rGB/values-en-rGB.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rGB/values.xml b/android-car-lib/res/values-en-rGB/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rGB/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rIN/values-en-rIN.xml b/android-car-lib/res/values-en-rIN/values-en-rIN.xml
deleted file mode 100644
index 14ebe5f..0000000
--- a/android-car-lib/res/values-en-rIN/values-en-rIN.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Focus on the road"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rIN/values.xml b/android-car-lib/res/values-en-rIN/values.xml
deleted file mode 100644
index b950788..0000000
--- a/android-car-lib/res/values-en-rIN/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Expand/collapse button"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Focus on the road"</string>
-</resources>
diff --git a/android-car-lib/res/values-en-rXC/values-en-rXC.xml b/android-car-lib/res/values-en-rXC/values-en-rXC.xml
deleted file mode 100644
index 2644d8a..0000000
--- a/android-car-lib/res/values-en-rXC/values-en-rXC.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎Focus on the road‎‏‎‎‏‎"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-en-rXC/values.xml b/android-car-lib/res/values-en-rXC/values.xml
deleted file mode 100644
index 1d1d116..0000000
--- a/android-car-lib/res/values-en-rXC/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎Expand/collapse button‎‏‎‎‏‎"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎Focus on the road‎‏‎‎‏‎"</string>
-</resources>
diff --git a/android-car-lib/res/values-es-rUS/values-es-rUS.xml b/android-car-lib/res/values-es-rUS/values-es-rUS.xml
deleted file mode 100644
index e5ecf44..0000000
--- a/android-car-lib/res/values-es-rUS/values-es-rUS.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concéntrate en el camino"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-es-rUS/values.xml b/android-car-lib/res/values-es-rUS/values.xml
deleted file mode 100644
index 0a3e9a8..0000000
--- a/android-car-lib/res/values-es-rUS/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botón Expandir/contraer"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concéntrate en el camino"</string>
-</resources>
diff --git a/android-car-lib/res/values-es/values-es.xml b/android-car-lib/res/values-es/values-es.xml
deleted file mode 100644
index 2af260c..0000000
--- a/android-car-lib/res/values-es/values-es.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Céntrate en la carretera"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-es/values.xml b/android-car-lib/res/values-es/values.xml
deleted file mode 100644
index a175812..0000000
--- a/android-car-lib/res/values-es/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botón para mostrar u ocultar"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Céntrate en la carretera"</string>
-</resources>
diff --git a/android-car-lib/res/values-et/values-et.xml b/android-car-lib/res/values-et/values-et.xml
deleted file mode 100644
index 30fce07..0000000
--- a/android-car-lib/res/values-et/values-et.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Keskenduge teele"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-et/values.xml b/android-car-lib/res/values-et/values.xml
deleted file mode 100644
index 18e9283..0000000
--- a/android-car-lib/res/values-et/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Nupp Laienda/Ahenda"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Keskenduge teele"</string>
-</resources>
diff --git a/android-car-lib/res/values-eu/values-eu.xml b/android-car-lib/res/values-eu/values-eu.xml
deleted file mode 100644
index 65513d4..0000000
--- a/android-car-lib/res/values-eu/values-eu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Jarri arreta errepidean"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-eu/values.xml b/android-car-lib/res/values-eu/values.xml
deleted file mode 100644
index 4e2c741..0000000
--- a/android-car-lib/res/values-eu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Zabaltzeko/Tolesteko botoia"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Jarri arreta errepidean"</string>
-</resources>
diff --git a/android-car-lib/res/values-fa/values-fa.xml b/android-car-lib/res/values-fa/values-fa.xml
deleted file mode 100644
index f683363..0000000
--- a/android-car-lib/res/values-fa/values-fa.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"روی جاده تمرکز داشته باشید"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fa/values.xml b/android-car-lib/res/values-fa/values.xml
deleted file mode 100644
index 319b857..0000000
--- a/android-car-lib/res/values-fa/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"دکمه بزرگ کردن/کوچک کردن"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"روی جاده تمرکز داشته باشید"</string>
-</resources>
diff --git a/android-car-lib/res/values-fi/values-fi.xml b/android-car-lib/res/values-fi/values-fi.xml
deleted file mode 100644
index b7223be..0000000
--- a/android-car-lib/res/values-fi/values-fi.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Pidä katse tiessä"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fi/values.xml b/android-car-lib/res/values-fi/values.xml
deleted file mode 100644
index 7e917d2..0000000
--- a/android-car-lib/res/values-fi/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Laajennus- ja tiivistyspainike"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Pidä katse tiessä"</string>
-</resources>
diff --git a/android-car-lib/res/values-fr-rCA/values-fr-rCA.xml b/android-car-lib/res/values-fr-rCA/values-fr-rCA.xml
deleted file mode 100644
index 79e44c5..0000000
--- a/android-car-lib/res/values-fr-rCA/values-fr-rCA.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrez-vous sur la route"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fr-rCA/values.xml b/android-car-lib/res/values-fr-rCA/values.xml
deleted file mode 100644
index e44d8cb..0000000
--- a/android-car-lib/res/values-fr-rCA/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Bouton Développer/Réduire"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrez-vous sur la route"</string>
-</resources>
diff --git a/android-car-lib/res/values-fr/values-fr.xml b/android-car-lib/res/values-fr/values-fr.xml
deleted file mode 100644
index 79e44c5..0000000
--- a/android-car-lib/res/values-fr/values-fr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrez-vous sur la route"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-fr/values.xml b/android-car-lib/res/values-fr/values.xml
deleted file mode 100644
index e44d8cb..0000000
--- a/android-car-lib/res/values-fr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Bouton Développer/Réduire"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrez-vous sur la route"</string>
-</resources>
diff --git a/android-car-lib/res/values-gl/values-gl.xml b/android-car-lib/res/values-gl/values-gl.xml
deleted file mode 100644
index d024b93..0000000
--- a/android-car-lib/res/values-gl/values-gl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Céntrate na estrada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-gl/values.xml b/android-car-lib/res/values-gl/values.xml
deleted file mode 100644
index 9b09422..0000000
--- a/android-car-lib/res/values-gl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botón despregar/contraer"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Céntrate na estrada"</string>
-</resources>
diff --git a/android-car-lib/res/values-gu/values-gu.xml b/android-car-lib/res/values-gu/values-gu.xml
deleted file mode 100644
index 6b0f8d5..0000000
--- a/android-car-lib/res/values-gu/values-gu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"રસ્તા પર ફોકસ કરો"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-gu/values.xml b/android-car-lib/res/values-gu/values.xml
deleted file mode 100644
index 8735563..0000000
--- a/android-car-lib/res/values-gu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"વિસ્તાર કરો/સંકુચિત કરો બટન"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"રસ્તા પર ફોકસ કરો"</string>
-</resources>
diff --git a/android-car-lib/res/values-h1752dp-v13/values-h1752dp-v13.xml b/android-car-lib/res/values-h1752dp-v13/values-h1752dp-v13.xml
deleted file mode 100644
index 9eb87ed..0000000
--- a/android-car-lib/res/values-h1752dp-v13/values-h1752dp-v13.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_action1_size">32sp</dimen>
-    <dimen name="car_app_bar_height">112dp</dimen>
-    <dimen name="car_avatar_size">96dp</dimen>
-    <dimen name="car_body1_size">40sp</dimen>
-    <dimen name="car_body2_size">32sp</dimen>
-    <dimen name="car_card_action_bar_height">96dp</dimen>
-    <dimen name="car_card_header_height">96dp</dimen>
-    <dimen name="car_headline1_size">56sp</dimen>
-    <dimen name="car_headline2_size">50sp</dimen>
-    <dimen name="car_label1_size">32sp</dimen>
-    <dimen name="car_primary_icon_size">56dp</dimen>
-    <dimen name="car_secondary_icon_size">36dp</dimen>
-    <dimen name="car_single_line_list_item_height">128dp</dimen>
-    <dimen name="car_slide_up_menu_initial_height">128dp</dimen>
-    <dimen name="car_sub_header_height">96dp</dimen>
-    <dimen name="car_title2_size">40sp</dimen>
-    <dimen name="car_touch_target_size">96dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-h668dp-v13/values-h668dp-v13.xml b/android-car-lib/res/values-h668dp-v13/values-h668dp-v13.xml
deleted file mode 100644
index 127e094..0000000
--- a/android-car-lib/res/values-h668dp-v13/values-h668dp-v13.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_app_bar_height">96dp</dimen>
-    <dimen name="car_drawer_list_item_end_icon_size">56dp</dimen>
-    <dimen name="car_drawer_list_item_icon_size">108dp</dimen>
-    <dimen name="car_drawer_list_item_small_icon_size">56dp</dimen>
-    <dimen name="car_headline2_size">36sp</dimen>
-    <dimen name="car_padding_2">16dp</dimen>
-    <dimen name="car_padding_3">28dp</dimen>
-    <dimen name="car_padding_4">32dp</dimen>
-    <dimen name="car_padding_5">64dp</dimen>
-    <dimen name="car_padding_6">96dp</dimen>
-    <dimen name="car_scroll_bar_button_size">76dp</dimen>
-    <dimen name="car_single_line_list_item_height">116dp</dimen>
-    <dimen name="car_slide_up_menu_initial_height">116dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hi/values-hi.xml b/android-car-lib/res/values-hi/values-hi.xml
deleted file mode 100644
index 5430f04..0000000
--- a/android-car-lib/res/values-hi/values-hi.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"सड़क पर ध्यान दें"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hi/values.xml b/android-car-lib/res/values-hi/values.xml
deleted file mode 100644
index d2cb5f8..0000000
--- a/android-car-lib/res/values-hi/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"बड़ा/छोटा करने वाला बटन"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"सड़क पर ध्यान दें"</string>
-</resources>
diff --git a/android-car-lib/res/values-hr/values-hr.xml b/android-car-lib/res/values-hr/values-hr.xml
deleted file mode 100644
index dc7be15..0000000
--- a/android-car-lib/res/values-hr/values-hr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Usredotočite se na cestu"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hr/values.xml b/android-car-lib/res/values-hr/values.xml
deleted file mode 100644
index d279d04..0000000
--- a/android-car-lib/res/values-hr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Gumb za proširivanje/sažimanje"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Usredotočite se na cestu"</string>
-</resources>
diff --git a/android-car-lib/res/values-hu/values-hu.xml b/android-car-lib/res/values-hu/values-hu.xml
deleted file mode 100644
index 1e7ff2c..0000000
--- a/android-car-lib/res/values-hu/values-hu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Figyeljen az útra"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hu/values.xml b/android-car-lib/res/values-hu/values.xml
deleted file mode 100644
index e009ab8..0000000
--- a/android-car-lib/res/values-hu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Gomb kibontása/összecsukása"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Figyeljen az útra"</string>
-</resources>
diff --git a/android-car-lib/res/values-hy/values-hy.xml b/android-car-lib/res/values-hy/values-hy.xml
deleted file mode 100644
index 54ba33e..0000000
--- a/android-car-lib/res/values-hy/values-hy.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Հետևեք ճանապարհին"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-hy/values.xml b/android-car-lib/res/values-hy/values.xml
deleted file mode 100644
index 05a225d..0000000
--- a/android-car-lib/res/values-hy/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"«Ընդարձակել/ծալել» կոճակ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Հետևեք ճանապարհին"</string>
-</resources>
diff --git a/android-car-lib/res/values-in/values-in.xml b/android-car-lib/res/values-in/values-in.xml
deleted file mode 100644
index 25b10ed..0000000
--- a/android-car-lib/res/values-in/values-in.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Konsentrasi saat mengemudi"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-in/values.xml b/android-car-lib/res/values-in/values.xml
deleted file mode 100644
index 33e98c8..0000000
--- a/android-car-lib/res/values-in/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Tombol luaskan/ciutkan"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Konsentrasi saat mengemudi"</string>
-</resources>
diff --git a/android-car-lib/res/values-is/values-is.xml b/android-car-lib/res/values-is/values-is.xml
deleted file mode 100644
index c48d73b..0000000
--- a/android-car-lib/res/values-is/values-is.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Einbeittu þér að akstrinum"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-is/values.xml b/android-car-lib/res/values-is/values.xml
deleted file mode 100644
index 8db74e8..0000000
--- a/android-car-lib/res/values-is/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Hnappur til að stækka/minnka"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Einbeittu þér að akstrinum"</string>
-</resources>
diff --git a/android-car-lib/res/values-it/values-it.xml b/android-car-lib/res/values-it/values-it.xml
deleted file mode 100644
index 64780ad..0000000
--- a/android-car-lib/res/values-it/values-it.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrati sulla strada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-it/values.xml b/android-car-lib/res/values-it/values.xml
deleted file mode 100644
index 42e9fb6..0000000
--- a/android-car-lib/res/values-it/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Pulsante Espandi/Comprimi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrati sulla strada"</string>
-</resources>
diff --git a/android-car-lib/res/values-iw/values-iw.xml b/android-car-lib/res/values-iw/values-iw.xml
deleted file mode 100644
index 3af92b7..0000000
--- a/android-car-lib/res/values-iw/values-iw.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"עליך להתמקד בכביש"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-iw/values.xml b/android-car-lib/res/values-iw/values.xml
deleted file mode 100644
index 9a5d0d9..0000000
--- a/android-car-lib/res/values-iw/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"לחצן הרחבה וכיווץ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"עליך להתמקד בכביש"</string>
-</resources>
diff --git a/android-car-lib/res/values-ja/values-ja.xml b/android-car-lib/res/values-ja/values-ja.xml
deleted file mode 100644
index 598f61f..0000000
--- a/android-car-lib/res/values-ja/values-ja.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"運転に集中してください"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ja/values.xml b/android-car-lib/res/values-ja/values.xml
deleted file mode 100644
index 004bc89..0000000
--- a/android-car-lib/res/values-ja/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"展開 / 折りたたみボタン"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"運転に集中してください"</string>
-</resources>
diff --git a/android-car-lib/res/values-ka/values-ka.xml b/android-car-lib/res/values-ka/values-ka.xml
deleted file mode 100644
index 0e5a161..0000000
--- a/android-car-lib/res/values-ka/values-ka.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"კონცენტრირდით გზაზე"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ka/values.xml b/android-car-lib/res/values-ka/values.xml
deleted file mode 100644
index fa26c0c..0000000
--- a/android-car-lib/res/values-ka/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ღილაკის გაშლა/ჩაკეცვა"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"კონცენტრირდით გზაზე"</string>
-</resources>
diff --git a/android-car-lib/res/values-kk/values-kk.xml b/android-car-lib/res/values-kk/values-kk.xml
deleted file mode 100644
index b70f1db..0000000
--- a/android-car-lib/res/values-kk/values-kk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Жолға назар аударыңыз"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-kk/values.xml b/android-car-lib/res/values-kk/values.xml
deleted file mode 100644
index a90524b..0000000
--- a/android-car-lib/res/values-kk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"\"Жаю/Жию\" түймесі"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Жолға назар аударыңыз"</string>
-</resources>
diff --git a/android-car-lib/res/values-km/values-km.xml b/android-car-lib/res/values-km/values-km.xml
deleted file mode 100644
index b550049..0000000
--- a/android-car-lib/res/values-km/values-km.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ផ្តោតលើ​ការបើកបរ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-km/values.xml b/android-car-lib/res/values-km/values.xml
deleted file mode 100644
index 8fc71c6..0000000
--- a/android-car-lib/res/values-km/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ប៊ូតុង​ពង្រីក/បង្រួម"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ផ្តោតលើ​ការបើកបរ"</string>
-</resources>
diff --git a/android-car-lib/res/values-kn/values-kn.xml b/android-car-lib/res/values-kn/values-kn.xml
deleted file mode 100644
index cf77bf0..0000000
--- a/android-car-lib/res/values-kn/values-kn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ರಸ್ತೆಯ ಮೇಲೆ ಗಮನಹರಿಸಿ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-kn/values.xml b/android-car-lib/res/values-kn/values.xml
deleted file mode 100644
index dea965f..0000000
--- a/android-car-lib/res/values-kn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ವಿಸ್ತರಿಸಿ/ಕುಗ್ಗಿಸಿ ಬಟನ್"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ರಸ್ತೆಯ ಮೇಲೆ ಗಮನಹರಿಸಿ"</string>
-</resources>
diff --git a/android-car-lib/res/values-ko/values-ko.xml b/android-car-lib/res/values-ko/values-ko.xml
deleted file mode 100644
index 5564a12..0000000
--- a/android-car-lib/res/values-ko/values-ko.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"도로 상황에 집중하세요."</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ko/values.xml b/android-car-lib/res/values-ko/values.xml
deleted file mode 100644
index 62f39d1..0000000
--- a/android-car-lib/res/values-ko/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"펼치기/접기 버튼"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"도로 상황에 집중하세요."</string>
-</resources>
diff --git a/android-car-lib/res/values-ky/values-ky.xml b/android-car-lib/res/values-ky/values-ky.xml
deleted file mode 100644
index eb5b9dc..0000000
--- a/android-car-lib/res/values-ky/values-ky.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Жолго көңүл буруңуз"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ky/values.xml b/android-car-lib/res/values-ky/values.xml
deleted file mode 100644
index 5a48f45..0000000
--- a/android-car-lib/res/values-ky/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Жайып көрсөтүү/жыйыштыруу баскычы"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Жолго көңүл буруңуз"</string>
-</resources>
diff --git a/android-car-lib/res/values-lo/values-lo.xml b/android-car-lib/res/values-lo/values-lo.xml
deleted file mode 100644
index 332f827..0000000
--- a/android-car-lib/res/values-lo/values-lo.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ຕັ້ງໃຈຂັບລົດ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-lo/values.xml b/android-car-lib/res/values-lo/values.xml
deleted file mode 100644
index 96a8c09..0000000
--- a/android-car-lib/res/values-lo/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ປຸ່ມຂະຫຍາຍ/ຫຍໍ້ລົງ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ຕັ້ງໃຈຂັບລົດ"</string>
-</resources>
diff --git a/android-car-lib/res/values-lt/values-lt.xml b/android-car-lib/res/values-lt/values-lt.xml
deleted file mode 100644
index cad45a9..0000000
--- a/android-car-lib/res/values-lt/values-lt.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Sutelkite dėmesį į kelią"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-lt/values.xml b/android-car-lib/res/values-lt/values.xml
deleted file mode 100644
index d77e8b0..0000000
--- a/android-car-lib/res/values-lt/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Mygtukas „Išskleisti / sutraukti“"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Sutelkite dėmesį į kelią"</string>
-</resources>
diff --git a/android-car-lib/res/values-lv/values-lv.xml b/android-car-lib/res/values-lv/values-lv.xml
deleted file mode 100644
index fa8b02b..0000000
--- a/android-car-lib/res/values-lv/values-lv.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Pievērsieties autovadīšanai"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-lv/values.xml b/android-car-lib/res/values-lv/values.xml
deleted file mode 100644
index a29444b..0000000
--- a/android-car-lib/res/values-lv/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Izvēršanas/sakļaušanas poga"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Pievērsieties ceļam"</string>
-</resources>
diff --git a/android-car-lib/res/values-mk/values-mk.xml b/android-car-lib/res/values-mk/values-mk.xml
deleted file mode 100644
index a1fec3e..0000000
--- a/android-car-lib/res/values-mk/values-mk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Фокусирајте се на патот"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-mk/values.xml b/android-car-lib/res/values-mk/values.xml
deleted file mode 100644
index ae4ceb5..0000000
--- a/android-car-lib/res/values-mk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Копче за проширување/собирање"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Фокусирајте се на патот"</string>
-</resources>
diff --git a/android-car-lib/res/values-ml/values-ml.xml b/android-car-lib/res/values-ml/values-ml.xml
deleted file mode 100644
index 0301e61..0000000
--- a/android-car-lib/res/values-ml/values-ml.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"റോഡിൽ ശ്രദ്ധിക്കുക"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ml/values.xml b/android-car-lib/res/values-ml/values.xml
deleted file mode 100644
index 5399293..0000000
--- a/android-car-lib/res/values-ml/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"വികസിപ്പിക്കുക/ചുരുക്കുക ബട്ടൺ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"റോഡിൽ ശ്രദ്ധിക്കുക"</string>
-</resources>
diff --git a/android-car-lib/res/values-mn/values-mn.xml b/android-car-lib/res/values-mn/values-mn.xml
deleted file mode 100644
index 3d2a53f..0000000
--- a/android-car-lib/res/values-mn/values-mn.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Зам дээр төвлөрөх"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-mn/values.xml b/android-car-lib/res/values-mn/values.xml
deleted file mode 100644
index abe78f1..0000000
--- a/android-car-lib/res/values-mn/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Дэлгэх/буулгах товчлуур"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Зам дээр анхаарлаа төвлөрүүлэх"</string>
-</resources>
diff --git a/android-car-lib/res/values-mr/values-mr.xml b/android-car-lib/res/values-mr/values-mr.xml
deleted file mode 100644
index 9f9dfa7..0000000
--- a/android-car-lib/res/values-mr/values-mr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"रस्त्यावर फोकस करा"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-mr/values.xml b/android-car-lib/res/values-mr/values.xml
deleted file mode 100644
index 77e890f..0000000
--- a/android-car-lib/res/values-mr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"बटण विस्‍तृत करा/कोलॅप्‍स करा"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"रस्त्यावर फोकस करा"</string>
-</resources>
diff --git a/android-car-lib/res/values-ms/values-ms.xml b/android-car-lib/res/values-ms/values-ms.xml
deleted file mode 100644
index f5e24b5..0000000
--- a/android-car-lib/res/values-ms/values-ms.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Beri tumpuan pada jalan raya"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ms/values.xml b/android-car-lib/res/values-ms/values.xml
deleted file mode 100644
index d04485b..0000000
--- a/android-car-lib/res/values-ms/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Butang kembangkan/runtuhkan"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Beri tumpuan pada jalan raya"</string>
-</resources>
diff --git a/android-car-lib/res/values-my/values-my.xml b/android-car-lib/res/values-my/values-my.xml
deleted file mode 100644
index 617468e..0000000
--- a/android-car-lib/res/values-my/values-my.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"လမ်းကို အာရုံစိုက်ရန်"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-my/values.xml b/android-car-lib/res/values-my/values.xml
deleted file mode 100644
index be8c9fc..0000000
--- a/android-car-lib/res/values-my/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ချဲ့ရန်/လျှော့ပြရန် ခလုတ်"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"လမ်းပေါ်တွင် အာရုံစိုက်ပါ"</string>
-</resources>
diff --git a/android-car-lib/res/values-nb/values-nb.xml b/android-car-lib/res/values-nb/values-nb.xml
deleted file mode 100644
index 7f50f78..0000000
--- a/android-car-lib/res/values-nb/values-nb.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokuser på veien"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-nb/values.xml b/android-car-lib/res/values-nb/values.xml
deleted file mode 100644
index 5575a1a..0000000
--- a/android-car-lib/res/values-nb/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Vis/skjul-knapp"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokuser på veien"</string>
-</resources>
diff --git a/android-car-lib/res/values-ne/values-ne.xml b/android-car-lib/res/values-ne/values-ne.xml
deleted file mode 100644
index 91acb81..0000000
--- a/android-car-lib/res/values-ne/values-ne.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"सडकमा ध्यान केन्द्रित गर्नु…"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ne/values.xml b/android-car-lib/res/values-ne/values.xml
deleted file mode 100644
index b366be2..0000000
--- a/android-car-lib/res/values-ne/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"विस्तृत/संक्षिप्त गर्ने बटन"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"सडकमा ध्यान केन्द्रित गर्नुहोस्"</string>
-</resources>
diff --git a/android-car-lib/res/values-night-v8/values-night-v8.xml b/android-car-lib/res/values-night-v8/values-night-v8.xml
deleted file mode 100644
index e9a243a..0000000
--- a/android-car-lib/res/values-night-v8/values-night-v8.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="car_accent">@color/car_accent_light</color>
-    <color name="car_action1">@color/car_action1_light</color>
-    <color name="car_body1">@color/car_body1_light</color>
-    <color name="car_body2">@color/car_body2_light</color>
-    <color name="car_body3">@color/car_body3_light</color>
-    <color name="car_body4">@color/car_body4_light</color>
-    <color name="car_card">@color/car_card_dark</color>
-    <color name="car_card_inverse">@color/car_card_light</color>
-    <color name="car_card_ripple_background">@color/car_card_ripple_background_light</color>
-    <color name="car_card_ripple_background_inverse">@color/car_card_ripple_background_dark</color>
-    <color name="car_headline1">@color/car_headline1_light</color>
-    <color name="car_headline2">@color/car_headline2_light</color>
-    <color name="car_headline3">@color/car_headline3_light</color>
-    <color name="car_headline4">@color/car_headline4_light</color>
-    <color name="car_label1">@color/car_label1_light</color>
-    <color name="car_list_divider">@color/car_list_divider_light</color>
-    <color name="car_list_divider_inverse">@color/car_list_divider_dark</color>
-    <color name="car_scrollbar_thumb">@color/car_scrollbar_thumb_light</color>
-    <color name="car_scrollbar_thumb_inverse">@color/car_scrollbar_thumb_dark</color>
-    <color name="car_tint">@color/car_tint_light</color>
-    <color name="car_tint_inverse">@color/car_tint_dark</color>
-    <color name="car_title">@color/car_title_light</color>
-    <color name="car_title2">@color/car_title2_light</color>
-    <color name="speed_bump_background">#FF4C4C4C</color>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-nl/values-nl.xml b/android-car-lib/res/values-nl/values-nl.xml
deleted file mode 100644
index 756b53d..0000000
--- a/android-car-lib/res/values-nl/values-nl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Houd je aandacht op de weg"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-nl/values.xml b/android-car-lib/res/values-nl/values.xml
deleted file mode 100644
index de8f173..0000000
--- a/android-car-lib/res/values-nl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Knop voor uitvouwen/samenvouwen"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Houd je aandacht op de weg"</string>
-</resources>
diff --git a/android-car-lib/res/values-or/values.xml b/android-car-lib/res/values-or/values.xml
deleted file mode 100644
index 1836305..0000000
--- a/android-car-lib/res/values-or/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ବିସ୍ତାର/ସଂକୋଚନ ବଟନ୍"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ରାସ୍ତା ଉପରେ ଧ୍ୟାନରଖନ୍ତୁ"</string>
-</resources>
diff --git a/android-car-lib/res/values-pa/values-pa.xml b/android-car-lib/res/values-pa/values-pa.xml
deleted file mode 100644
index 8aec306..0000000
--- a/android-car-lib/res/values-pa/values-pa.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"ਸੜਕ \'ਤੇ ਧਿਆਨ ਦਿਓ"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pa/values.xml b/android-car-lib/res/values-pa/values.xml
deleted file mode 100644
index c4369d3..0000000
--- a/android-car-lib/res/values-pa/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ਵਿਸਤਾਰ ਕਰੋ ਜਾਂ ਸਮੇਟੋ ਬਟਨ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"ਸੜਕ \'ਤੇ ਧਿਆਨ ਦਿਓ"</string>
-</resources>
diff --git a/android-car-lib/res/values-pl/values-pl.xml b/android-car-lib/res/values-pl/values-pl.xml
deleted file mode 100644
index 32a3af6..0000000
--- a/android-car-lib/res/values-pl/values-pl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Skup się na drodze"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pl/values.xml b/android-car-lib/res/values-pl/values.xml
deleted file mode 100644
index 0373349..0000000
--- a/android-car-lib/res/values-pl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Przycisk zwijania/rozwijania"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Skup się na drodze"</string>
-</resources>
diff --git a/android-car-lib/res/values-pt-rBR/values-pt-rBR.xml b/android-car-lib/res/values-pt-rBR/values-pt-rBR.xml
deleted file mode 100644
index 01c5f31..0000000
--- a/android-car-lib/res/values-pt-rBR/values-pt-rBR.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Foco na estrada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pt-rPT/values-pt-rPT.xml b/android-car-lib/res/values-pt-rPT/values-pt-rPT.xml
deleted file mode 100644
index 9cc59bc..0000000
--- a/android-car-lib/res/values-pt-rPT/values-pt-rPT.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentre-se na estrada."</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pt-rPT/values.xml b/android-car-lib/res/values-pt-rPT/values.xml
deleted file mode 100644
index 85c248a..0000000
--- a/android-car-lib/res/values-pt-rPT/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botão Expandir/reduzir"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentre-se na estrada"</string>
-</resources>
diff --git a/android-car-lib/res/values-pt/values-pt.xml b/android-car-lib/res/values-pt/values-pt.xml
deleted file mode 100644
index 01c5f31..0000000
--- a/android-car-lib/res/values-pt/values-pt.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Foco na estrada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-pt/values.xml b/android-car-lib/res/values-pt/values.xml
deleted file mode 100644
index 8d7071d..0000000
--- a/android-car-lib/res/values-pt/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Botão \"Expandir/Recolher\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Foco na estrada"</string>
-</resources>
diff --git a/android-car-lib/res/values-ro/values-ro.xml b/android-car-lib/res/values-ro/values-ro.xml
deleted file mode 100644
index 72b3ef7..0000000
--- a/android-car-lib/res/values-ro/values-ro.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Concentrați-vă asupra drumului"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ro/values.xml b/android-car-lib/res/values-ro/values.xml
deleted file mode 100644
index 4a40973..0000000
--- a/android-car-lib/res/values-ro/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Butonul de extindere/restrângere"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Concentrați-vă asupra drumului"</string>
-</resources>
diff --git a/android-car-lib/res/values-ru/values-ru.xml b/android-car-lib/res/values-ru/values-ru.xml
deleted file mode 100644
index 96f1b8f..0000000
--- a/android-car-lib/res/values-ru/values-ru.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Следите за дорогой"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ru/values.xml b/android-car-lib/res/values-ru/values.xml
deleted file mode 100644
index 82def43..0000000
--- a/android-car-lib/res/values-ru/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Кнопка \"Развернуть/свернуть\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Следите за дорогой"</string>
-</resources>
diff --git a/android-car-lib/res/values-si/values-si.xml b/android-car-lib/res/values-si/values-si.xml
deleted file mode 100644
index 53aeba6..0000000
--- a/android-car-lib/res/values-si/values-si.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"මාර්ගයට අවධානය යොමු කරන්න"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-si/values.xml b/android-car-lib/res/values-si/values.xml
deleted file mode 100644
index d841b61..0000000
--- a/android-car-lib/res/values-si/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"දිග හැරීමේ/හැකිළීමේ බොත්තම"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"මාර්ගයට අවධානය යොමු කරන්න"</string>
-</resources>
diff --git a/android-car-lib/res/values-sk/values-sk.xml b/android-car-lib/res/values-sk/values-sk.xml
deleted file mode 100644
index 20634da..0000000
--- a/android-car-lib/res/values-sk/values-sk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Sústreďte sa na cestu"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sk/values.xml b/android-car-lib/res/values-sk/values.xml
deleted file mode 100644
index cd78105..0000000
--- a/android-car-lib/res/values-sk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Tlačidlo rozbalenia/zbalenia"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Sústreďte sa na cestu"</string>
-</resources>
diff --git a/android-car-lib/res/values-sl/values-sl.xml b/android-car-lib/res/values-sl/values-sl.xml
deleted file mode 100644
index 6a8dd70..0000000
--- a/android-car-lib/res/values-sl/values-sl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Glejte na cesto"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sl/values.xml b/android-car-lib/res/values-sl/values.xml
deleted file mode 100644
index db5e068..0000000
--- a/android-car-lib/res/values-sl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Gumb za razširitev/strnitev"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Glejte na cesto"</string>
-</resources>
diff --git a/android-car-lib/res/values-sq/values-sq.xml b/android-car-lib/res/values-sq/values-sq.xml
deleted file mode 100644
index 2079f47..0000000
--- a/android-car-lib/res/values-sq/values-sq.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Përqendrohu te rruga"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sq/values.xml b/android-car-lib/res/values-sq/values.xml
deleted file mode 100644
index e72a586..0000000
--- a/android-car-lib/res/values-sq/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Butoni i zgjerimit/palosjes"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Përqendrohu te rruga"</string>
-</resources>
diff --git a/android-car-lib/res/values-sr/values-sr.xml b/android-car-lib/res/values-sr/values-sr.xml
deleted file mode 100644
index 428dcc6..0000000
--- a/android-car-lib/res/values-sr/values-sr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Фокусирајте се на пут"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sr/values.xml b/android-car-lib/res/values-sr/values.xml
deleted file mode 100644
index 2c6b1ea..0000000
--- a/android-car-lib/res/values-sr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Дугме Прошири/скупи"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Фокусирајте се на пут"</string>
-</resources>
diff --git a/android-car-lib/res/values-sv/values-sv.xml b/android-car-lib/res/values-sv/values-sv.xml
deleted file mode 100644
index b63afe6..0000000
--- a/android-car-lib/res/values-sv/values-sv.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Fokusera på körningen"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sv/values.xml b/android-car-lib/res/values-sv/values.xml
deleted file mode 100644
index d7a7ca4..0000000
--- a/android-car-lib/res/values-sv/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Knappen Utöka/komprimera"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Fokusera på körningen"</string>
-</resources>
diff --git a/android-car-lib/res/values-sw/values-sw.xml b/android-car-lib/res/values-sw/values-sw.xml
deleted file mode 100644
index 4b3d68a..0000000
--- a/android-car-lib/res/values-sw/values-sw.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Tia makini barabarani"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-sw/values.xml b/android-car-lib/res/values-sw/values.xml
deleted file mode 100644
index dfb951c..0000000
--- a/android-car-lib/res/values-sw/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Kitufe cha kupanua/kukunja"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Makinika barabarani"</string>
-</resources>
diff --git a/android-car-lib/res/values-ta/values-ta.xml b/android-car-lib/res/values-ta/values-ta.xml
deleted file mode 100644
index 0718f29..0000000
--- a/android-car-lib/res/values-ta/values-ta.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"வாகனம் ஓட்டும்போது கவனம் தேவை"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ta/values.xml b/android-car-lib/res/values-ta/values.xml
deleted file mode 100644
index 2a7bf98..0000000
--- a/android-car-lib/res/values-ta/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"விரிவாக்குவதற்கான/சுருக்குவதற்கான பட்டன்"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"வாகனம் ஓட்டும்போது கவனம் தேவை"</string>
-</resources>
diff --git a/android-car-lib/res/values-te/values-te.xml b/android-car-lib/res/values-te/values-te.xml
deleted file mode 100644
index c4d7d3e..0000000
--- a/android-car-lib/res/values-te/values-te.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"రహదారిపై దృష్టి ఉంచండి"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-te/values.xml b/android-car-lib/res/values-te/values.xml
deleted file mode 100644
index 082ee94..0000000
--- a/android-car-lib/res/values-te/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"విస్తరించు/కుదించు బటన్"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"రహదారిపై దృష్టి ఉంచండి"</string>
-</resources>
diff --git a/android-car-lib/res/values-th/values-th.xml b/android-car-lib/res/values-th/values-th.xml
deleted file mode 100644
index e3fb94f..0000000
--- a/android-car-lib/res/values-th/values-th.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"จดจ่อกับถนน"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-th/values.xml b/android-car-lib/res/values-th/values.xml
deleted file mode 100644
index 4c7f8ce..0000000
--- a/android-car-lib/res/values-th/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"ปุ่มขยาย/ยุบ"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"จดจ่อกับถนน"</string>
-</resources>
diff --git a/android-car-lib/res/values-tl/values-tl.xml b/android-car-lib/res/values-tl/values-tl.xml
deleted file mode 100644
index 332c15c..0000000
--- a/android-car-lib/res/values-tl/values-tl.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Tumuon sa kalsada"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-tl/values.xml b/android-car-lib/res/values-tl/values.xml
deleted file mode 100644
index 674ffb1..0000000
--- a/android-car-lib/res/values-tl/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Button na i-expand/i-collapse"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Tumuon sa kalsada"</string>
-</resources>
diff --git a/android-car-lib/res/values-tr/values-tr.xml b/android-car-lib/res/values-tr/values-tr.xml
deleted file mode 100644
index 5f66ef3..0000000
--- a/android-car-lib/res/values-tr/values-tr.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Dikkatinizi yola verin"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-tr/values.xml b/android-car-lib/res/values-tr/values.xml
deleted file mode 100644
index dde5e18..0000000
--- a/android-car-lib/res/values-tr/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Genişlet/daralt düğmesi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Dikkatinizi yola verin"</string>
-</resources>
diff --git a/android-car-lib/res/values-uk/values-uk.xml b/android-car-lib/res/values-uk/values-uk.xml
deleted file mode 100644
index 472d178..0000000
--- a/android-car-lib/res/values-uk/values-uk.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Зосередьтеся на дорозі"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-uk/values.xml b/android-car-lib/res/values-uk/values.xml
deleted file mode 100644
index e277cc5..0000000
--- a/android-car-lib/res/values-uk/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Кнопка \"Розгорнути або згорнути\""</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Зосередьтеся на дорозі"</string>
-</resources>
diff --git a/android-car-lib/res/values-ur/values-ur.xml b/android-car-lib/res/values-ur/values-ur.xml
deleted file mode 100644
index 6f13ae2..0000000
--- a/android-car-lib/res/values-ur/values-ur.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"سڑک پر توجہ مرکوز کریں"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-ur/values.xml b/android-car-lib/res/values-ur/values.xml
deleted file mode 100644
index 70659bf..0000000
--- a/android-car-lib/res/values-ur/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"پھیلائیں/سکیڑیں بٹن"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"سڑک پر توجہ مرکوز کریں"</string>
-</resources>
diff --git a/android-car-lib/res/values-uz/values-uz.xml b/android-car-lib/res/values-uz/values-uz.xml
deleted file mode 100644
index cb5f3aa..0000000
--- a/android-car-lib/res/values-uz/values-uz.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Diqqatingizni yo‘lga qarating"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-uz/values.xml b/android-car-lib/res/values-uz/values.xml
deleted file mode 100644
index e9c7755..0000000
--- a/android-car-lib/res/values-uz/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Yoyish/yig‘ish tugmasi"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Diqqatingizni yo‘lga qarating"</string>
-</resources>
diff --git a/android-car-lib/res/values-vi/values-vi.xml b/android-car-lib/res/values-vi/values-vi.xml
deleted file mode 100644
index cecbeac..0000000
--- a/android-car-lib/res/values-vi/values-vi.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Tập trung vào đường đi"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-vi/values.xml b/android-car-lib/res/values-vi/values.xml
deleted file mode 100644
index 070849e..0000000
--- a/android-car-lib/res/values-vi/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Nút mở rộng/thu gọn"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Tập trung vào đường đi"</string>
-</resources>
diff --git a/android-car-lib/res/values-w1280dp-v13/values-w1280dp-v13.xml b/android-car-lib/res/values-w1280dp-v13/values-w1280dp-v13.xml
deleted file mode 100644
index e5d29e6..0000000
--- a/android-car-lib/res/values-w1280dp-v13/values-w1280dp-v13.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_keyline_4">182dp</dimen>
-    <dimen name="car_keyline_4_neg">-182dp</dimen>
-    <dimen name="car_margin">148dp</dimen>
-    <integer name="car_dialog_column_number">8</integer>
-    <integer name="column_card_default_column_span">8</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-w1920dp-v13/values-w1920dp-v13.xml b/android-car-lib/res/values-w1920dp-v13/values-w1920dp-v13.xml
deleted file mode 100644
index bcffcfa..0000000
--- a/android-car-lib/res/values-w1920dp-v13/values-w1920dp-v13.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_gutter_size">32dp</dimen>
-    <dimen name="car_keyline_1">48dp</dimen>
-    <dimen name="car_keyline_1_keyline_3_diff">104dp</dimen>
-    <dimen name="car_keyline_1_neg">-48dp</dimen>
-    <dimen name="car_keyline_3">152dp</dimen>
-    <dimen name="car_keyline_3_neg">-152dp</dimen>
-    <dimen name="car_margin">192dp</dimen>
-    <integer name="car_column_number">16</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-w690dp-v13/values-w690dp-v13.xml b/android-car-lib/res/values-w690dp-v13/values-w690dp-v13.xml
deleted file mode 100644
index 19864c5..0000000
--- a/android-car-lib/res/values-w690dp-v13/values-w690dp-v13.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_margin">112dp</dimen>
-    <integer name="car_column_number">12</integer>
-    <integer name="car_dialog_column_number">10</integer>
-    <integer name="car_slide_up_menu_column_number">12</integer>
-    <integer name="column_card_default_column_span">12</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-w930dp-v13/values-w930dp-v13.xml b/android-car-lib/res/values-w930dp-v13/values-w930dp-v13.xml
deleted file mode 100644
index 363170c..0000000
--- a/android-car-lib/res/values-w930dp-v13/values-w930dp-v13.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <dimen name="car_gutter_size">24dp</dimen>
-    <dimen name="car_keyline_1">32dp</dimen>
-    <dimen name="car_keyline_1_keyline_3_diff">96dp</dimen>
-    <dimen name="car_keyline_1_neg">-32dp</dimen>
-    <dimen name="car_keyline_2">108dp</dimen>
-    <dimen name="car_keyline_2_neg">-108dp</dimen>
-    <dimen name="car_keyline_3">128dp</dimen>
-    <dimen name="car_keyline_3_neg">-128dp</dimen>
-    <dimen name="car_keyline_4">168dp</dimen>
-    <dimen name="car_keyline_4_neg">-168dp</dimen>
-    <integer name="car_dialog_column_number">10</integer>
-    <integer name="column_card_default_column_span">10</integer>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rCN/values-zh-rCN.xml b/android-car-lib/res/values-zh-rCN/values-zh-rCN.xml
deleted file mode 100644
index e3ac7a1..0000000
--- a/android-car-lib/res/values-zh-rCN/values-zh-rCN.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"请专心驾驶"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rCN/values.xml b/android-car-lib/res/values-zh-rCN/values.xml
deleted file mode 100644
index 5347850..0000000
--- a/android-car-lib/res/values-zh-rCN/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"“展开”/“收起”按钮"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"请专心驾驶"</string>
-</resources>
diff --git a/android-car-lib/res/values-zh-rHK/values-zh-rHK.xml b/android-car-lib/res/values-zh-rHK/values-zh-rHK.xml
deleted file mode 100644
index 37107e1..0000000
--- a/android-car-lib/res/values-zh-rHK/values-zh-rHK.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"請專心駕駛"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rHK/values.xml b/android-car-lib/res/values-zh-rHK/values.xml
deleted file mode 100644
index b190714..0000000
--- a/android-car-lib/res/values-zh-rHK/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"展開/收合按鈕"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"請專心駕駛"</string>
-</resources>
diff --git a/android-car-lib/res/values-zh-rTW/values-zh-rTW.xml b/android-car-lib/res/values-zh-rTW/values-zh-rTW.xml
deleted file mode 100644
index 37107e1..0000000
--- a/android-car-lib/res/values-zh-rTW/values-zh-rTW.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"請專心駕駛"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zh-rTW/values.xml b/android-car-lib/res/values-zh-rTW/values.xml
deleted file mode 100644
index b190714..0000000
--- a/android-car-lib/res/values-zh-rTW/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"展開/收合按鈕"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"請專心駕駛"</string>
-</resources>
diff --git a/android-car-lib/res/values-zu/values-zu.xml b/android-car-lib/res/values-zu/values-zu.xml
deleted file mode 100644
index 1f93364..0000000
--- a/android-car-lib/res/values-zu/values-zu.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string msgid="5405697774899378511" name="speed_bump_lockout_message">"Gxila emgwaqweni"</string>
-</resources>
\ No newline at end of file
diff --git a/android-car-lib/res/values-zu/values.xml b/android-car-lib/res/values-zu/values.xml
deleted file mode 100644
index 0646429..0000000
--- a/android-car-lib/res/values-zu/values.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_bar_expand_collapse_button" msgid="2901704611804567760">"Inkinobho yokunweba/ukugoqa"</string>
-    <string name="speed_bump_lockout_message" msgid="4050134640025645838">"Gxila emgwaqeni"</string>
-</resources>
diff --git a/android-car-lib/res/values/values.xml b/android-car-lib/res/values/values.xml
deleted file mode 100644
index 15e70f0..0000000
--- a/android-car-lib/res/values/values.xml
+++ /dev/null
@@ -1,552 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="car_accent">@color/car_accent_dark</color>
-    <color name="car_accent_dark">@color/car_teal_700</color>
-    <color name="car_accent_light">@color/car_teal_200</color>
-    <color name="car_action1">@color/car_action1_dark</color>
-    <color name="car_action1_dark">@color/car_grey_50</color>
-    <color name="car_action1_light">@color/car_grey_900</color>
-    <color name="car_blue_300">#ff91a7ff</color>
-    <color name="car_blue_500">#ff5677fc</color>
-    <color name="car_blue_grey_800">#ff37474F</color>
-    <color name="car_blue_grey_900">#ff263238</color>
-    <color name="car_body1">@color/car_body1_dark</color>
-    <color name="car_body1_dark">@color/car_grey_900</color>
-    <color name="car_body1_light">@color/car_grey_100</color>
-    <color name="car_body2">@color/car_body2_dark</color>
-    <color name="car_body2_dark">@color/car_grey_650</color>
-    <color name="car_body2_light">@color/car_grey_300</color>
-    <color name="car_body3">@color/car_body3_dark</color>
-    <color name="car_body3_dark">@android:color/black</color>
-    <color name="car_body3_light">@android:color/white</color>
-    <color name="car_body4">@color/car_body4_dark</color>
-    <color name="car_body4_dark">@android:color/black</color>
-    <color name="car_body4_light">@android:color/white</color>
-    <color name="car_card">@color/car_card_light</color>
-    <color name="car_card_dark">@color/car_dark_blue_grey_700</color>
-    <color name="car_card_inverse">@color/car_card_dark</color>
-    <color name="car_card_light">@color/car_grey_50</color>
-    <color name="car_card_ripple_background">@color/car_card_ripple_background_dark</color>
-    <color name="car_card_ripple_background_dark">#8F000000</color>
-    <color name="car_card_ripple_background_inverse">@color/car_card_ripple_background_light</color>
-    <color name="car_card_ripple_background_light">#27ffffff</color>
-    <color name="car_dark_blue_grey_1000">#ff090c0f</color>
-    <color name="car_dark_blue_grey_600">#ff1d272d</color>
-    <color name="car_dark_blue_grey_700">#ff172026</color>
-    <color name="car_dark_blue_grey_800">#ff11181d</color>
-    <color name="car_dark_blue_grey_900">#ff0c1013</color>
-    <color name="car_green_500">#ff0f9d58</color>
-    <color name="car_green_700">#ff0b8043</color>
-    <color name="car_grey_100">#fff5f5f5</color>
-    <color name="car_grey_1000">#cc000000</color>
-    <color name="car_grey_200">#ffeeeeee</color>
-    <color name="car_grey_300">#ffe0e0e0</color>
-    <color name="car_grey_400">#ffbdbdbd</color>
-    <color name="car_grey_50">#fffafafa</color>
-    <color name="car_grey_500">#ff9e9e9e</color>
-    <color name="car_grey_600">#ff757575</color>
-    <color name="car_grey_650">#ff6B6B6B</color>
-    <color name="car_grey_700">#ff616161</color>
-    <color name="car_grey_800">#ff424242</color>
-    <color name="car_grey_900">#ff212121</color>
-    <color name="car_headline1">@color/car_headline1_dark</color>
-    <color name="car_headline1_dark">@color/car_grey_800</color>
-    <color name="car_headline1_light">@color/car_grey_100</color>
-    <color name="car_headline2">@color/car_headline2_dark</color>
-    <color name="car_headline2_dark">@color/car_grey_900</color>
-    <color name="car_headline2_light">@color/car_grey_100</color>
-    <color name="car_headline3">@color/car_headline3_dark</color>
-    <color name="car_headline3_dark">@color/car_grey_900</color>
-    <color name="car_headline3_light">@android:color/white</color>
-    <color name="car_headline4">@color/car_headline4_dark</color>
-    <color name="car_headline4_dark">@android:color/black</color>
-    <color name="car_headline4_light">@android:color/white</color>
-    <color name="car_highlight">@color/car_highlight_light</color>
-    <color name="car_highlight_dark">@color/car_teal_200</color>
-    <color name="car_highlight_light">@color/car_teal_700</color>
-    <color name="car_indigo_800">#ff283593</color>
-    <color name="car_label1">@color/car_label1_dark</color>
-    <color name="car_label1_dark">@color/car_grey_900</color>
-    <color name="car_label1_light">@color/car_grey_50</color>
-    <color name="car_light_blue_300">#ff4fc3f7</color>
-    <color name="car_light_blue_500">#ff03A9F4</color>
-    <color name="car_light_blue_600">#ff039be5</color>
-    <color name="car_light_blue_700">#ff0288d1</color>
-    <color name="car_light_blue_800">#ff0277bd</color>
-    <color name="car_light_blue_900">#ff01579b</color>
-    <color name="car_list_divider">@color/car_list_divider_dark</color>
-    <color name="car_list_divider_dark">#1f000000</color>
-    <color name="car_list_divider_inverse">@color/car_list_divider_light</color>
-    <color name="car_list_divider_light">#1fffffff</color>
-    <color name="car_list_header">@color/car_blue_500</color>
-    <color name="car_red_400">#ffe06055</color>
-    <color name="car_red_500">#ffdb4437</color>
-    <color name="car_red_500a">#ffd50000</color>
-    <color name="car_red_700">#ffc53929</color>
-    <color name="car_scrollbar_thumb">@color/car_scrollbar_thumb_dark</color>
-    <color name="car_scrollbar_thumb_dark">#7f0b0f12</color>
-    <color name="car_scrollbar_thumb_inverse">@color/car_scrollbar_thumb_light</color>
-    <color name="car_scrollbar_thumb_light">#99ffffff</color>
-    <color name="car_seekbar_track_background">@color/car_seekbar_track_background_dark</color>
-    <color name="car_seekbar_track_background_dark">@color/car_grey_700</color>
-    <color name="car_seekbar_track_background_inverse"> @color/car_seekbar_track_background_light
-    </color>
-    <color name="car_seekbar_track_background_light">@color/car_grey_400</color>
-    <color name="car_teal_200">#ff80cbc4</color>
-    <color name="car_teal_700">#ff00796b</color>
-    <color name="car_tint">@color/car_tint_dark</color>
-    <color name="car_tint_dark">@color/car_grey_900</color>
-    <color name="car_tint_inverse">@color/car_tint_light</color>
-    <color name="car_tint_light">@color/car_grey_50</color>
-    <color name="car_title">@color/car_title_dark</color>
-    <color name="car_title2">@color/car_title2_dark</color>
-    <color name="car_title2_dark">@color/car_grey_900</color>
-    <color name="car_title2_light">@color/car_grey_100</color>
-    <color name="car_title_dark">@color/car_grey_900</color>
-    <color name="car_title_light">@color/car_grey_100</color>
-    <color name="car_white_1000">#1effffff</color>
-    <color name="car_yellow_500">#fff4b400</color>
-    <color name="car_yellow_800">#ffee8100</color>
-    <color name="speed_bump_background">#FFD0D0D0</color>
-    <declare-styleable name="ActionBar"><attr format="integer" name="columns"/></declare-styleable>
-    <declare-styleable name="CarTheme"><attr format="reference" name="carDialogTheme"/><attr format="reference" name="pagedListViewStyle"/><attr format="reference" name="listItemStyle"/><attr format="color" name="dialogBackgroundColor"/><attr format="reference" name="dialogTitleStyle"/><attr format="reference" name="dialogBodyStyle"/><attr format="reference" name="dialogButtonStyle"/><attr format="reference" name="dialogListTheme"/><attr format="color" name="drawerBackgroundColor"/><attr format="color" name="drawerOpenHeaderColor"/><attr format="color" name="drawerClosedHeaderColor"/><attr format="reference" name="drawerItemTitleTextAppearance"/><attr format="reference" name="drawerItemBodyTextAppearance"/><attr format="reference" name="drawerListStyle"/></declare-styleable>
-    <declare-styleable name="ClickThroughToolbar"><attr format="boolean" name="clickThrough"/></declare-styleable>
-    <declare-styleable name="ColumnCardView"><attr format="integer" name="columnSpan"/></declare-styleable>
-    <declare-styleable name="DrawerArrowDrawable"><attr format="color" name="carArrowColor"/><attr format="boolean" name="carArrowAnimate"/><attr format="dimension" name="carArrowSize"/><attr format="dimension" name="carArrowHeadLength"/><attr format="dimension" name="carArrowShaftLength"/><attr format="dimension" name="carArrowThickness"/><attr format="dimension" name="carMenuBarSpacing"/><attr format="dimension" name="carMenuBarThickness"/></declare-styleable>
-    <declare-styleable name="ListItem"><attr format="color" name="listItemBackgroundColor"/><attr format="reference" name="listItemTitleTextAppearance"/><attr format="reference" name="listItemBodyTextAppearance"/></declare-styleable>
-    <declare-styleable name="PagedListView"><attr format="boolean" name="offsetScrollBar"/><attr format="enum" name="gutter">
-            
-            <enum name="none" value="0"/>
-            
-            <enum name="start" value="1"/>
-            
-            <enum name="end" value="2"/>
-            
-            <enum name="both" value="3"/>
-        </attr><attr format="dimension" name="gutterSize"/><attr format="boolean" name="scrollBarEnabled"/><attr format="dimension" name="scrollBarTopMargin"/><attr format="dimension" name="scrollBarContainerWidth"/><attr format="boolean" name="showPagedListViewDivider"/><attr format="reference" name="alignDividerStartTo"/><attr format="reference" name="alignDividerEndTo"/><attr format="dimension" name="dividerStartMargin"/><attr format="dimension" name="dividerEndMargin"/><attr format="color" name="listDividerColor"/><attr format="dimension" name="listEndMargin"/><attr format="dimension" name="itemSpacing"/><attr format="reference" name="upButtonIcon"/><attr format="reference" name="downButtonIcon"/><attr format="reference" name="listContentTopOffset"/><attr format="enum" name="dayNightStyle">
-            
-            <enum name="auto" value="0"/>
-            
-            <enum name="auto_inverse" value="1"/>
-            
-            <enum name="force_night" value="2"/>
-            
-            <enum name="force_day" value="3"/>
-        </attr></declare-styleable>
-    <dimen name="app_header_height">96dp</dimen>
-    <dimen name="car_action1_size">26sp</dimen>
-    <dimen name="car_action_bar_activation_ring_radius">64dp</dimen>
-    <dimen name="car_action_bar_activation_ring_stroke_width">3dp</dimen>
-    <dimen name="car_action_bar_button_height">128dp</dimen>
-    <dimen name="car_action_bar_button_ripple_radius">48dp</dimen>
-    <dimen name="car_action_bar_button_width">128dp</dimen>
-    <dimen name="car_action_bar_buttons_space">@dimen/car_padding_4</dimen>
-    <dimen name="car_action_bar_elevation">2dp</dimen>
-    <dimen name="car_action_bar_height">128dp</dimen>
-    <dimen name="car_action_bar_touch_ripple_size">38dp</dimen>
-    <dimen name="car_action_button_icon_inset">24dp</dimen>
-    <dimen name="car_action_button_ripple_inset">16dp</dimen>
-    <dimen name="car_alpha_jump_button_size">@dimen/car_scroll_bar_button_size</dimen>
-    <dimen name="car_app_bar_default_elevation">8dp</dimen>
-    <dimen name="car_app_bar_height">80dp</dimen>
-    <dimen name="car_arrow_head_length">18dp</dimen>
-    <dimen name="car_arrow_shaft_length">34dp</dimen>
-    <dimen name="car_arrow_size">96dp</dimen>
-    <dimen name="car_arrow_thickness">3dp</dimen>
-    <dimen name="car_avatar_size">56dp</dimen>
-    <dimen name="car_body1_size">32sp</dimen>
-    <dimen name="car_body2_size">26sp</dimen>
-    <dimen name="car_body3_size">16sp</dimen>
-    <dimen name="car_body4_size">14sp</dimen>
-    <dimen name="car_body5_size">18sp</dimen>
-    <dimen name="car_borderless_button_horizontal_padding">0dp</dimen>
-    <dimen name="car_button_height">56dp</dimen>
-    <dimen name="car_button_horizontal_padding">@dimen/car_padding_4</dimen>
-    <dimen name="car_button_min_width">158dp</dimen>
-    <dimen name="car_button_radius">@dimen/car_radius_1</dimen>
-    <dimen name="car_card_action_bar_height">76dp</dimen>
-    <dimen name="car_card_header_height">76dp</dimen>
-    <dimen name="car_dialog_action_bar_height">@dimen/car_card_action_bar_height</dimen>
-    <dimen name="car_dialog_elevation">16dp</dimen>
-    <dimen name="car_dialog_header_height">@dimen/car_card_header_height</dimen>
-    <dimen name="car_double_line_list_item_height">@dimen/car_single_line_list_item_height</dimen>
-    <dimen name="car_drawer_list_item_end_icon_size">56dp</dimen>
-    <dimen name="car_drawer_list_item_end_margin">32dp</dimen>
-    <dimen name="car_drawer_list_item_icon_end_margin">32dp</dimen>
-    <dimen name="car_drawer_list_item_icon_size">64dp</dimen>
-    <dimen name="car_drawer_list_item_small_icon_size">56dp</dimen>
-    <dimen name="car_drawer_margin_end">96dp</dimen>
-    <dimen name="car_drawer_progress_bar_size">48dp</dimen>
-    <dimen name="car_gutter_size">16dp</dimen>
-    <dimen name="car_headline1_size">45sp</dimen>
-    <dimen name="car_headline2_size">32sp</dimen>
-    <dimen name="car_headline3_size">24sp</dimen>
-    <dimen name="car_headline4_size">20sp</dimen>
-    <dimen name="car_keyline_1">24dp</dimen>
-    <dimen name="car_keyline_1_keyline_3_diff">88dp</dimen>
-    <dimen name="car_keyline_1_neg">-24dp</dimen>
-    <dimen name="car_keyline_2">96dp</dimen>
-    <dimen name="car_keyline_2_neg">-96dp</dimen>
-    <dimen name="car_keyline_3">112dp</dimen>
-    <dimen name="car_keyline_3_neg">-112dp</dimen>
-    <dimen name="car_keyline_4">148dp</dimen>
-    <dimen name="car_keyline_4_neg">-148dp</dimen>
-    <dimen name="car_label1_size">26sp</dimen>
-    <dimen name="car_last_card_peek_amount">16dp</dimen>
-    <dimen name="car_list_divider_height">1dp</dimen>
-    <dimen name="car_margin">20dp</dimen>
-    <dimen name="car_menu_bar_length">40dp</dimen>
-    <dimen name="car_menu_bar_spacing">6dp</dimen>
-    <dimen name="car_padding_0">4dp</dimen>
-    <dimen name="car_padding_1">10dp</dimen>
-    <dimen name="car_padding_2">12dp</dimen>
-    <dimen name="car_padding_3">16dp</dimen>
-    <dimen name="car_padding_4">20dp</dimen>
-    <dimen name="car_padding_5">40dp</dimen>
-    <dimen name="car_padding_6">64dp</dimen>
-    <dimen name="car_primary_icon_size">44dp</dimen>
-    <dimen name="car_progress_bar_height">@dimen/car_seekbar_height</dimen>
-    <dimen name="car_radius_1">4dp</dimen>
-    <dimen name="car_radius_2">8dp</dimen>
-    <dimen name="car_radius_3">16dp</dimen>
-    <dimen name="car_radius_5">100dp</dimen>
-    <dimen name="car_sample_row_height">128dp</dimen>
-    <dimen name="car_scroll_bar_button_size">56dp</dimen>
-    <dimen name="car_scroll_bar_thumb_width">6dp</dimen>
-    <dimen name="car_secondary_icon_size">24dp</dimen>
-    <dimen name="car_seekbar_height">6dp</dimen>
-    <dimen name="car_seekbar_thumb_size">20dp</dimen>
-    <dimen name="car_seekbar_thumb_stroke">1dp</dimen>
-    <dimen name="car_single_line_list_item_height">96dp</dimen>
-    <dimen name="car_slide_down_menu_initial_height">@dimen/car_slide_up_menu_initial_height</dimen>
-    <dimen name="car_slide_up_menu_initial_height">76dp</dimen>
-    <dimen name="car_sub_header_height">76dp</dimen>
-    <dimen name="car_text_input_line_height">2dp</dimen>
-    <dimen name="car_text_vertical_margin">2dp</dimen>
-    <dimen name="car_title2_size">32sp</dimen>
-    <dimen name="car_title_size">32sp</dimen>
-    <dimen name="car_touch_target_size">76dp</dimen>
-    <dimen name="car_vertical_line_divider_height">60dp</dimen>
-    <dimen name="car_vertical_line_divider_width">1dp</dimen>
-    <dimen name="speed_bump_lock_out_drawable_margin_bottom">8dp</dimen>
-    <dimen name="speed_bump_lock_out_message_height">96dp</dimen>
-    <integer name="car_action_bar_collapse_anim_duration">233</integer>
-    <integer name="car_action_bar_expand_anim_duration">333</integer>
-    <integer name="car_borderless_button_text_length_limit">20</integer>
-    <integer name="car_column_number">4</integer>
-    <integer name="car_dialog_column_number">10</integer>
-    <integer name="car_list_item_text_length_limit">120</integer>
-    <integer name="car_slide_up_menu_column_number">4</integer>
-    <integer name="column_card_default_column_span">4</integer>
-    <integer name="speed_bump_fade_duration_ms">167</integer>
-    <integer name="speed_bump_lock_out_color_change_ms">500</integer>
-    <integer name="speed_bump_lock_out_color_change_start_delay_ms">5433</integer>
-    <integer name="speed_bump_lock_out_duration_ms">5933</integer>
-    <integer name="speed_bump_translate_y_duration_ms">300</integer>
-    <string name="action_bar_expand_collapse_button">Expand/collapse button</string>
-    <string name="car_drawer_close" translatable="false">Close drawer</string>
-    <string name="car_drawer_open" translatable="false">Open drawer</string>
-    <string name="ellipsis" translatable="false">…</string>
-    <string name="speed_bump_lockout_message">Focus on the road</string>
-    <style name="CarListVerticalDivider">
-        <item name="android:layout_width">@dimen/car_vertical_line_divider_width</item>
-        <item name="android:layout_height">@dimen/car_vertical_line_divider_height</item>
-        <item name="android:layout_marginStart">@dimen/car_padding_4</item>
-        <item name="android:background">@color/car_list_divider</item>
-    </style>
-    <style name="TextAppearance.Car" parent="TextAppearance.AppCompat"/>
-    <style name="TextAppearance.Car.Body1">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body1_size</item>
-        <item name="android:textColor">@color/car_body1</item>
-    </style>
-    <style name="TextAppearance.Car.Body1.Dark">
-        <item name="android:textColor">@color/car_body2_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Body1.Light">
-        <item name="android:textColor">@color/car_body1_light</item>
-    </style>
-    <style name="TextAppearance.Car.Body2">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body2_size</item>
-        <item name="android:textColor">@color/car_body2</item>
-    </style>
-    <style name="TextAppearance.Car.Body2.Dark">
-        <item name="android:textColor">@color/car_body2_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Body2.Light">
-        <item name="android:textColor">@color/car_body2_light</item>
-    </style>
-    <style name="TextAppearance.Car.Body3">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body3_size</item>
-        <item name="android:textColor">@color/car_body3</item>
-    </style>
-    <style name="TextAppearance.Car.Body4">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_body4_size</item>
-        <item name="android:textColor">@color/car_body4</item>
-    </style>
-    <style name="TextAppearance.Car.Headline1">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline1_size</item>
-        <item name="android:textColor">@color/car_headline1</item>
-    </style>
-    <style name="TextAppearance.Car.Headline1.Dark">
-        <item name="android:textColor">@color/car_headline1_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Headline1.Light">
-        <item name="android:textColor">@color/car_headline1_light</item>
-    </style>
-    <style name="TextAppearance.Car.Headline2">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline2_size</item>
-        <item name="android:textColor">@color/car_headline2</item>
-    </style>
-    <style name="TextAppearance.Car.Headline3">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline3_size</item>
-        <item name="android:textColor">@color/car_headline3</item>
-    </style>
-    <style name="TextAppearance.Car.Headline4">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_headline4_size</item>
-        <item name="android:textColor">@color/car_headline4</item>
-    </style>
-    <style name="TextAppearance.Car.Hint" parent="TextAppearance.Car.Body2"/>
-    <style name="TextAppearance.Car.Label1">
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_label1_size</item>
-        <item name="android:textColor">@color/car_label1</item>
-    </style>
-    <style name="TextAppearance.Car.Title">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_title_size</item>
-        <item name="android:textColor">@color/car_title</item>
-    </style>
-    <style name="TextAppearance.Car.Title.Dark">
-        <item name="android:textColor">@color/car_title_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Title.Light">
-        <item name="android:textColor">@color/car_title_light</item>
-    </style>
-    <style name="TextAppearance.Car.Title2">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:textStyle">normal</item>
-        <item name="android:textSize">@dimen/car_title2_size</item>
-        <item name="android:textColor">@color/car_title2</item>
-    </style>
-    <style name="TextAppearance.Car.Title2.Dark">
-        <item name="android:textColor">@color/car_title2_dark</item>
-    </style>
-    <style name="TextAppearance.Car.Title2.Light">
-        <item name="android:textColor">@color/car_title2_light</item>
-    </style>
-    <style name="Theme.Car.Dark.Dialog" parent="Theme.Car.Dialog">
-        <item name="dialogButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="dialogBackgroundColor">@color/car_card_dark</item>
-        <item name="dialogListTheme">@style/Theme.Car.Light.List.DarkItems</item>
-        <item name="dialogTitleStyle">@style/Widget.Car.Dialog.Title.Light</item>
-        <item name="dialogBodyStyle">@style/Widget.Car.Dialog.Body.Light</item>
-    </style>
-    <style name="Theme.Car.Dark.Dialog.Alert" parent="Theme.Car.Dialog.Alert">
-        <item name="android:background">@color/car_card_dark</item>
-        <item name="android:listDividerAlertDialog">@drawable/car_list_divider_light</item>
-        <item name="android:textColorPrimary">@color/car_body2_light</item>
-        <item name="android:windowTitleStyle">@style/Widget.Car.Dialog.Title.Light</item>
-    </style>
-    <style name="Theme.Car.Dark.NoActionBar" parent="Theme.Car.NoActionBar">
-        <item name="android:alertDialogTheme">@style/Theme.Car.Dark.Dialog.Alert</item>
-        <item name="alertDialogTheme">@style/Theme.Car.Dark.Dialog.Alert</item>
-        <item name="carDialogTheme">@style/Theme.Car.Dark.Dialog</item>
-        <item name="pagedListViewStyle">@style/Widget.Car.Light.List.LightDivider</item>
-        <item name="listItemStyle">@style/Widget.Car.ListItem.Dark</item>
-    </style>
-    <style name="Theme.Car.Dark.NoActionBar.Drawer">
-        <item name="drawerArrowStyle">@style/Widget.Car.DrawerArrowToggle</item>
-        <item name="drawerBackgroundColor">@color/car_card_dark</item>
-        <item name="drawerOpenHeaderColor">@color/car_title2_light</item>
-        <item name="drawerClosedHeaderColor">@color/car_title2_light</item>
-        <item name="drawerItemTitleTextAppearance">@style/TextAppearance.Car.Body1.Light</item>
-        <item name="drawerItemBodyTextAppearance">@style/TextAppearance.Car.Body2.Light</item>
-        <item name="drawerListStyle">@style/Widget.Car.Light.List.LightDivider</item>
-    </style>
-    <style name="Theme.Car.Dialog" parent="Theme.AppCompat.Dialog">
-        <item name="android:windowIsTranslucent">true</item>
-        <item name="android:windowBackground">@android:color/transparent</item>
-        <item name="dialogButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="dialogBackgroundColor">@color/car_card</item>
-        <item name="dialogListTheme">@style/Theme.Car.List</item>
-        <item name="dialogTitleStyle">@style/Widget.Car.Dialog.Title</item>
-        <item name="dialogBodyStyle">@style/Widget.Car.Dialog.Body</item>
-    </style>
-    <style name="Theme.Car.Dialog.Alert" parent="Theme.AppCompat.Dialog.Alert">
-        <item name="android:background">@color/car_card</item>
-        <item name="android:borderlessButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="android:colorButtonNormal">@color/car_accent</item>
-        <item name="android:listDividerAlertDialog">@drawable/car_list_divider</item>
-        <item name="android:textColorPrimary">@color/car_body2</item>
-        <item name="android:windowTitleStyle">@style/Widget.Car.Dialog.Title</item>
-        <item name="buttonBarNeutralButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="buttonBarNegativeButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="buttonBarPositiveButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-    </style>
-    <style name="Theme.Car.Light.Dialog.Alert" parent="Theme.Car.Dialog.Alert">
-        <item name="android:background">@color/car_card_light</item>
-        <item name="android:listDividerAlertDialog">@drawable/car_list_divider_dark</item>
-        <item name="android:textColorPrimary">@color/car_body2_dark</item>
-        <item name="android:windowTitleStyle">@style/Widget.Car.Dialog.Title.Dark</item>
-    </style>
-    <style name="Theme.Car.Light.List" parent="Theme.Car.List">
-        <item name="pagedListViewStyle">@style/Widget.Car.Light.List.LightDivider</item>
-    </style>
-    <style name="Theme.Car.Light.List.DarkItems">
-        <item name="listItemStyle">@style/Widget.Car.ListItem.Dark</item>
-    </style>
-    <style name="Theme.Car.Light.NoActionBar" parent="Theme.Car.NoActionBar"/>
-    <style name="Theme.Car.Light.NoActionBar.Drawer" parent="Theme.Car.NoActionBar.Drawer"/>
-    <style name="Theme.Car.List" parent="android:Theme">
-        <item name="pagedListViewStyle">@style/Widget.Car.List</item>
-        <item name="listItemStyle">@style/Widget.Car.ListItem</item>
-    </style>
-    <style name="Theme.Car.NoActionBar" parent="Theme.AppCompat.NoActionBar">
-        <item name="android:colorAccent">@color/car_accent</item>
-        <item name="android:colorButtonNormal">@color/car_accent</item>
-        <item name="android:buttonStyle">@style/Widget.Car.Button</item>
-        <item name="android:borderlessButtonStyle">@style/Widget.Car.Button.Borderless.Colored</item>
-        <item name="android:progressBarStyleHorizontal">@style/Widget.Car.ProgressBar.Horizontal</item>
-        <item name="android:textColorHint">@color/car_body2</item>
-        <item name="android:editTextStyle">@style/Widget.Car.EditText</item>
-        <item name="android:editTextColor">@color/car_body1</item>
-        <item name="android:colorControlNormal">@color/car_body2</item>
-        <item name="carDialogTheme">@style/Theme.Car.Dialog</item>
-        <item name="pagedListViewStyle">@style/Widget.Car.List</item>
-        <item name="listItemStyle">@style/Widget.Car.ListItem</item>
-    </style>
-    <style name="Theme.Car.NoActionBar.Drawer">
-        <item name="drawerArrowStyle">@style/Widget.Car.DrawerArrowToggle</item>
-        <item name="drawerBackgroundColor">@color/car_card</item>
-        <item name="drawerOpenHeaderColor">@color/car_title2</item>
-        <item name="drawerClosedHeaderColor">@color/car_title2_light</item>
-        <item name="drawerItemTitleTextAppearance">@style/TextAppearance.Car.Body1</item>
-        <item name="drawerItemBodyTextAppearance">@style/TextAppearance.Car.Body2</item>
-        <item name="drawerListStyle">@style/Widget.Car.List</item>
-    </style>
-    <style name="Widget.Car.Button" parent="Widget.AppCompat.Button">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:layout_height">@dimen/car_button_height</item>
-        <item name="android:minWidth">@dimen/car_button_min_width</item>
-        <item name="android:paddingStart">@dimen/car_button_horizontal_padding</item>
-        <item name="android:paddingEnd">@dimen/car_button_horizontal_padding</item>
-        <item name="android:textSize">@dimen/car_action1_size</item>
-        <item name="android:background">@drawable/car_button_background</item>
-        <item name="android:textColor">@drawable/car_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Button.ActionBar">
-        <item name="android:scaleType">fitCenter</item>
-        <item name="android:padding">@dimen/car_action_button_icon_inset</item>
-        <!-- Added paddingStart/End explicitly to make sure style works the same regardless of -->
-        <!-- whether RTL is enabled or disabled. -->
-        <!-- Note: When RTL is enabled, paddingStart/End overrides value of padding, -->
-        <!-- while padding overrides value of paddingStart/End when RTL is disabled. -->
-        <item name="android:paddingStart">@dimen/car_action_button_icon_inset</item>
-        <item name="android:paddingEnd">@dimen/car_action_button_icon_inset</item>
-        <item name="android:background">@drawable/car_action_button_background</item>
-        <item name="android:tint">@color/car_tint</item>
-    </style>
-    <style name="Widget.Car.Button.Borderless.Colored" parent="Widget.AppCompat.Button.Borderless.Colored">
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:layout_height">@dimen/car_button_height</item>
-        <item name="android:minWidth">@dimen/car_button_min_width</item>
-        <item name="android:paddingStart">@dimen/car_borderless_button_horizontal_padding</item>
-        <item name="android:paddingEnd">@dimen/car_borderless_button_horizontal_padding</item>
-        <item name="android:textSize">@dimen/car_action1_size</item>
-        <item name="android:textColor">@drawable/car_borderless_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Button.Borderless.Colored.Dark">
-        <item name="android:textColor">@drawable/car_borderless_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Button.Borderless.Colored.Light">
-        <item name="android:textColor">@drawable/car_borderless_button_text_color</item>
-    </style>
-    <style name="Widget.Car.Dark.List" parent="Widget.Car.List">
-        <item name="dayNightStyle">force_day</item>
-    </style>
-    <style name="Widget.Car.Dark.List.LightDivider">
-        <item name="listDividerColor">@color/car_list_divider_light</item>
-    </style>
-    <style name="Widget.Car.Dialog" parent="android:Widget"/>
-    <style name="Widget.Car.Dialog.Body">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body2</item>
-    </style>
-    <style name="Widget.Car.Dialog.Body.Dark">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body2.Dark</item>
-    </style>
-    <style name="Widget.Car.Dialog.Body.Light">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body2.Light</item>
-    </style>
-    <style name="Widget.Car.Dialog.Title">
-        <item name="android:maxLines">1</item>
-        <item name="android:textAppearance">@style/TextAppearance.Car.Title2</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:textAlignment">viewStart</item>
-    </style>
-    <style name="Widget.Car.Dialog.Title.Dark">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Title2.Dark</item>
-    </style>
-    <style name="Widget.Car.Dialog.Title.Light">
-        <item name="android:textAppearance">@style/TextAppearance.Car.Title2.Light</item>
-    </style>
-    <style name="Widget.Car.DrawerArrowToggle" parent="Widget.AppCompat.DrawerArrowToggle">
-        <item name="color">@color/car_title_light</item>
-        <item name="spinBars">true</item>
-        <item name="barLength">@dimen/car_menu_bar_length</item>
-        <item name="thickness">@dimen/car_arrow_thickness</item>
-        <item name="gapBetweenBars">@dimen/car_menu_bar_spacing</item>
-        <item name="arrowShaftLength">@dimen/car_arrow_shaft_length</item>
-        <item name="arrowHeadLength">@dimen/car_arrow_head_length</item>
-        <item name="drawableSize">@dimen/car_arrow_size</item>
-    </style>
-    <style name="Widget.Car.EditText" parent="Widget.AppCompat.EditText">
-        <item name="android:textColor">?attr/editTextColor</item>
-        <item name="android:textAppearance">@style/TextAppearance.Car.Body1</item>
-    </style>
-    <style name="Widget.Car.Light.List" parent="Widget.Car.List">
-        <item name="dayNightStyle">force_night</item>
-    </style>
-    <style name="Widget.Car.Light.List.LightDivider">
-        <item name="listDividerColor">@color/car_list_divider_light</item>
-    </style>
-    <style name="Widget.Car.List" parent="android:Widget">
-        <item name="dayNightStyle">auto</item>
-        <item name="listDividerColor">@color/car_list_divider</item>
-    </style>
-    <style name="Widget.Car.List.Inverse">
-        <item name="dayNightStyle">auto_inverse</item>
-        <item name="listDividerColor">@color/car_list_divider_inverse</item>
-    </style>
-    <style name="Widget.Car.ListItem" parent="android:Widget">
-        <item name="listItemBackgroundColor">@color/car_card</item>
-        <item name="listItemTitleTextAppearance">@style/TextAppearance.Car.Body1</item>
-        <item name="listItemBodyTextAppearance">@style/TextAppearance.Car.Body2</item>
-    </style>
-    <style name="Widget.Car.ListItem.Dark">
-        <item name="listItemBackgroundColor">@color/car_card_dark</item>
-        <item name="listItemTitleTextAppearance">@style/TextAppearance.Car.Body1.Light</item>
-        <item name="listItemBodyTextAppearance">@style/TextAppearance.Car.Body2.Light</item>
-    </style>
-    <style name="Widget.Car.ProgressBar.Horizontal" parent="Widget.AppCompat.ProgressBar.Horizontal">
-        <item name="android:minHeight">@dimen/car_progress_bar_height</item>
-        <item name="android:maxHeight">@dimen/car_progress_bar_height</item>
-    </style>
-    <style name="Widget.Car.SeekBar" parent="Widget.AppCompat.SeekBar">
-        <item name="android:progressDrawable">@drawable/car_seekbar_track</item>
-        <item name="android:thumb">@drawable/car_seekbar_thumb</item>
-    </style>
-    <style name="Widget.Car.Toolbar" parent="Widget.AppCompat.Toolbar">
-        <item name="titleTextAppearance">@style/TextAppearance.Car.Title.Light</item>
-        <item name="contentInsetStart">@dimen/car_keyline_1</item>
-        <item name="contentInsetEnd">@dimen/car_keyline_1</item>
-    </style>
-</resources>
\ No newline at end of file
diff --git a/androidx-car/Android.bp b/androidx-car/Android.bp
new file mode 100644
index 0000000..8d1eee6
--- /dev/null
+++ b/androidx-car/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2020 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.
+
+android_library_import {
+    name: "androidx.car_car-resources-partially-dejetified-nodeps",
+    aars: ["androidx-car-resources.aar"],
+    sdk_version: "current",
+    static_libs: [
+        "com.google.android.material_material",
+        "androidx.appcompat_appcompat",
+        "androidx.cardview_cardview",
+        "androidx.recyclerview_recyclerview",
+        "androidx.gridlayout_gridlayout",
+        "androidx.preference_preference",
+        "androidx-constraintlayout_constraintlayout",
+    ],
+}
+android_library {
+    name: "androidx.car_car-resources-partially-dejetified",
+    sdk_version: "current",
+    min_sdk_version: "21",
+    manifest: "AndroidManifest.xml",
+    static_libs: [
+        "androidx.car_car-resources-partially-dejetified-nodeps",
+        "com.google.android.material_material",
+        "androidx.appcompat_appcompat",
+        "androidx.cardview_cardview",
+        "androidx.recyclerview_recyclerview",
+        "androidx.gridlayout_gridlayout",
+        "androidx.preference_preference",
+        "androidx-constraintlayout_constraintlayout",
+    ],
+    java_version: "1.7",
+}
diff --git a/androidx-car/AndroidManifest.xml b/androidx-car/AndroidManifest.xml
new file mode 100644
index 0000000..87ef2c9
--- /dev/null
+++ b/androidx-car/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.car" >
+
+    <uses-sdk
+        android:minSdkVersion="21"
+        android:targetSdkVersion="28" />
+
+</manifest>
diff --git a/androidx-car/androidx-car-resources.aar b/androidx-car/androidx-car-resources.aar
new file mode 100755
index 0000000..8f8aeaf
--- /dev/null
+++ b/androidx-car/androidx-car-resources.aar
Binary files differ
diff --git a/androidx-room/Android.bp b/androidx-room/Android.bp
deleted file mode 100644
index f9ac357..0000000
--- a/androidx-room/Android.bp
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// 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.
-//
-
-java_plugin {
-    name: "car-androidx-room-compiler",
-    static_libs: [
-        "car-androidx-annotation-nodeps-bp",
-        "car-androidx-room-common-nodeps-bp",
-        "car-androidx-room-compiler-nodeps-bp",
-        "car-androidx-room-compiler-tools-common-m2-deps",
-        "car-androidx-room-migration-nodeps-bp",
-        "kotlin-stdlib",
-    ],
-    processor_class: "androidx.room.RoomProcessor",
-    generates_api: true,
-}
-
-android_library_import {
-    name: "car-androidx-room-runtime-nodeps-bp",
-    aars: ["androidx.room/room-runtime-2.0.0-alpha1.aar"],
-    sdk_version: "current",
-}
-
-java_import {
-    name: "car-androidx-room-common-nodeps-bp",
-    jars: ["androidx.room/room-common-2.0.0-alpha1.jar"],
-    host_supported: true,
-}
-
-java_import_host {
-    name: "car-androidx-room-compiler-nodeps-bp",
-    jars: ["androidx.room/room-compiler-2.0.0-alpha1.jar"],
-}
-
-java_import_host {
-    name: "car-androidx-room-migration-nodeps-bp",
-    jars: ["androidx.room/room-migration-2.0.0-alpha1.jar"],
-}
-
-java_import_host {
-    name: "car-androidx-annotation-nodeps-bp",
-    jars: ["annotation-1.0.0-alpha1.jar"],
-}
diff --git a/androidx-room/Android.mk b/androidx-room/Android.mk
deleted file mode 100644
index 675dac8..0000000
--- a/androidx-room/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-    car-androidx-room-runtime-nodeps:androidx.room/room-runtime-2.0.0-alpha1.aar \
-    car-androidx-room-common-nodeps:androidx.room/room-common-2.0.0-alpha1.jar
-
-include $(BUILD_MULTI_PREBUILT)
-
-include $(CLEAR_VARS)
-
-COMMON_LIBS_PATH := ../../../../../prebuilts/tools/common/m2/repository
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-    car-androidx-room-common-nodeps:androidx.room/room-common-2.0.0-alpha1.jar \
-    car-androidx-room-compiler-nodeps:androidx.room/room-compiler-2.0.0-alpha1.jar \
-    car-androidx-room-migration-nodeps:androidx.room/room-migration-2.0.0-alpha1.jar \
-    car-androidx-annotation-nodeps:annotation-1.0.0-alpha1.jar \
-    car-antlr4-nodeps:$(COMMON_LIBS_PATH)/org/antlr/antlr4/4.5.3/antlr4-4.5.3.jar \
-    car-apache-commons-codec-nodeps:$(COMMON_LIBS_PATH)/org/eclipse/tycho/tycho-bundles-external/0.18.1/eclipse/plugins/org.apache.commons.codec_1.4.0.v201209201156.jar \
-    car-auto-common-nodeps:$(COMMON_LIBS_PATH)/com/google/auto/auto-common/0.9/auto-common-0.9.jar \
-    car-javapoet-nodeps:$(COMMON_LIBS_PATH)/com/squareup/javapoet/1.8.0/javapoet-1.8.0.jar \
-    car-jetbrains-annotations-nodeps:$(COMMON_LIBS_PATH)/org/jetbrains/annotations/13.0/annotations-13.0.jar \
-    car-kotlin-metadata-nodeps:$(COMMON_LIBS_PATH)/me/eugeniomarletti/kotlin-metadata/1.2.1/kotlin-metadata-1.2.1.jar \
-    car-sqlite-jdbc-nodeps:$(COMMON_LIBS_PATH)/org/xerial/sqlite-jdbc/3.20.1/sqlite-jdbc-3.20.1.jar
-
-include $(BUILD_HOST_PREBUILT)
diff --git a/androidx-room/androidx.room/room-common-2.0.0-alpha1.jar b/androidx-room/androidx.room/room-common-2.0.0-alpha1.jar
deleted file mode 100644
index 2c09fdf..0000000
--- a/androidx-room/androidx.room/room-common-2.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/androidx.room/room-compiler-2.0.0-alpha1.jar b/androidx-room/androidx.room/room-compiler-2.0.0-alpha1.jar
deleted file mode 100644
index a95872d..0000000
--- a/androidx-room/androidx.room/room-compiler-2.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/androidx.room/room-migration-2.0.0-alpha1.jar b/androidx-room/androidx.room/room-migration-2.0.0-alpha1.jar
deleted file mode 100644
index 4851df9..0000000
--- a/androidx-room/androidx.room/room-migration-2.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/androidx.room/room-runtime-2.0.0-alpha1.aar b/androidx-room/androidx.room/room-runtime-2.0.0-alpha1.aar
deleted file mode 100644
index ca797dd..0000000
--- a/androidx-room/androidx.room/room-runtime-2.0.0-alpha1.aar
+++ /dev/null
Binary files differ
diff --git a/androidx-room/annotation-1.0.0-alpha1.jar b/androidx-room/annotation-1.0.0-alpha1.jar
deleted file mode 100644
index 3bfd348..0000000
--- a/androidx-room/annotation-1.0.0-alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/Android.bp b/car-apps-common/Android.bp
index dae4a15..4f9ef51 100644
--- a/car-apps-common/Android.bp
+++ b/car-apps-common/Android.bp
@@ -13,8 +13,9 @@
 // limitations under the License.
 //
 
+// Unbundled target (should stay that way).
 android_library {
-    name: "car-apps-common-bp",
+    name: "car-apps-common",
 
     srcs: ["src/**/*.java"],
 
@@ -25,7 +26,9 @@
     },
 
     libs: ["android.car-stubs",],
-    min_sdk_version: "29",
+
+    sdk_version: "system_current",
+    min_sdk_version: "28",
 
     static_libs: [
         "androidx.annotation_annotation",
@@ -36,5 +39,6 @@
         "androidx-constraintlayout_constraintlayout",
         "androidx.recyclerview_recyclerview",
         "androidx-constraintlayout_constraintlayout-solver",
+        "car-ui-lib",
     ],
 }
diff --git a/car-apps-common/Android.mk b/car-apps-common/Android.mk
deleted file mode 100644
index ce96f11..0000000
--- a/car-apps-common/Android.mk
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-apps-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.annotation_annotation \
-    androidx.cardview_cardview \
-    androidx.interpolator_interpolator \
-    androidx.lifecycle_lifecycle-common-java8 \
-    androidx.lifecycle_lifecycle-extensions \
-    androidx-constraintlayout_constraintlayout \
-    androidx.recyclerview_recyclerview
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    androidx-constraintlayout_constraintlayout-solver
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/car-ui-lib/res/color/car_ui_text_color_primary.xml b/car-apps-common/res/color/primary_text_color.xml
similarity index 100%
copy from car-ui-lib/res/color/car_ui_text_color_primary.xml
copy to car-apps-common/res/color/primary_text_color.xml
diff --git a/car-ui-lib/res/color/car_ui_text_color_secondary.xml b/car-apps-common/res/color/secondary_text_color.xml
similarity index 100%
copy from car-ui-lib/res/color/car_ui_text_color_secondary.xml
copy to car-apps-common/res/color/secondary_text_color.xml
diff --git a/car-apps-common/res/color/uxr_button_text_color_selector.xml b/car-apps-common/res/color/uxr_button_text_color_selector.xml
deleted file mode 100644
index 08b64e1..0000000
--- a/car-apps-common/res/color/uxr_button_text_color_selector.xml
+++ /dev/null
@@ -1,22 +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.
-  -->
-
-<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_text_disabled_color"/>
-    <item app:state_ux_restricted="false" android:color="@color/uxr_button_text_color"/>
-</selector>
diff --git a/car-apps-common/res/drawable-hdpi/ic_contact.png b/car-apps-common/res/drawable-hdpi/ic_contact.png
deleted file mode 100644
index c34e844..0000000
--- a/car-apps-common/res/drawable-hdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable-mdpi/ic_contact.png b/car-apps-common/res/drawable-mdpi/ic_contact.png
deleted file mode 100644
index 9461076..0000000
--- a/car-apps-common/res/drawable-mdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable-xhdpi/ic_contact.png b/car-apps-common/res/drawable-xhdpi/ic_contact.png
deleted file mode 100644
index fec660d..0000000
--- a/car-apps-common/res/drawable-xhdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable-xxhdpi/ic_contact.png b/car-apps-common/res/drawable-xxhdpi/ic_contact.png
deleted file mode 100644
index 199fd7b..0000000
--- a/car-apps-common/res/drawable-xxhdpi/ic_contact.png
+++ /dev/null
Binary files differ
diff --git a/car-apps-common/res/drawable/car_button_ripple_background.xml b/car-apps-common/res/drawable/car_button_ripple_background.xml
deleted file mode 100644
index 3975d12..0000000
--- a/car-apps-common/res/drawable/car_button_ripple_background.xml
+++ /dev/null
@@ -1,19 +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.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@*android:color/car_card_ripple_background" />
diff --git a/car-apps-common/res/drawable/car_card_ripple_background.xml b/car-apps-common/res/drawable/car_card_ripple_background.xml
deleted file mode 100644
index 6b8a041..0000000
--- a/car-apps-common/res/drawable/car_card_ripple_background.xml
+++ /dev/null
@@ -1,23 +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.
-  -->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@*android:color/car_card_ripple_background">
-  <item
-      android:id="@android:id/mask"
-      android:drawable="@*android:color/white" />
-</ripple>
diff --git a/car-apps-common/res/drawable/car_scrollbar_thumb.xml b/car-apps-common/res/drawable/car_scrollbar_thumb.xml
deleted file mode 100644
index 0464f2f..0000000
--- a/car-apps-common/res/drawable/car_scrollbar_thumb.xml
+++ /dev/null
@@ -1,23 +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
-  -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-  <solid android:color="@*android:color/car_scrollbar_thumb" />
-  <corners android:radius="@*android:dimen/car_radius_5"/>
-</shape>
diff --git a/car-apps-common/res/drawable/control_bar_button_background.xml b/car-apps-common/res/drawable/control_bar_button_background.xml
index 0412fd3..09bd38a 100644
--- a/car-apps-common/res/drawable/control_bar_button_background.xml
+++ b/car-apps-common/res/drawable/control_bar_button_background.xml
@@ -16,7 +16,28 @@
   ~ limitations under the License.
   ~
  -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@color/control_bar_button_background_color"
-        android:radius="@dimen/control_bar_button_background_radius">
-</ripple>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:state_pressed="true">
+        <shape android:shape="oval">
+            <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/>
+            <stroke android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width"
+                    android:color="@color/car_ui_rotary_focus_pressed_stroke_color" />
+            <size android:width="@dimen/control_bar_button_background_radius"
+                  android:height="@dimen/control_bar_button_background_radius"/>
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape android:shape="oval">
+            <solid android:color="@color/car_ui_rotary_focus_fill_color"/>
+            <stroke android:width="@dimen/car_ui_rotary_focus_stroke_width"
+                    android:color="@color/car_ui_rotary_focus_stroke_color" />
+            <size android:width="@dimen/control_bar_button_background_radius"
+                  android:height="@dimen/control_bar_button_background_radius"/>
+        </shape>
+    </item>
+    <item>
+        <ripple android:color="@color/control_bar_button_background_color"
+                android:radius="@dimen/control_bar_button_background_radius">
+        </ripple>
+    </item>
+</selector>
diff --git a/car-apps-common/res/drawable/hero_button_background.xml b/car-apps-common/res/drawable/hero_button_background.xml
index 15e9b2a..e5aeec5 100644
--- a/car-apps-common/res/drawable/hero_button_background.xml
+++ b/car-apps-common/res/drawable/hero_button_background.xml
@@ -13,12 +13,31 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@*android:color/car_card_ripple_background">
-    <item>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:state_pressed="true">
         <shape android:shape="rectangle">
-            <solid android:color="@color/hero_button_background_color" />
+            <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/>
+            <stroke android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width"
+                    android:color="@color/car_ui_rotary_focus_pressed_stroke_color" />
             <corners android:radius="@dimen/hero_button_corner_radius"/>
         </shape>
     </item>
-</ripple>
+    <item android:state_focused="true">
+        <shape android:shape="rectangle">
+            <solid android:color="@color/car_ui_rotary_focus_fill_color"/>
+            <stroke android:width="@dimen/car_ui_rotary_focus_stroke_width"
+                    android:color="@color/car_ui_rotary_focus_stroke_color" />
+            <corners android:radius="@dimen/hero_button_corner_radius"/>
+        </shape>
+    </item>
+    <item>
+        <ripple android:color="@color/car_card_ripple_background">
+            <item>
+                <shape android:shape="rectangle">
+                    <solid android:color="@color/hero_button_background_color" />
+                    <corners android:radius="@dimen/hero_button_corner_radius"/>
+                </shape>
+            </item>
+        </ripple>
+    </item>
+</selector>
diff --git a/car-apps-common/res/layout/car_paged_scrollbar_buttons.xml b/car-apps-common/res/layout/car_paged_scrollbar_buttons.xml
deleted file mode 100644
index 4a0ccae..0000000
--- a/car-apps-common/res/layout/car_paged_scrollbar_buttons.xml
+++ /dev/null
@@ -1,53 +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.
-  -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="center">
-
-  <ImageButton
-      android:id="@+id/page_up"
-      android:layout_width="@dimen/car_scroll_bar_button_size"
-      android:layout_height="@dimen/car_scroll_bar_button_size"
-      android:background="@drawable/car_button_ripple_background"
-      android:contentDescription="@string/scroll_bar_page_up_button"
-      android:focusable="false"
-      android:hapticFeedbackEnabled="false"
-      android:src="@drawable/ic_up"
-      android:scaleType="centerInside" />
-
-  <!-- View height is dynamically calculated during layout. -->
-  <View
-      android:id="@+id/scrollbar_thumb"
-      android:layout_width="@dimen/car_scroll_bar_thumb_width"
-      android:layout_height="0dp"
-      android:layout_gravity="center_horizontal"
-      android:background="@drawable/car_scrollbar_thumb" />
-
-  <ImageButton
-      android:id="@+id/page_down"
-      android:layout_width="@dimen/car_scroll_bar_button_size"
-      android:layout_height="@dimen/car_scroll_bar_button_size"
-      android:background="@drawable/car_button_ripple_background"
-      android:contentDescription="@string/scroll_bar_page_down_button"
-      android:focusable="false"
-      android:hapticFeedbackEnabled="false"
-      android:src="@drawable/ic_down"
-      android:scaleType="centerInside" />
-</LinearLayout>
diff --git a/car-apps-common/res/layout/minimized_control_bar.xml b/car-apps-common/res/layout/minimized_control_bar.xml
index 814fe15..286af0f 100644
--- a/car-apps-common/res/layout/minimized_control_bar.xml
+++ b/car-apps-common/res/layout/minimized_control_bar.xml
@@ -28,7 +28,7 @@
         android:id="@+id/metadata_background"
         android:layout_width="0dp"
         android:layout_height="0dp"
-        android:background="@drawable/car_card_ripple_background"
+        android:background="?android:attr/selectableItemBackground"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
diff --git a/car-apps-common/res/values-h600dp/dimens.xml b/car-apps-common/res/values-h600dp/dimens.xml
deleted file mode 100644
index dcbea47..0000000
--- a/car-apps-common/res/values-h600dp/dimens.xml
+++ /dev/null
@@ -1,22 +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.
--->
-<resources>
-    <dimen name="control_bar_button_background_radius">48dp</dimen>
-    <dimen name="control_bar_button_size">96dp</dimen>
-    <dimen name="control_bar_button_padding">26dp</dimen>
-    <dimen name="minimized_control_bar_button_size">96dp</dimen>
-</resources>
diff --git a/car-apps-common/res/values-night/colors.xml b/car-apps-common/res/values-night/colors.xml
index 6a2f4cf..a0a9c3a 100644
--- a/car-apps-common/res/values-night/colors.xml
+++ b/car-apps-common/res/values-night/colors.xml
@@ -21,9 +21,6 @@
     <color name="scrim_overlay_color">#D6000000</color>
     <color name="minimized_control_bar_background_color">#E00E1013</color>
 
-    <color name="primary_text_color">#E0FFFFFF</color>
-    <color name="secondary_text_color">#99FFFFFF</color>
-
     <color name="primary_app_icon_color">#E0FFFFFF</color>
     <color name="secondary_app_icon_color">#99FFFFFF</color>
 
diff --git a/car-apps-common/res/values-port/dimens.xml b/car-apps-common/res/values-port/dimens.xml
index c46b0b6..e7b2546 100644
--- a/car-apps-common/res/values-port/dimens.xml
+++ b/car-apps-common/res/values-port/dimens.xml
@@ -21,5 +21,5 @@
     <dimen name="car_tab_width">-2px</dimen>
 
     <!-- Control Bar - typically at the bottom of the application's space. -->
-    <dimen name="control_bar_margin_x">@*android:dimen/car_padding_5</dimen>
+    <dimen name="control_bar_margin_x">@dimen/car_ui_padding_5</dimen>
 </resources>
diff --git a/car-apps-common/res/values-w1280dp/styles.xml b/car-apps-common/res/values-w1280dp/styles.xml
index c810097..71af982 100644
--- a/car-apps-common/res/values-w1280dp/styles.xml
+++ b/car-apps-common/res/values-w1280dp/styles.xml
@@ -20,4 +20,9 @@
         <item name="android:layout_width">@dimen/control_bar_width</item>
         <item name="android:layout_height">wrap_content</item>
     </style>
+
+    <style name="MinimizedControlBar">
+        <item name="android:layout_width">@dimen/control_bar_width</item>
+        <item name="android:layout_height">@dimen/minimized_control_bar_height</item>
+    </style>
 </resources>
diff --git a/car-apps-common/res/values/attrs.xml b/car-apps-common/res/values/attrs.xml
index c7b3541..0f953ee 100644
--- a/car-apps-common/res/values/attrs.xml
+++ b/car-apps-common/res/values/attrs.xml
@@ -37,52 +37,6 @@
         <attr name="textAppearanceGridItemSecondary" format="reference" />
     </declare-styleable>
 
-    <!-- Attributes for tab layout. -->
-    <declare-styleable name="CarTabLayout">
-        <attr name="tabPaddingX" format="reference|dimension"/>
-        <attr name="tabFlexibleLayout" format="reference|boolean"/>
-        <attr name="tabItemLayout" format="reference"/>
-    </declare-styleable>
-
-    <declare-styleable name="PagedRecyclerView">
-        <!-- Whether to include a gutter to the start, end or both sides of the list view items.
-             The gutter width will be the width of the scrollbar, and by default will be set to
-             both. -->
-        <attr name="gutter" format="enum">
-            <!-- No gutter on either side, the list view items will extend the full width of the
-                 PagedRecyclerView. -->
-            <enum name="none" value="0" />
-            <!-- Include a gutter on the start side only (i.e. the side with the scrollbar). -->
-            <enum name="start" value="1" />
-            <!-- Include a gutter on the end side only (i.e. the opposite side to the
-                 scrollbar). -->
-            <enum name="end" value="2" />
-            <!-- Include a gutter on both sides of the list view items. -->
-            <enum name="both" value="3" />
-        </attr>
-        <!-- Position of the scrollbar. Default to left. -->
-        <attr name="scrollBarPosition" format="enum">
-            <!-- Position scrollbar on the left side of the screen -->
-            <enum name="start" value="0" />
-            <!-- Position scrollbar on the right side of the screen -->
-            <enum name="end" value="1" />
-        </attr>
-        <!-- Whether to display the Scroll Bar or not. Defaults to true. If this is set to false,
-             the PagedRecyclerView will behave exactly like the RecyclerView. -->
-        <attr name="scrollBarEnabled" format="boolean" />
-        <!-- Whether to place the scrollbar z-index above the recycler view. Defaults to
-             true. -->
-        <attr name="scrollBarAboveRecyclerView" format="boolean" />
-        <!-- Width of the scrollbar container. -->
-        <attr name="scrollBarContainerWidth" format="dimension" />
-        <!-- Custom Scrollbar class path -->
-        <attr name="scrollBarCustomClass" format="string" />
-    </declare-styleable>
-
-    <declare-styleable name="PagedRecyclerViewTheme">
-        <attr name="pagedRecyclerViewStyle" format="reference" />
-    </declare-styleable>
-
     <declare-styleable name="CrossfadeImageView">
         <attr name="align_horizontal" format="enum">
             <enum name="center" value="0"/>
@@ -113,6 +67,16 @@
     <declare-styleable name="BackgroundImageView">
         <!-- Sets a scale to be applied on top of the scaling that was used to fit the image to the frame of the view. Defaults to 1.05 -->
         <attr name="imageAdditionalScale" format="float"/>
+
+        <!-- The layout to load as background. Defaults to R.layout.background_image. -->
+        <attr name="contentLayout" format="reference"/>
+
+        <!-- The strength of the blur. Defaults to R.dimen.background_bitmap_blur_percent. -->
+        <attr name="bitmap_blur_percent" format="float"/>
+
+        <!-- Size for the image. Defaults to R.integer.background_bitmap_target_size_px. -->
+        <attr name="bitmap_target_size_px" format="integer"/>
+
     </declare-styleable>
     <!-- Attribute for specifying a default style for all BackgroundImageViews -->
     <attr name="backgroundImageViewStyle" format="reference"/>
diff --git a/car-apps-common/res/values/colors.xml b/car-apps-common/res/values/colors.xml
index 37a7bda..45a0a18 100644
--- a/car-apps-common/res/values/colors.xml
+++ b/car-apps-common/res/values/colors.xml
@@ -34,14 +34,14 @@
         <item>#757575</item>
     </array>
 
-    <color name="loading_image_placeholder_color">@*android:color/car_grey_800</color>
+    <color name="loading_image_placeholder_color">@color/car_grey_800</color>
     <color name="improper_image_refs_tint_color">#C8FF0000</color>
 
     <color name="control_bar_background_color">@android:color/transparent</color>
-    <color name="minimized_control_bar_background_color">#F50E1013</color>
+    <color name="minimized_control_bar_background_color">#D60E1013</color>
     <color name="scrim_overlay_color">#C7000000</color>
     <color name="app_bar_background_color">#E0000000</color>
-    <color name="icon_tint">@*android:color/car_tint</color>
+    <color name="icon_tint">@color/car_grey_50</color>
 
     <color name="car_tab_selected_color">@color/car_tab_selected_color_light</color>
     <color name="car_tab_selected_color_dark">#E2FFFFFF</color>
@@ -50,24 +50,52 @@
     <color name="car_tab_unselected_color_dark">#80FFFFFF</color>
     <color name="car_tab_unselected_color_light">#90FFFFFF</color>
 
-    <color name="primary_text_color">#FFFFFFFF</color>
-    <color name="secondary_text_color">#B8FFFFFF</color>
-
     <color name="primary_app_icon_color">#FFFFFFFF</color>
     <color name="secondary_app_icon_color">#B8FFFFFF</color>
-    <color name="car_tint_inverse">@*android:color/car_tint_inverse</color>
-    <color name="car_scrollbar_thumb_inverse">@*android:color/car_scrollbar_thumb_dark</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_text_color">@color/primary_text_color</color>
     <color name="uxr_button_image_disabled_color">#80FFFFFF</color>
-    <color name="uxr_button_text_disabled_color">#80FFFFFF</color>
 
     <color name="control_bar_button_background_color">#66ffffff</color>
 
-    <color name="hero_button_background_color">@*android:color/car_grey_868</color>
-    <color name="hero_button_text_color">@color/uxr_button_text_color_selector</color>
+    <color name="hero_button_background_color">@color/car_grey_868</color>
+    <color name="hero_button_text_color">@color/primary_text_color</color>
+
+
+
+    <!--
+        Color palette for cars.
+        Those values are NOT part of the car-ui-lib "resource API", they are just constants used in
+        various places to give a default value to the attributes of the "api".
+     -->
+    <color name="car_grey_972">#ff090A0C</color>
+    <color name="car_grey_958">#ff0e1013</color>
+    <color name="car_grey_928">#ff17181b</color>
+    <color name="car_grey_900">#ff202124</color>
+    <color name="car_grey_868">#ff282a2d</color>
+    <color name="car_grey_846">#ff2e3234</color>
+    <color name="car_grey_800">#ff3c4043</color>
+    <color name="car_grey_772">#ff464a4d</color>
+    <color name="car_grey_746">#ff4d5256</color>
+    <color name="car_grey_700">#ff5f6368</color>
+    <color name="car_grey_600">#ff80868b</color>
+    <color name="car_grey_500">#ff9aa0a6</color>
+    <color name="car_grey_400">#ffbdc1c6</color>
+    <color name="car_grey_300">#ffdadce0</color>
+    <color name="car_grey_200">#ffe8eaed</color>
+    <color name="car_grey_100">#fff1f3f4</color>
+    <color name="car_grey_50">#fff8f9fa</color>
+
+    <color name="car_dark_blue_grey_700">#ff172026</color>
+
+    <color name="car_green_700">#ff218c48</color>
+    <color name="car_green_500">#ff41af6a</color>
+
+    <color name="car_red_500a">#ffd50000</color>
+
+    <!-- End color palette -->
+
 </resources>
diff --git a/car-apps-common/res/values/config.xml b/car-apps-common/res/values/config.xml
index 68a0fa1..eecb9ea 100644
--- a/car-apps-common/res/values/config.xml
+++ b/car-apps-common/res/values/config.xml
@@ -15,16 +15,6 @@
   ~ limitations under the License
   -->
 <resources>
-    <!--
-    Configuration for a default scrollbar for the PagedRecyclerView. This component must inherit
-    abstract class ScrollBarUI. If the ScrollBar is enabled, the component will be initialized from
-    PagedRecyclerView#createScrollBarFromConfig().
-    -->
-    <string name="config_scrollBarComponent" translatable="false">
-        com.android.car.apps.common.widget.CarScrollBar
-    </string>
-
-
     <!-- This value must remain false for production builds. It is intended to be overlaid in
         the simulator, so third party app developers can notice quickly that they are sending
         improper image references.
@@ -42,6 +32,14 @@
     -->
     <integer name="config_number_of_letters_shown_for_avatar">1</integer>
 
+    <!-- A default mask to apply to icons cropped via IconCropper. The mask is defined as
+     an SVG path in the range of [0..100, 0..100], it is automatically scaled to fit
+     the actual icon size, following the adaptive icon definition guideline:
+     https://source.android.com/devices/tech/display/adaptive-icons#implementation -->
+    <string name="config_crop_icon_mask" translatable="false">
+        M0,50 a50,50 0 1,0 100,0 a50,50 0 1,0 -100,0
+    </string>
+
     <!-- String format used to format a address Uri. -->
     <string name="config_address_uri_format" translatable="false">geo:0,0?q=%s</string>
     <!-- String format used to format a navigation Uri. -->
diff --git a/car-apps-common/res/values/dimens.xml b/car-apps-common/res/values/dimens.xml
index b1a51f5..c87fa6b 100644
--- a/car-apps-common/res/values/dimens.xml
+++ b/car-apps-common/res/values/dimens.xml
@@ -20,18 +20,18 @@
     <dimen name="fab_focused_stroke_width">8dp</dimen>
     <dimen name="fab_focused_growth">1.2dp</dimen>
 
-    <dimen name="touch_target_size">@*android:dimen/car_touch_target_size</dimen>
+    <dimen name="touch_target_size">@dimen/car_ui_touch_target_size</dimen>
 
     <!-- Control Bar - typically at the bottom of the application's space. -->
     <dimen name="control_bar_height">128dp</dimen>
-    <dimen name="control_bar_margin_x">@*android:dimen/car_margin</dimen>
-    <dimen name="control_bar_margin_bottom">@*android:dimen/car_padding_2</dimen>
-    <dimen name="control_bar_button_size">76dp</dimen>
+    <dimen name="control_bar_margin_x">@dimen/car_ui_margin</dimen>
+    <dimen name="control_bar_margin_bottom">@dimen/car_ui_padding_2</dimen>
+    <dimen name="control_bar_button_size">104dp</dimen>
     <dimen name="control_bar_button_slot_height">@dimen/control_bar_height</dimen>
     <dimen name="control_bar_button_slot_width">@dimen/control_bar_button_size</dimen>
     <dimen name="control_bar_elevation">0dp</dimen>
-    <dimen name="control_bar_button_padding">16dp</dimen>
-    <dimen name="control_bar_button_background_radius">38dp</dimen>
+    <dimen name="control_bar_button_padding">30dp</dimen>
+    <dimen name="control_bar_button_background_radius">52dp</dimen>
 
     <!-- Overflow button in control Bar -->
     <dimen name="overflow_button_icon_size">44dp</dimen>
@@ -43,10 +43,10 @@
     <dimen name="minimized_control_bar_radius">0dp</dimen>
     <dimen name="minimized_control_bar_margin_x">0dp</dimen>
     <dimen name="minimized_control_bar_margin_bottom">0dp</dimen>
-    <dimen name="minimized_control_bar_edge_padding">@*android:dimen/car_padding_4</dimen>
-    <dimen name="minimized_control_bar_text_padding">@*android:dimen/car_padding_3</dimen>
-    <dimen name="minimized_control_bar_button_padding">@*android:dimen/car_padding_5</dimen>
-    <dimen name="minimized_control_bar_button_size">76dp</dimen>
+    <dimen name="minimized_control_bar_edge_padding">@dimen/car_ui_padding_4</dimen>
+    <dimen name="minimized_control_bar_text_padding">@dimen/car_ui_padding_3</dimen>
+    <dimen name="minimized_control_bar_button_padding">@dimen/car_ui_padding_5</dimen>
+    <dimen name="minimized_control_bar_button_size">104dp</dimen>
 
     <!-- Tabs -->
     <dimen name="car_tab_width">135dp</dimen>
@@ -61,16 +61,6 @@
     <item name="letter_spacing_body2" format="float" type="dimen">0.0</item>
     <item name="letter_spacing_body3" format="float" type="dimen">0.0</item>
 
-    <!-- Default Scroll Bar for PagedRecyclerView -->
-    <dimen name="car_scroll_bar_button_size">@*android:dimen/car_touch_target_size</dimen>
-    <dimen name="car_scroll_bar_thumb_width">@*android:dimen/car_seekbar_height</dimen>
-    <dimen name="car_scroll_bar_separator_margin">@*android:dimen/car_padding_2</dimen>
-    <dimen name="car_scroll_bar_margin">@*android:dimen/car_margin</dimen>
-    <item name="button_disabled_alpha" format="float" type="dimen">0.2</item>
-    <item name="scroller_milliseconds_per_inch" format="float" type="dimen">150</item>
-    <item name="scroller_deceleration_time_divisor" format="float" type="dimen">0.45</item>
-    <item name="scroller_interpolator_factor" format="float" type="dimen">1.8</item>
-
     <!-- Target size for the background bitmap to blur (in pixels) -->
     <integer name="background_bitmap_target_size_px">64</integer>
     <!-- Value used to blur background images, the blur radius is P * (W + H)/2.
diff --git a/car-apps-common/res/values/id.xml b/car-apps-common/res/values/id.xml
index 82905b8..548e7cc 100644
--- a/car-apps-common/res/values/id.xml
+++ b/car-apps-common/res/values/id.xml
@@ -3,4 +3,6 @@
     <item type="id" name="imageDownloadTask"/>
     <item type="id" name="car_tab_item_icon"/>
     <item type="id" name="car_tab_item_text"/>
+    <item type="id" name="minimized_control_bar_content_tile"/>
+    <item type="id" name="art_background"/>
 </resources>
\ No newline at end of file
diff --git a/car-apps-common/res/values/styles.xml b/car-apps-common/res/values/styles.xml
index 73457af..3b5a5d6 100644
--- a/car-apps-common/res/values/styles.xml
+++ b/car-apps-common/res/values/styles.xml
@@ -122,14 +122,6 @@
         <item name="android:layout_height">@dimen/minimized_control_bar_height</item>
     </style>
 
-    <style name="PagedRecyclerView">
-        <item name="gutter">both</item>
-        <item name="scrollBarPosition">start</item>
-        <item name="scrollBarAboveRecyclerView">true</item>
-    </style>
-    <style name="PagedRecyclerView.NestedRecyclerView">
-    </style>
-
     <style name="FullScreenErrorMessageStyle">
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
diff --git a/car-apps-common/src/com/android/car/apps/common/AccountImageHelper.java b/car-apps-common/src/com/android/car/apps/common/AccountImageHelper.java
deleted file mode 100644
index 97286ce..0000000
--- a/car-apps-common/src/com/android/car/apps/common/AccountImageHelper.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2016 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.car.apps.common;
-
-import android.accounts.Account;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Intent.ShortcutIconResource;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-
-/**
- * Utility functions for retrieving account pictures.
- * @hide
- */
-public final class AccountImageHelper {
-
-    static final String[] CONTACT_PROJECTION_DATA = new String[] {
-        ContactsContract.Data._ID,
-        ContactsContract.Data.CONTACT_ID,
-        ContactsContract.Data.RAW_CONTACT_ID,
-        ContactsContract.Data.LOOKUP_KEY,
-        ContactsContract.Data.PHOTO_URI,
-        ContactsContract.Data.PHOTO_FILE_ID
-    };
-    static final String CONTACT_SELECTION =
-            ContactsContract.CommonDataKinds.Email.ADDRESS + " LIKE ?";
-
-    /**
-     * Non instantiable.
-     */
-    private AccountImageHelper() {
-    }
-
-    /**
-     * Tries to retrieve the Picture for the provided account, from the Contacts database.
-     */
-    public static String getAccountPictureUri(Context context, Account account) {
-        // Look up this account in the contacts database.
-
-        String[] selectionArgs = new String[] {
-        account.name };
-        Cursor c = null;
-        long contactId = -1;
-        String lookupKey = null;
-        String photoUri = null;
-        int photoFileId = 0;
-        long rawContactId = 0;
-        try {
-            c = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
-                    CONTACT_PROJECTION_DATA, CONTACT_SELECTION, selectionArgs, null);
-            if (c.moveToNext()) {
-                contactId = c.getLong(1);
-                rawContactId = c.getLong(2);
-                lookupKey = c.getString(3);
-                photoUri = c.getString(4);
-                photoFileId = c.getInt(5);
-            }
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-
-        if (contactId != -1 && !TextUtils.isEmpty(lookupKey) && !TextUtils.isEmpty(photoUri)) {
-            if (photoFileId == 0) {
-                // Trigger a VIEW action on this photo, which will force the Contacts
-                // Sync adapter to sync the HiRes version of the contact photo.
-                syncContactHiResPhoto(context, rawContactId);
-            }
-            return photoUri;
-        }
-        return getDefaultPictureUri(context);
-    }
-
-    private static void syncContactHiResPhoto(Context context, long rawContactId) {
-        final String serviceName = "com.google.android.syncadapters.contacts." +
-                "SyncHighResPhotoIntentService";
-        final String servicePackageName = "com.google.android.syncadapters.contacts";
-        final Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,
-                rawContactId);
-        final Intent intent = new Intent();
-        intent.setClassName(servicePackageName, serviceName);
-        intent.setAction(Intent.ACTION_VIEW);
-        intent.setDataAndType(uri, RawContacts.CONTENT_ITEM_TYPE);
-        try {
-            context.startService(intent);
-        } catch (Exception e) {
-
-        }
-    }
-
-    /**
-     * Returns a default image to be used when an account has no picture associated with it.
-     */
-    public static String getDefaultPictureUri(Context context) {
-        // TODO: get a better default image.
-        ShortcutIconResource iconResource = new ShortcutIconResource();
-        iconResource.packageName = context.getPackageName();
-        iconResource.resourceName = context.getResources().getResourceName(
-                R.drawable.ic_contact);
-        return UriUtils.getShortcutIconResourceUri(iconResource).toString();
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java b/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java
index 043f41a..b6555b4 100644
--- a/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java
+++ b/car-apps-common/src/com/android/car/apps/common/BackgroundImageView.java
@@ -52,24 +52,30 @@
     public BackgroundImageView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        inflate(getContext(), R.layout.background_image, this);
+        float extraScale;
+        int resId;
+        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
+                R.styleable.BackgroundImageView, defStyle, 0);
+        try {
+            extraScale = a.getFloat(R.styleable.BackgroundImageView_imageAdditionalScale, 1.05f);
+            resId = a.getResourceId(R.styleable.BackgroundImageView_contentLayout,
+                    R.layout.background_image);
+            mBitmapBlurPercent = a.getFloat(R.styleable.BackgroundImageView_bitmap_blur_percent,
+                    getResources().getFloat(R.dimen.background_bitmap_blur_percent));
+
+            int size = a.getInteger(R.styleable.BackgroundImageView_bitmap_target_size_px,
+                    getResources().getInteger(R.integer.background_bitmap_target_size_px));
+            mBitmapTargetSize = new Size(size, size);
+        } finally {
+            a.recycle();
+        }
+
+        inflate(getContext(), resId, this);
 
         mImageView = findViewById(R.id.background_image_image);
         mDarkeningScrim = findViewById(R.id.background_image_darkening_scrim);
 
-        int size = getResources().getInteger(R.integer.background_bitmap_target_size_px);
-        mBitmapTargetSize = new Size(size, size);
-        mBitmapBlurPercent = getResources().getFloat(R.dimen.background_bitmap_blur_percent);
-
-        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
-                R.styleable.BackgroundImageView, defStyle, 0);
-
-        try {
-            setImageAdditionalScale(a.getFloat(R.styleable.BackgroundImageView_imageAdditionalScale,
-                    1.05f));
-        } finally {
-            a.recycle();
-        }
+        setImageAdditionalScale(extraScale);
     }
 
     /**
diff --git a/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java b/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java
index 08b5dd1..bd96ee5 100644
--- a/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/BitmapUtils.java
@@ -17,9 +17,6 @@
 
 import static android.graphics.Bitmap.Config.ARGB_8888;
 
-import android.annotation.ColorInt;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -32,6 +29,10 @@
 import android.util.Log;
 import android.util.Size;
 
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 public class BitmapUtils {
     private static final String TAG = "BitmapUtils";
 
diff --git a/car-apps-common/src/com/android/car/apps/common/CarUxRestrictionsUtil.java b/car-apps-common/src/com/android/car/apps/common/CarUxRestrictionsUtil.java
deleted file mode 100644
index 219bf59..0000000
--- a/car-apps-common/src/com/android/car/apps/common/CarUxRestrictionsUtil.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2016 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.car.apps.common;
-
-import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH;
-
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.drivingstate.CarUxRestrictions;
-import android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo;
-import android.car.drivingstate.CarUxRestrictionsManager;
-import android.content.Context;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.Collections;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-/**
- * Utility class to access Car Restriction Manager.
- *
- * This class must be a singleton because only one listener can be registered with
- * {@link CarUxRestrictionsManager} at a time, as documented in
- * {@link CarUxRestrictionsManager#registerListener}.
- *
- * @deprecated Use {@link com.android.car.ui.utils.CarUxRestrictionsUtil} instead
- */
-public class CarUxRestrictionsUtil {
-    private static final String TAG = "CarUxRestrictionsUtil";
-
-    private final Car mCarApi;
-    private CarUxRestrictionsManager mCarUxRestrictionsManager;
-    @NonNull
-    private CarUxRestrictions mCarUxRestrictions = getDefaultRestrictions();
-
-    private Set<OnUxRestrictionsChangedListener> mObservers;
-    private static CarUxRestrictionsUtil sInstance = null;
-
-    private CarUxRestrictionsUtil(Context context) {
-        CarUxRestrictionsManager.OnUxRestrictionsChangedListener listener = (carUxRestrictions) -> {
-            if (carUxRestrictions == null) {
-                mCarUxRestrictions = getDefaultRestrictions();
-            } else {
-                mCarUxRestrictions = carUxRestrictions;
-            }
-
-            for (OnUxRestrictionsChangedListener observer : mObservers) {
-                observer.onRestrictionsChanged(mCarUxRestrictions);
-            }
-        };
-
-        mCarApi = Car.createCar(context.getApplicationContext());
-        mObservers = Collections.newSetFromMap(new WeakHashMap<>());
-
-        try {
-            mCarUxRestrictionsManager = (CarUxRestrictionsManager) mCarApi
-                    .getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
-            mCarUxRestrictionsManager.registerListener(listener);
-            listener.onUxRestrictionsChanged(
-                    mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
-        } catch (CarNotConnectedException e) {
-            Log.e(TAG, "Car not connected", e);
-            // mCarUxRestrictions will be the default
-        } catch (NullPointerException e) {
-            Log.e(TAG, "Car not connected", e);
-            // mCarUxRestrictions will be the default
-        }
-    }
-
-    @NonNull
-    private CarUxRestrictions getDefaultRestrictions() {
-        return new CarUxRestrictions.Builder(true,
-                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0).build();
-    }
-
-    /**
-     * Listener interface used to update clients on UxRestrictions changes
-     */
-    public interface OnUxRestrictionsChangedListener {
-        /**
-         * Called when CarUxRestrictions changes
-         */
-        void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions);
-    }
-
-    /**
-     * Returns the singleton instance of this class
-     */
-    @NonNull
-    public static CarUxRestrictionsUtil getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new CarUxRestrictionsUtil(context);
-        }
-
-        return sInstance;
-    }
-
-    /**
-     * Registers a listener on this class for updates to CarUxRestrictions.
-     * Multiple listeners may be registered.
-     */
-    public void register(OnUxRestrictionsChangedListener listener) {
-        mObservers.add(listener);
-        listener.onRestrictionsChanged(mCarUxRestrictions);
-    }
-
-    /**
-     * Unregisters a registered listener
-     */
-    public void unregister(OnUxRestrictionsChangedListener listener) {
-        mObservers.remove(listener);
-    }
-
-    /**
-     * Returns whether any of the given flags is blocked by the current restrictions. If null is
-     * given, the method returns true for safety.
-     */
-    public static boolean isRestricted(@CarUxRestrictionsInfo int restrictionFlags,
-            @Nullable CarUxRestrictions uxr) {
-        return (uxr == null) || ((uxr.getActiveRestrictions() & restrictionFlags) != 0);
-    }
-
-    /**
-     * Complies the input string with the given UX restrictions.
-     * Returns the original string if already compliant, otherwise a shortened ellipsized string.
-     */
-    public static String complyString(Context context, String str, CarUxRestrictions uxr) {
-
-        if (isRestricted(UX_RESTRICTIONS_LIMIT_STRING_LENGTH, uxr)) {
-            int maxLength = uxr == null
-                    ? context.getResources().getInteger(R.integer.default_max_string_length)
-                    : uxr.getMaxRestrictedStringLength();
-
-            if (str.length() > maxLength) {
-                return str.substring(0, maxLength) + context.getString(R.string.ellipsis);
-            }
-        }
-
-        return str;
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/ClickThroughToolbar.java b/car-apps-common/src/com/android/car/apps/common/ClickThroughToolbar.java
deleted file mode 100644
index 7e5b79c..0000000
--- a/car-apps-common/src/com/android/car/apps/common/ClickThroughToolbar.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.apps.common;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.Toolbar;
-
-/**
- * A toolbar that optionally supports allowing clicks on it to pass through to any underlying views.
- *
- * <p>By default, the {@link Toolbar} eats all touches on it. This view will override
- * {@link #onTouchEvent(MotionEvent)} and return {@code false} if configured to allow pass through.
- *
- * @deprecated Use {@link com.android.car.ui.toolbar.Toolbar} instead
- */
-@Deprecated
-public class ClickThroughToolbar extends Toolbar {
-    private boolean mAllowClickPassThrough;
-
-    public ClickThroughToolbar(Context context) {
-        super(context);
-    }
-
-    public ClickThroughToolbar(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        initAttributes(context, attrs, 0 /* defStyleAttrs */);
-    }
-
-    public ClickThroughToolbar(Context context, AttributeSet attrs, int defStyleAttrs) {
-        super(context, attrs, defStyleAttrs);
-        initAttributes(context, attrs, defStyleAttrs);
-    }
-
-    private void initAttributes(Context context, AttributeSet attrs, int defStyleAttrs) {
-        TypedArray a = context.obtainStyledAttributes(
-                attrs, R.styleable.ClickThroughToolbar, defStyleAttrs, 0 /* defStyleRes */);
-
-        mAllowClickPassThrough = a.getBoolean(R.styleable.ClickThroughToolbar_clickThrough, false);
-
-        a.recycle();
-    }
-
-    /**
-     * Whether or not clicks on this toolbar will pass through to any views that are underneath
-     * it. By default, this value is {@code false}.
-     *
-     * @param allowPassThrough {@code true} if clicks will pass through to an underlying view;
-     *                         {@code false} otherwise.
-     */
-    public void setClickPassThrough(boolean allowPassThrough) {
-        mAllowClickPassThrough = allowPassThrough;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (mAllowClickPassThrough) {
-            return false;
-        }
-
-        return super.onTouchEvent(ev);
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/CommonFlags.java b/car-apps-common/src/com/android/car/apps/common/CommonFlags.java
index 5fbc4a0..f70d296 100644
--- a/car-apps-common/src/com/android/car/apps/common/CommonFlags.java
+++ b/car-apps-common/src/com/android/car/apps/common/CommonFlags.java
@@ -17,11 +17,12 @@
 package com.android.car.apps.common;
 
 
-import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.SystemProperties;
 
+import androidx.annotation.NonNull;
+
 /** Singleton class regrouping common library feature flags. */
 public class CommonFlags {
 
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 3ed7331..4181867 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
@@ -16,6 +16,8 @@
 
 package com.android.car.apps.common;
 
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -29,6 +31,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
@@ -38,9 +41,10 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.core.util.Preconditions;
 import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
 
-import com.android.internal.util.Preconditions;
+import com.android.car.apps.common.util.ViewUtils;
 
 import java.util.Locale;
 
@@ -89,6 +93,10 @@
     private boolean mExpandEnabled;
     // Callback for the expand/collapse button
     private ExpandCollapseCallback mExpandCollapseCallback;
+    // The root of the transition animation.
+    private ViewGroup mTransitionRoot;
+    // Whether this control bar has focus.
+    private boolean mHasFocus;
 
     // Default number of columns, if unspecified
     private static final int DEFAULT_COLUMNS = 3;
@@ -159,6 +167,15 @@
         mDefaultExpandCollapseView.setContentDescription(context.getString(
                 R.string.control_bar_expand_collapse_button));
         mDefaultExpandCollapseView.setOnClickListener(v -> onExpandCollapse());
+
+        // Collapse the control bar when it is expanded and loses focus.
+        getViewTreeObserver().addOnGlobalFocusChangeListener((oldFocus, newFocus) -> {
+            boolean hasFocus = hasFocus();
+            if (mHasFocus && !hasFocus && mIsExpanded) {
+                onExpandCollapse();
+            }
+            mHasFocus = hasFocus;
+        });
     }
 
     private int getSlotIndex(@SlotPosition int slotPosition) {
@@ -259,7 +276,7 @@
                 viewToUse = mViews[viewsIndex];
                 viewsIndex++;
             }
-            setView(viewToUse, mSlots[i]);
+            ViewUtils.setView(viewToUse, mSlots[i]);
             if (viewToUse != null) {
                 lastUsedIndex = i;
             }
@@ -291,23 +308,6 @@
         }
     }
 
-    private void setView(@Nullable View view, FrameLayout container) {
-        container.removeAllViews();
-        if (view != null) {
-            ViewGroup parent = (ViewGroup) view.getParent();
-            // As we are removing views (on BT disconnect, for example), some items will be
-            // shifting from expanded to collapsed (like Queue item) - remove those from the
-            // group before adding to the new slot
-            if (view.getParent() != null) {
-                parent.removeView(view);
-            }
-            container.addView(view);
-            container.setVisibility(VISIBLE);
-        } else {
-            container.setVisibility(INVISIBLE);
-        }
-    }
-
     private void onExpandCollapse() {
         mIsExpanded = !mIsExpanded;
         if (mExpandCollapseView != null) {
@@ -326,12 +326,34 @@
                 .addTransition(new Fade())
                 .setDuration(animationDuration)
                 .setInterpolator(new FastOutSlowInInterpolator());
-        TransitionManager.beginDelayedTransition(this, set);
+        maybeInitTransitionRoot();
+        TransitionManager.beginDelayedTransition(mTransitionRoot, set);
         for (int i = 0; i < mNumExtraRowsInUse; i++) {
             mRowsContainer.getChildAt(i).setVisibility(mIsExpanded ? View.VISIBLE : View.GONE);
         }
     }
 
+    private void maybeInitTransitionRoot() {
+        if (mTransitionRoot != null) {
+            return;
+        }
+        // During the control bar expanding/collapsing animation, the height of the control bar
+        // changes gradually. If the height of its ancestor is WRAP_CONTENT, the height of its
+        // ancestor will not change during the animation, causing janky animation. To fix it the
+        // animation should be played on the highest ancestor that wraps the control bar vertically.
+        mTransitionRoot = this;
+        ViewParent viewParent = getParent();
+        while (viewParent != null && viewParent instanceof ViewGroup) {
+            ViewGroup parent = (ViewGroup) viewParent;
+            if (parent.getLayoutParams().height == WRAP_CONTENT) {
+                mTransitionRoot = parent;
+                viewParent = parent.getParent();
+            } else {
+                break;
+            }
+        }
+    }
+
     /**
      * Returns the view assigned to the given row and column, after layout.
      *
diff --git a/car-apps-common/src/com/android/car/apps/common/IconCropper.java b/car-apps-common/src/com/android/car/apps/common/IconCropper.java
new file mode 100644
index 0000000..49d4abc
--- /dev/null
+++ b/car-apps-common/src/com/android/car/apps/common/IconCropper.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 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.car.apps.common;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.Drawable;
+
+import androidx.annotation.NonNull;
+import androidx.core.graphics.PathParser;
+
+/** A helper to crop icons to a shape using a given or the default path. */
+public final class IconCropper {
+    private static final float ICON_MASK_SIZE = 100.0f;
+
+    @NonNull
+    private final Path mIconMask;
+
+    /** Sets up the icon cropper with the given icon mask. */
+    public IconCropper(@NonNull Path iconMask) {
+        mIconMask = iconMask;
+    }
+
+    /**
+     * Sets up the icon cropper instance with the default crop mask.
+     *
+     * The SVG path mask is read from the {@code R.string.config_crop_icon_mask} resource value.
+     */
+    public IconCropper(@NonNull Context context) {
+        this(getDefaultMask(context));
+    }
+
+    private static Path getDefaultMask(@NonNull Context context) {
+        return PathParser.createPathFromPathData(
+                context.getString(R.string.config_crop_icon_mask));
+    }
+
+    /** Crops the given drawable according to the current object settings. */
+    @NonNull
+    public Bitmap crop(@NonNull Drawable source) {
+        return crop(BitmapUtils.fromDrawable(source, null));
+    }
+
+    /** Crops the given bitmap according to the current object settings. */
+    @NonNull
+    public Bitmap crop(@NonNull Bitmap icon) {
+        int width = icon.getWidth();
+        int height = icon.getHeight();
+
+        Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
+        Canvas canvas = new Canvas(output);
+
+        Paint paint = new Paint();
+        paint.setAntiAlias(true);
+        // Note: only alpha component of the color set below matters, since we
+        // overlay the mask using PorterDuff.Mode.SRC_IN mode (more details here:
+        // https://d.android.com/reference/android/graphics/PorterDuff.Mode).
+        paint.setColor(Color.WHITE);
+
+        canvas.save();
+        canvas.scale(width / ICON_MASK_SIZE, height / ICON_MASK_SIZE);
+        canvas.drawPath(mIconMask, paint);
+        canvas.restore();
+
+        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+        canvas.drawBitmap(icon, 0, 0, paint);
+
+        return output;
+    }
+}
diff --git a/car-apps-common/src/com/android/car/apps/common/ImageUtils.java b/car-apps-common/src/com/android/car/apps/common/ImageUtils.java
index e110e76..cfdbe57 100644
--- a/car-apps-common/src/com/android/car/apps/common/ImageUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/ImageUtils.java
@@ -16,7 +16,6 @@
 
 package com.android.car.apps.common;
 
-import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.renderscript.Allocation;
@@ -25,6 +24,8 @@
 import android.renderscript.ScriptIntrinsicBlur;
 import android.util.Size;
 
+import androidx.annotation.NonNull;
+
 /**
  * Utility methods to manipulate images.
  */
diff --git a/car-apps-common/src/com/android/car/apps/common/MinimizedControlBar.java b/car-apps-common/src/com/android/car/apps/common/MinimizedControlBar.java
index 7158f44..2eeb1b8 100644
--- a/car-apps-common/src/com/android/car/apps/common/MinimizedControlBar.java
+++ b/car-apps-common/src/com/android/car/apps/common/MinimizedControlBar.java
@@ -21,7 +21,6 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.ImageView;
@@ -30,6 +29,8 @@
 import androidx.annotation.Nullable;
 import androidx.constraintlayout.widget.ConstraintLayout;
 
+import com.android.car.apps.common.util.ViewUtils;
+
 /**
  * This is a compact CarControlBar that provides a fixed number of controls (with no overflow),
  * along with some metadata (title, subtitle, icon)
@@ -122,25 +123,7 @@
                 viewToUse = mViews[viewIndex];
                 viewIndex++;
             }
-            setView(viewToUse, mSlots[CarControlBar.getSlotIndex(i, NUM_COLUMNS)]);
+            ViewUtils.setView(viewToUse, mSlots[CarControlBar.getSlotIndex(i, NUM_COLUMNS)]);
         }
     }
-
-    private void setView(@Nullable View view, FrameLayout container) {
-        container.removeAllViews();
-        if (view != null) {
-            ViewGroup parent = (ViewGroup) view.getParent();
-            // As we are removing views (on BT disconnect, for example), some items will be
-            // shifting from expanded to collapsed - remove those from the group before adding to
-            // the new slot
-            if (view.getParent() != null) {
-                parent.removeView(view);
-            }
-            container.addView(view);
-            container.setVisibility(VISIBLE);
-        } else {
-            container.setVisibility(INVISIBLE);
-        }
-    }
-
 }
diff --git a/car-apps-common/src/com/android/car/apps/common/UxrButton.java b/car-apps-common/src/com/android/car/apps/common/UxrButton.java
index aae5aa3..0da6056 100644
--- a/car-apps-common/src/com/android/car/apps/common/UxrButton.java
+++ b/car-apps-common/src/com/android/car/apps/common/UxrButton.java
@@ -16,7 +16,6 @@
 
 package com.android.car.apps.common;
 
-import android.annotation.Nullable;
 import android.car.drivingstate.CarUxRestrictions;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -26,6 +25,10 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import androidx.annotation.Nullable;
+
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+
 /**
  * UX Restrictions compliant Button.
  * This class will automatically listen to Car UXRestrictions, and respond to click event
diff --git a/car-apps-common/src/com/android/car/apps/common/UxrTextView.java b/car-apps-common/src/com/android/car/apps/common/UxrTextView.java
index c84d158..10c92c4 100644
--- a/car-apps-common/src/com/android/car/apps/common/UxrTextView.java
+++ b/car-apps-common/src/com/android/car/apps/common/UxrTextView.java
@@ -24,6 +24,8 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+
 /**
  * UX Restrictions compliant TextView.
  * This class will automatically listen to Car UXRestrictions and truncate text accordingly.
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java b/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java
index f640218..6270a89 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/ImageBinder.java
@@ -17,16 +17,17 @@
 package com.android.car.apps.common.imaging;
 
 
-import static com.android.internal.util.Preconditions.checkNotNull;
+import static androidx.core.util.Preconditions.checkNotNull;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.util.Size;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.apps.common.R;
 import com.android.car.apps.common.UriUtils;
 
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java b/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java
index 464d974..2682cb0 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/ImageKey.java
@@ -19,8 +19,9 @@
 import android.net.Uri;
 import android.util.Size;
 
+import androidx.core.util.Preconditions;
+
 import com.android.car.apps.common.UriUtils;
-import com.android.internal.util.Preconditions;
 
 import java.util.Objects;
 
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java b/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
index ee50b72..896d5af 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
@@ -16,13 +16,14 @@
 
 package com.android.car.apps.common.imaging;
 
-import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.Size;
 import android.widget.ImageView;
 
+import androidx.annotation.Nullable;
+
 import com.android.car.apps.common.CommonFlags;
 import com.android.car.apps.common.R;
 
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java b/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java
index e8b245e..84fb530 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/LocalImageFetcher.java
@@ -16,10 +16,8 @@
 
 package com.android.car.apps.common.imaging;
 
-import android.annotation.UiThread;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.ImageDecoder;
@@ -30,21 +28,21 @@
 import android.util.Log;
 import android.util.LruCache;
 
+import androidx.annotation.UiThread;
+
 import com.android.car.apps.common.BitmapUtils;
 import com.android.car.apps.common.CommonFlags;
 import com.android.car.apps.common.R;
 import com.android.car.apps.common.UriUtils;
 import com.android.car.apps.common.util.CarAppsIOUtils;
 
-import libcore.io.IoUtils;
-
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
 import java.net.URL;
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -248,7 +246,7 @@
         };
 
         // ALLOCATOR_HARDWARE causes crashes on some emulators (in media center's queue).
-        private @ImageDecoder.Allocator int mAllocatorMode = ImageDecoder.ALLOCATOR_SOFTWARE;
+        private int mAllocatorMode = ImageDecoder.ALLOCATOR_SOFTWARE;
 
         @Override
         protected Drawable doInBackground(Void... voids) {
@@ -265,18 +263,8 @@
                             UriUtils.getIconResource(context, imageUri));
                 } else if (UriUtils.isContentUri(imageUri)) {
                     ContentResolver resolver = context.getContentResolver();
-
-                    // TODO(b/140959390): Remove the check once the bug is fixed in framework.
-                    if (!hasFile(resolver, imageUri)) {
-                        if (L_WARN) {
-                            Log.w(TAG, "File not found in uri: " + imageUri);
-                        }
-                        return null;
-                    }
-
                     ImageDecoder.Source src = ImageDecoder.createSource(resolver, imageUri);
                     return ImageDecoder.decodeDrawable(src, mOnHeaderDecodedListener);
-
                 } else if (mFlagRemoteImages) {
                     mAllocatorMode = ImageDecoder.ALLOCATOR_SOFTWARE; // Needed for canvas drawing.
                     URL url = new URL(imageUri.toString());
@@ -285,7 +273,8 @@
                          ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
 
                         CarAppsIOUtils.copy(is, bytes);
-                        ImageDecoder.Source src = ImageDecoder.createSource(bytes.toByteArray());
+                        ImageDecoder.Source src =
+                                ImageDecoder.createSource(ByteBuffer.wrap(bytes.toByteArray()));
                         Bitmap decoded = ImageDecoder.decodeBitmap(src, mOnHeaderDecodedListener);
                         Bitmap tinted = BitmapUtils.createTintedBitmap(decoded,
                                 context.getColor(R.color.improper_image_refs_tint_color));
@@ -300,34 +289,6 @@
             return null;
         }
 
-        private boolean hasFile(ContentResolver resolver, Uri uri) {
-            AssetFileDescriptor assetFd = null;
-            try {
-                if (uri.getScheme() == ContentResolver.SCHEME_CONTENT) {
-                    assetFd = resolver.openTypedAssetFileDescriptor(uri, "image/*", null);
-                } else {
-                    assetFd = resolver.openAssetFileDescriptor(uri, "r");
-                }
-            } catch (FileNotFoundException e) {
-                // Some images cannot be opened as AssetFileDescriptors (e.g.bmp, ico). Open them
-                // as InputStreams.
-                try {
-                    InputStream is = resolver.openInputStream(uri);
-                    if (is != null) {
-                        IoUtils.closeQuietly(is);
-                        return true;
-                    }
-                } catch (IOException exception) {
-                    return false;
-                }
-            }
-            if (assetFd != null) {
-                IoUtils.closeQuietly(assetFd);
-                return true;
-            }
-            return false;
-        }
-
         @UiThread
         @Override
         protected void onPostExecute(Drawable drawable) {
diff --git a/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java b/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java
index 43e4381..6d43424 100644
--- a/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/util/CarPackageManagerUtils.java
@@ -16,15 +16,12 @@
 
 package com.android.car.apps.common.util;
 
-import android.car.Car;
-import android.car.CarNotConnectedException;
+import android.app.PendingIntent;
 import android.car.content.pm.CarPackageManager;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 
@@ -34,43 +31,26 @@
 public class CarPackageManagerUtils {
     private static final String TAG = "CarPackageManagerUtils";
 
-    private final Car mCarApi;
-    private CarPackageManager mCarPackageManager;
-
-    private static CarPackageManagerUtils sInstance = null;
-
-    private CarPackageManagerUtils(Context context) {
-        mCarApi = Car.createCar(context.getApplicationContext());
-        try {
-            mCarPackageManager = (CarPackageManager) mCarApi.getCarManager(Car.PACKAGE_SERVICE);
-        } catch (CarNotConnectedException e) {
-            Log.e(TAG, "Car not connected when retrieving car package manager", e);
-        }
-    }
-
     /**
-     * Returns the singleton instance of this class
+     * Returns whether the given {@link PendingIntent} represents an activity that is distraction
+     * optimized.
      */
-    @NonNull
-    public static CarPackageManagerUtils getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new CarPackageManagerUtils(context);
+    public static boolean isDistractionOptimized(CarPackageManager carPackageManager,
+            @NonNull PendingIntent pendingIntent) {
+        if (carPackageManager != null) {
+            return carPackageManager.isPendingIntentDistractionOptimized(pendingIntent);
         }
-        return sInstance;
+        return false;
     }
 
     /**
      * Returns true if the provided Activity is distraction optimized
      */
-    public boolean isDistractionOptimized(@NonNull ActivityInfo activityInfo) {
-        if (mCarPackageManager != null) {
-            try {
-                return mCarPackageManager.isActivityDistractionOptimized(
-                        activityInfo.packageName, activityInfo.name);
-            } catch (CarNotConnectedException e) {
-                Log.e(TAG, "Car not connected when getting driver optimization info", e);
-                return false;
-            }
+    public static boolean isDistractionOptimized(CarPackageManager carPackageManager,
+            @NonNull ActivityInfo activityInfo) {
+        if (carPackageManager != null) {
+            return carPackageManager.isActivityDistractionOptimized(
+                    activityInfo.packageName, activityInfo.name);
         }
         return false;
     }
@@ -79,9 +59,11 @@
      * Attempts to resolve the provided intent into an activity, and returns true if the
      * resolved activity is distraction optimized
      */
-    public boolean isDistractionOptimized(PackageManager packageManager, Intent intent) {
+    public static boolean isDistractionOptimized(CarPackageManager carPackageManager,
+            PackageManager packageManager, Intent intent) {
         ResolveInfo info = packageManager.resolveActivity(
                 intent, PackageManager.MATCH_DEFAULT_ONLY);
-        return (info != null) ? isDistractionOptimized(info.activityInfo) : false;
+        return (info != null) ? isDistractionOptimized(carPackageManager, info.activityInfo)
+                : false;
     }
 }
diff --git a/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java b/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java
index a3d10e4..c056f84 100644
--- a/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java
+++ b/car-apps-common/src/com/android/car/apps/common/util/SafeLog.java
@@ -16,10 +16,11 @@
 
 package com.android.car.apps.common.util;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 /**
  * Convenience logging methods that respect whitelisted tags.
  */
diff --git a/car-apps-common/src/com/android/car/apps/common/util/ScrollBarUI.java b/car-apps-common/src/com/android/car/apps/common/util/ScrollBarUI.java
deleted file mode 100644
index 7098a82..0000000
--- a/car-apps-common/src/com/android/car/apps/common/util/ScrollBarUI.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.apps.common.util;
-
-import android.content.Context;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.widget.PagedRecyclerView;
-import com.android.car.apps.common.widget.PagedRecyclerView.ScrollBarPosition;
-
-/**
- * An abstract class that defines required contract for a custom scroll bar for the
- * {@link PagedRecyclerView}. All custom scroll bar must inherit from this class.
- */
-public abstract class ScrollBarUI {
-    protected RecyclerView mRecyclerView;
-
-    public RecyclerView getRecyclerView() {
-        return mRecyclerView;
-    }
-
-    /**
-     * The concrete class should implement this method to initialize configuration of a scrollbar
-     * view.
-     */
-    public abstract void initialize(Context context, RecyclerView recyclerView,
-            int scrollBarContainerWidth, @ScrollBarPosition int scrollBarPosition,
-            boolean scrollBarAboveRecyclerView);
-
-    /**
-     * Requests layout of the scrollbar. Should be called when there's been a change that will
-     * affect the size of the scrollbar view.
-     */
-    public abstract void requestLayout();
-
-    /**
-     * Sets the padding of the scrollbar, relative to the padding of the RecyclerView.
-     */
-    public abstract void setPadding(int padddingStart, int paddingEnd);
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/util/VectorMath.java b/car-apps-common/src/com/android/car/apps/common/util/VectorMath.java
new file mode 100644
index 0000000..cd6ad03
--- /dev/null
+++ b/car-apps-common/src/com/android/car/apps/common/util/VectorMath.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.car.apps.common.util;
+
+/**
+ * Simple utilities to deal with vector math.
+ */
+public class VectorMath {
+
+    private VectorMath() {
+    }
+
+    /** Error threshold constant. */
+    public static final float EPSILON = 0.0001f;
+
+    /** Returns the dot product of the given vectors. */
+    public static float dotProduct(float vx, float vy, float ux, float uy) {
+        return (vx * ux) + (vy * uy);
+    }
+
+    /** Returns the Euclidean norm of the given vector. */
+    public static float norm2(float vx, float vy) {
+        return (float) Math.sqrt(dotProduct(vx, vy, vx, vy));
+    }
+
+    /** Returns the center of the given coordinates. */
+    public static float center(float a, float b) {
+        return (a + b) / 2.0f;
+    }
+}
diff --git a/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java b/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
index fe11f38..a6cc870 100644
--- a/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
+++ b/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
@@ -16,14 +16,19 @@
 
 package com.android.car.apps.common.util;
 
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.annotation.NonNull;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
@@ -100,7 +105,7 @@
                 .setListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationStart(Animator animation) {
-                        view.setVisibility(View.VISIBLE);
+                        view.setVisibility(VISIBLE);
                     }
                 })
                 .alpha(1f);
@@ -123,7 +128,7 @@
     /** Sets the visibility of the (optional) view to {@link View#VISIBLE} or {@link View#GONE}. */
     public static void setVisible(@Nullable View view, boolean visible) {
         if (view != null) {
-            view.setVisibility(visible ? View.VISIBLE : View.GONE);
+            view.setVisibility(visible ? VISIBLE : View.GONE);
         }
     }
 
@@ -139,7 +144,7 @@
      */
     public static void setInvisible(@Nullable View view, boolean invisible) {
         if (view != null) {
-            view.setVisibility(invisible ? View.INVISIBLE : View.VISIBLE);
+            view.setVisibility(invisible ? INVISIBLE : VISIBLE);
         }
     }
 
@@ -201,4 +206,30 @@
         viewIds.recycle();
         return views;
     }
+
+    /** Adds the {@code view} into the {@code container}. */
+    public static void setView(@Nullable View view, FrameLayout container) {
+        if (view != null) {
+            // Don't set the view if it stays the same.
+            if (container.getChildCount() == 1 && container.getChildAt(0) == view) {
+                return;
+            }
+
+            ViewGroup parent = (ViewGroup) view.getParent();
+            // As we are removing views (on BT disconnect, for example), some items will be
+            // shifting from expanded to collapsed (like Queue item) - remove those from the
+            // group before adding to the new slot
+            if (view.getParent() != null) {
+                parent.removeView(view);
+            }
+            container.removeAllViews();
+            container.addView(view);
+            container.setVisibility(VISIBLE);
+        } else {
+            if (container.getChildCount() != 0) {
+                container.removeAllViews();
+            }
+            container.setVisibility(INVISIBLE);
+        }
+    }
 }
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/CarScrollBar.java b/car-apps-common/src/com/android/car/apps/common/widget/CarScrollBar.java
deleted file mode 100644
index 2de23a3..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/CarScrollBar.java
+++ /dev/null
@@ -1,760 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.apps.common.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.PointF;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import androidx.annotation.IntRange;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.OrientationHelper;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.R;
-import com.android.car.apps.common.util.ScrollBarUI;
-import com.android.car.apps.common.widget.PagedRecyclerView.ScrollBarPosition;
-
-/**
- * Inspired by {@link androidx.car.widget.PagedListView}. Most pagination and scrolling logic has
- * been ported from the PLV with minor updates.
- *
- * The default scroll bar widget for the {@link PagedRecyclerView}.
- */
-class CarScrollBar extends ScrollBarUI {
-    private float mButtonDisabledAlpha;
-    private static final String TAG = "CarScrollBar";
-    private PagedSnapHelper mSnapHelper;
-
-    private ImageView mUpButton;
-    private PaginateButtonClickListener mUpButtonClickListener;
-    private View mScrollView;
-    private View mScrollThumb;
-    private ImageView mDownButton;
-    private PaginateButtonClickListener mDownButtonClickListener;
-
-    private int mSeparatingMargin;
-    private int mScrollBarThumbWidth;
-
-    private int mPaddingStart;
-    private int mPaddingEnd;
-
-    /** The amount of space that the scroll thumb is allowed to roam over. */
-    private int mScrollThumbTrackHeight;
-
-    private final Interpolator mPaginationInterpolator = new AccelerateDecelerateInterpolator();
-
-    private int mRowsPerPage = -1;
-    private final Handler mHandler = new Handler();
-
-    private OrientationHelper mOrientationHelper;
-
-    /**
-     * When doing a snap, offset the snap by this number of position and then do a smooth scroll to
-     * the final position.
-     */
-    private static final int SNAP_SCROLL_OFFSET_POSITION = 2;
-
-    /**
-     * The amount of time after settling to wait before autoscrolling to the next page when the user
-     * holds down a pagination button.
-     */
-    private static final int PAGINATION_HOLD_DELAY_MS = 400;
-
-    @Override
-    public void initialize(Context context, RecyclerView recyclerView,
-            int scrollBarContainerWidth, @ScrollBarPosition int scrollBarPosition,
-            boolean scrollBarAboveRecyclerView) {
-
-        mRecyclerView = recyclerView;
-
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
-
-        FrameLayout parent = (FrameLayout) getRecyclerView().getParent();
-
-        mScrollView = inflater.inflate(R.layout.car_paged_scrollbar_buttons, parent, false);
-        mScrollView.setLayoutParams(
-                new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
-
-        mButtonDisabledAlpha = context.getResources().getFloat(R.dimen.button_disabled_alpha);
-
-        if (scrollBarAboveRecyclerView) {
-            parent.addView(mScrollView);
-        } else {
-            parent.addView(mScrollView, /* index= */0);
-        }
-
-        setScrollBarContainerWidth(scrollBarContainerWidth);
-        setScrollBarPosition(scrollBarPosition);
-
-        getRecyclerView().addOnScrollListener(mRecyclerViewOnScrollListener);
-        getRecyclerView().getRecycledViewPool().setMaxRecycledViews(0, 12);
-
-        Resources res = context.getResources();
-        mSeparatingMargin = res.getDimensionPixelSize(R.dimen.car_scroll_bar_separator_margin);
-        mScrollBarThumbWidth = res.getDimensionPixelSize(R.dimen.car_scroll_bar_thumb_width);
-
-        mUpButton = mScrollView.findViewById(R.id.page_up);
-        mUpButtonClickListener = new PaginateButtonClickListener(PaginationListener.PAGE_UP);
-        mUpButton.setOnClickListener(mUpButtonClickListener);
-
-        mDownButton = mScrollView.findViewById(R.id.page_down);
-        mDownButtonClickListener = new PaginateButtonClickListener(PaginationListener.PAGE_DOWN);
-        mDownButton.setOnClickListener(mDownButtonClickListener);
-
-        mScrollThumb = mScrollView.findViewById(R.id.scrollbar_thumb);
-
-        mSnapHelper = new PagedSnapHelper(context);
-        getRecyclerView().setOnFlingListener(null);
-        mSnapHelper.attachToRecyclerView(getRecyclerView());
-
-        mScrollView.addOnLayoutChangeListener((View v, int left, int top, int right, int bottom,
-                    int oldLeft, int oldTop, int oldRight, int oldBottom) -> {
-            int width = right - left;
-
-            OrientationHelper orientationHelper =
-                    getOrientationHelper(getRecyclerView().getLayoutManager());
-
-            // This value will keep track of the top of the current view being laid out.
-            int layoutTop = orientationHelper.getStartAfterPadding() + mPaddingStart;
-
-            // Lay out the up button at the top of the view.
-            layoutViewCenteredFromTop(mUpButton, layoutTop, width);
-            layoutTop = mUpButton.getBottom();
-
-            // Lay out the scroll thumb
-            layoutTop += mSeparatingMargin;
-            layoutViewCenteredFromTop(mScrollThumb, layoutTop, width);
-
-            // Lay out the bottom button at the bottom of the view.
-            int downBottom = orientationHelper.getEndAfterPadding() - mPaddingEnd;
-            layoutViewCenteredFromBottom(mDownButton, downBottom, width);
-
-            mHandler.post(this::calculateScrollThumbTrackHeight);
-            mHandler.post(() -> updatePaginationButtons(/* animate= */false));
-        });
-    }
-
-    @Override
-    public void requestLayout() {
-        mScrollView.requestLayout();
-    }
-
-    @Override
-    public void setPadding(int paddingStart, int paddingEnd) {
-        mPaddingStart = paddingStart;
-        mPaddingEnd = paddingEnd;
-        requestLayout();
-    }
-
-    /**
-     * Sets the listener that will be notified when the up and down buttons have been pressed.
-     *
-     * @param listener The listener to set.
-     */
-    void setPaginationListener(PaginationListener listener) {
-        mUpButtonClickListener.setPaginationListener(listener);
-        mDownButtonClickListener.setPaginationListener(listener);
-    }
-
-    /** Returns {@code true} if the "up" button is pressed */
-    private boolean isUpPressed() {
-        return mUpButton.isPressed();
-    }
-
-    /** Returns {@code true} if the "down" button is pressed */
-    private boolean isDownPressed() {
-        return mDownButton.isPressed();
-    }
-
-    /**
-     * Sets the width of the container that holds the scrollbar. The scrollbar will be centered
-     * within this width.
-     *
-     * @param width The width of the scrollbar container.
-     */
-    void setScrollBarContainerWidth(int width) {
-        ViewGroup.LayoutParams layoutParams = mScrollView.getLayoutParams();
-        layoutParams.width = width;
-        mScrollView.requestLayout();
-    }
-
-    /**
-     * Sets the position of the scrollbar.
-     *
-     * @param position Enum value of the scrollbar position. 0 for Start and 1 for end.
-     */
-    void setScrollBarPosition(@ScrollBarPosition int position) {
-        FrameLayout.LayoutParams layoutParams =
-                (FrameLayout.LayoutParams) mScrollView.getLayoutParams();
-        if (position == ScrollBarPosition.START) {
-            layoutParams.gravity = Gravity.LEFT;
-        } else {
-            layoutParams.gravity = Gravity.RIGHT;
-        }
-
-        mScrollView.requestLayout();
-    }
-
-    /**
-     * Sets whether or not the up button on the scroll bar is clickable.
-     *
-     * @param enabled {@code true} if the up button is enabled.
-     */
-    private void setUpEnabled(boolean enabled) {
-        mUpButton.setEnabled(enabled);
-        mUpButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
-    }
-
-    /**
-     * Sets whether or not the down button on the scroll bar is clickable.
-     *
-     * @param enabled {@code true} if the down button is enabled.
-     */
-    private void setDownEnabled(boolean enabled) {
-        mDownButton.setEnabled(enabled);
-        mDownButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
-    }
-
-    /**
-     * Returns whether or not the down button on the scroll bar is clickable.
-     *
-     * @return {@code true} if the down button is enabled. {@code false} otherwise.
-     */
-    private boolean isDownEnabled() {
-        return mDownButton.isEnabled();
-    }
-
-    /** Listener for when the list should paginate. */
-    interface PaginationListener {
-        int PAGE_UP = 0;
-        int PAGE_DOWN = 1;
-
-        /** Called when the linked view should be paged in the given direction */
-        void onPaginate(int direction);
-    }
-
-    /**
-     * Calculate the amount of space that the scroll bar thumb is allowed to roam. The thumb
-     * is allowed to take up the space between the down bottom and the up or alpha jump
-     * button, depending on if the latter is visible.
-     */
-    private void calculateScrollThumbTrackHeight() {
-        // Subtracting (2 * mSeparatingMargin) for the top/bottom margin above and below the
-        // scroll bar thumb.
-        mScrollThumbTrackHeight = mDownButton.getTop() - (2 * mSeparatingMargin);
-
-        // If there's an alpha jump button, then the thumb is laid out starting from below that.
-        mScrollThumbTrackHeight -= mUpButton.getBottom();
-    }
-
-    private void measureScrollThumb() {
-        int scrollWidth = MeasureSpec.makeMeasureSpec(mScrollBarThumbWidth, MeasureSpec.EXACTLY);
-        int scrollHeight = MeasureSpec.makeMeasureSpec(
-                mScrollThumb.getLayoutParams().height,
-                MeasureSpec.EXACTLY);
-        mScrollThumb.measure(scrollWidth, scrollHeight);
-    }
-
-    /**
-     * An optimization method to only remeasure and lay out the scroll thumb. This method should be
-     * used when the height of the thumb has changed, but no other views need to be remeasured.
-     */
-    private void measureAndLayoutScrollThumb() {
-        measureScrollThumb();
-
-        // The top value should not change from what it was before; only the height is assumed to
-        // be changing.
-        int layoutTop = mScrollThumb.getTop();
-        layoutViewCenteredFromTop(mScrollThumb, layoutTop, mScrollView.getMeasuredWidth());
-    }
-
-    /**
-     * Lays out the given View starting from the given {@code top} value downwards and centered
-     * within the given {@code availableWidth}.
-     *
-     * @param  view The view to lay out.
-     * @param  top The top value to start laying out from. This value will be the resulting top
-     *             value of the view.
-     * @param  availableWidth The width in which to center the given view.
-     */
-    private void layoutViewCenteredFromTop(View view, int top, int availableWidth) {
-        int viewWidth = view.getMeasuredWidth();
-        int viewLeft = (availableWidth - viewWidth) / 2;
-        view.layout(viewLeft, top, viewLeft + viewWidth,
-                top + view.getMeasuredHeight());
-    }
-
-    /**
-     * Lays out the given View starting from the given {@code bottom} value upwards and centered
-     * within the given {@code availableSpace}.
-     *
-     * @param  view The view to lay out.
-     * @param  bottom The bottom value to start laying out from. This value will be the resulting
-     *                bottom value of the view.
-     * @param  availableWidth The width in which to center the given view.
-     */
-    private void layoutViewCenteredFromBottom(View view, int bottom, int availableWidth) {
-        int viewWidth = view.getMeasuredWidth();
-        int viewLeft = (availableWidth - viewWidth) / 2;
-        view.layout(viewLeft, bottom - view.getMeasuredHeight(),
-                viewLeft + viewWidth, bottom);
-    }
-
-    /**
-     * Sets the range, offset and extent of the scroll bar. The range represents the size of a
-     * container for the scrollbar thumb; offset is the distance from the start of the container
-     * to where the thumb should be; and finally, extent is the size of the thumb.
-     *
-     * <p>These values can be expressed in arbitrary units, so long as they share the same units.
-     * The values should also be positive.
-     *
-     * @param range The range of the scrollbar's thumb
-     * @param offset The offset of the scrollbar's thumb
-     * @param extent The extent of the scrollbar's thumb
-     * @param animate Whether or not the thumb should animate from its current position to the
-     *                position specified by the given range, offset and extent.
-     */
-    void setParameters(
-            @IntRange(from = 0) int range,
-            @IntRange(from = 0) int offset,
-            @IntRange(from = 0) int extent, boolean animate) {
-        // Not laid out yet, so values cannot be calculated.
-        if (!mScrollView.isLaidOut()) {
-            return;
-        }
-
-        // If the scroll bars aren't visible, then no need to update.
-        if (mScrollView.getVisibility() == View.GONE || range == 0) {
-            return;
-        }
-
-        int thumbLength = calculateScrollThumbLength(range, extent);
-        int thumbOffset = calculateScrollThumbOffset(range, offset, thumbLength);
-
-        // Sets the size of the thumb and request a redraw if needed.
-        ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
-
-        if (lp.height != thumbLength) {
-            lp.height = thumbLength;
-            mScrollThumb.requestLayout();
-        }
-
-        moveY(mScrollThumb, thumbOffset, animate);
-    }
-
-    /**
-     * An optimized version of {@link #setParameters(int, int, int, boolean)} that is meant to be
-     * called if a view is laying itself out. This method will avoid a complete remeasure of
-     * the views in the {@code PagedScrollBarView} if the scroll thumb's height needs to be changed.
-     * Instead, only the thumb itself will be remeasured and laid out.
-     *
-     * <p>These values can be expressed in arbitrary units, so long as they share the same units.
-     *
-     * @param range The range of the scrollbar's thumb
-     * @param offset The offset of the scrollbar's thumb
-     * @param extent The extent of the scrollbar's thumb
-     *
-     * @see #setParameters(int, int, int, boolean)
-     */
-    void setParametersInLayout(int range, int offset, int extent) {
-        // If the scroll bars aren't visible, then no need to update.
-        if (mScrollView.getVisibility() == View.GONE || range == 0) {
-            return;
-        }
-
-        int thumbLength = calculateScrollThumbLength(range, extent);
-        int thumbOffset = calculateScrollThumbOffset(range, offset, thumbLength);
-
-        // Sets the size of the thumb and request a redraw if needed.
-        ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
-
-        if (lp.height != thumbLength) {
-            lp.height = thumbLength;
-            measureAndLayoutScrollThumb();
-        }
-
-        mScrollThumb.setY(thumbOffset);
-    }
-
-    /**
-     * Calculates and returns how big the scroll bar thumb should be based on the given range and
-     * extent.
-     *
-     * @param range The total amount of space the scroll bar is allowed to roam over.
-     * @param extent The amount of space that the scroll bar takes up relative to the range.
-     * @return The height of the scroll bar thumb in pixels.
-     */
-    private int calculateScrollThumbLength(int range, int extent) {
-        // Scale the length by the available space that the thumb can fill.
-        return Math.round(((float) extent / range) * mScrollThumbTrackHeight);
-    }
-
-    /**
-     * Calculates and returns how much the scroll thumb should be offset from the top of where it
-     * has been laid out.
-     *
-     * @param  range The total amount of space the scroll bar is allowed to roam over.
-     * @param  offset The amount the scroll bar should be offset, expressed in the same units as
-     *                the given range.
-     * @param  thumbLength The current length of the thumb in pixels.
-     * @return The amount the thumb should be offset in pixels.
-     */
-    private int calculateScrollThumbOffset(int range, int offset, int thumbLength) {
-        // Ensure that if the user has reached the bottom of the list, then the scroll bar is
-        // aligned to the bottom as well. Otherwise, scale the offset appropriately.
-        // This offset will be a value relative to the parent of this scrollbar, so start by where
-        // the top of mScrollThumb is.
-        return mScrollThumb.getTop() + (isDownEnabled()
-                ? Math.round(((float) offset / range) * mScrollThumbTrackHeight)
-                : mScrollThumbTrackHeight - thumbLength);
-    }
-
-    /** Moves the given view to the specified 'y' position. */
-    private void moveY(final View view, float newPosition, boolean animate) {
-        final int duration = animate ? 200 : 0;
-        view.animate()
-                .y(newPosition)
-                .setDuration(duration)
-                .setInterpolator(mPaginationInterpolator)
-                .start();
-    }
-
-    /**
-     * Updates the rows number per current page, which is used for calculating how many items we
-     * want to show.
-     */
-    private void updateRowsPerPage() {
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-        if (layoutManager == null) {
-            mRowsPerPage = 1;
-            return;
-        }
-
-        View firstChild = layoutManager.getChildAt(0);
-        if (firstChild == null || firstChild.getHeight() == 0) {
-            mRowsPerPage = 1;
-        } else {
-            mRowsPerPage = Math.max(1, getRecyclerView().getHeight() / firstChild.getHeight());
-        }
-    }
-
-    private class PaginateButtonClickListener implements View.OnClickListener {
-        private final int mPaginateDirection;
-        private PaginationListener mPaginationListener;
-
-        PaginateButtonClickListener(int paginateDirection) {
-            mPaginateDirection = paginateDirection;
-        }
-
-        public void setPaginationListener(PaginationListener listener) {
-            mPaginationListener = listener;
-        }
-
-        @Override
-        public void onClick(View v) {
-            if (mPaginationListener != null) {
-                mPaginationListener.onPaginate(mPaginateDirection);
-            }
-            if (mPaginateDirection == PaginationListener.PAGE_DOWN) {
-                pageDown();
-            } else if (mPaginateDirection == PaginationListener.PAGE_UP) {
-                pageUp();
-            }
-        }
-    }
-
-    private final RecyclerView.OnScrollListener mRecyclerViewOnScrollListener =
-            new RecyclerView.OnScrollListener() {
-                @Override
-                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-                    updatePaginationButtons(false);
-                }
-            };
-
-    private final Runnable mPaginationRunnable = () -> {
-        boolean upPressed = isUpPressed();
-        boolean downPressed = isDownPressed();
-        if (upPressed && downPressed) {
-            return;
-        }
-        if (upPressed) {
-            pageUp();
-        } else if (downPressed) {
-            pageDown();
-        }
-    };
-
-    /** Returns the page the given position is on, starting with page 0. */
-    int getPage(int position) {
-        if (mRowsPerPage == -1) {
-            return -1;
-        }
-        if (mRowsPerPage == 0) {
-            return 0;
-        }
-        return position / mRowsPerPage;
-    }
-
-    private OrientationHelper getOrientationHelper(RecyclerView.LayoutManager layoutManager) {
-        if (mOrientationHelper == null || mOrientationHelper.getLayoutManager() != layoutManager) {
-            // PagedRecyclerView is assumed to be a list that always vertically scrolls.
-            mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
-        }
-        return mOrientationHelper;
-    }
-
-    /**
-     * Scrolls the contents of the RecyclerView up a page. A page is defined as the height of the
-     * {@code PagedRecyclerView}.
-     *
-     * <p>The resulting first item in the list will be snapped to so that it is completely visible.
-     * If this is not possible due to the first item being taller than the containing
-     * {@code PagedRecyclerView}, then the snapping will not occur.
-     */
-    void pageUp() {
-        int currentOffset = getRecyclerView().computeVerticalScrollOffset();
-        if (getRecyclerView().getLayoutManager() == null
-                || getRecyclerView().getChildCount() == 0 || currentOffset == 0) {
-            return;
-        }
-
-        // Use OrientationHelper to calculate scroll distance in order to match snapping behavior.
-        OrientationHelper orientationHelper =
-                getOrientationHelper(getRecyclerView().getLayoutManager());
-        int screenSize = orientationHelper.getTotalSpace();
-
-        int scrollDistance = screenSize;
-        // The iteration order matters. In case where there are 2 items longer than screen size, we
-        // want to focus on upcoming view.
-        for (int i = 0; i < getRecyclerView().getChildCount(); i++) {
-            /*
-             * We treat child View longer than screen size differently:
-             * 1) When it enters screen, next pageUp will align its bottom with parent bottom;
-             * 2) When it leaves screen, next pageUp will align its top with parent top.
-             */
-            View child = getRecyclerView().getChildAt(i);
-            if (child.getHeight() > screenSize) {
-                if (orientationHelper.getDecoratedEnd(child) < screenSize) {
-                    // Child view bottom is entering screen. Align its bottom with parent bottom.
-                    scrollDistance = screenSize - orientationHelper.getDecoratedEnd(child);
-                } else if (-screenSize < orientationHelper.getDecoratedStart(child)
-                        && orientationHelper.getDecoratedStart(child) < 0) {
-                    // Child view top is about to enter screen - its distance to parent top
-                    // is less than a full scroll. Align child top with parent top.
-                    scrollDistance = Math.abs(orientationHelper.getDecoratedStart(child));
-                }
-                // There can be two items that are longer than the screen. We stop at the first one.
-                // This is affected by the iteration order.
-                break;
-            }
-        }
-        // Distance should always be positive. Negate its value to scroll up.
-        getRecyclerView().smoothScrollBy(0, -scrollDistance);
-    }
-
-    /**
-     * Scrolls the contents of the RecyclerView down a page. A page is defined as the height of the
-     * {@code PagedRecyclerView}.
-     *
-     * <p>This method will attempt to bring the last item in the list as the first item. If the
-     * current first item in the list is taller than the {@code PagedRecyclerView}, then it will be
-     * scrolled the length of a page, but not snapped to.
-     */
-    void pageDown() {
-        if (getRecyclerView().getLayoutManager() == null
-                || getRecyclerView().getChildCount() == 0) {
-            return;
-        }
-
-        OrientationHelper orientationHelper =
-                getOrientationHelper(getRecyclerView().getLayoutManager());
-        int screenSize = orientationHelper.getTotalSpace();
-        int scrollDistance = screenSize;
-
-        // If the last item is partially visible, page down should bring it to the top.
-        View lastChild = getRecyclerView().getChildAt(getRecyclerView().getChildCount() - 1);
-        if (getRecyclerView().getLayoutManager().isViewPartiallyVisible(lastChild,
-                /* completelyVisible= */ false, /* acceptEndPointInclusion= */ false)) {
-            scrollDistance = orientationHelper.getDecoratedStart(lastChild);
-            if (scrollDistance < 0) {
-                // Scroll value can be negative if the child is longer than the screen size and the
-                // visible area of the screen does not show the start of the child.
-                // Scroll to the next screen if the start value is negative
-                scrollDistance = screenSize;
-            }
-        }
-
-        // The iteration order matters. In case where there are 2 items longer than screen size, we
-        // want to focus on upcoming view (the one at the bottom of screen).
-        for (int i = getRecyclerView().getChildCount() - 1; i >= 0; i--) {
-            /* We treat child View longer than screen size differently:
-             * 1) When it enters screen, next pageDown will align its top with parent top;
-             * 2) When it leaves screen, next pageDown will align its bottom with parent bottom.
-             */
-            View child = getRecyclerView().getChildAt(i);
-            if (child.getHeight() > screenSize) {
-                if (orientationHelper.getDecoratedStart(child) > 0) {
-                    // Child view top is entering screen. Align its top with parent top.
-                    scrollDistance = orientationHelper.getDecoratedStart(child);
-                } else if (screenSize < orientationHelper.getDecoratedEnd(child)
-                        && orientationHelper.getDecoratedEnd(child) < 2 * screenSize) {
-                    // Child view bottom is about to enter screen - its distance to parent bottom
-                    // is less than a full scroll. Align child bottom with parent bottom.
-                    scrollDistance = orientationHelper.getDecoratedEnd(child) - screenSize;
-                }
-                // There can be two items that are longer than the screen. We stop at the first one.
-                // This is affected by the iteration order.
-                break;
-            }
-        }
-
-        getRecyclerView().smoothScrollBy(0, scrollDistance);
-    }
-
-    /**
-     * Determines if scrollbar should be visible or not and shows/hides it accordingly. If this is
-     * being called as a result of adapter changes, it should be called after the new layout has
-     * been calculated because the method of determining scrollbar visibility uses the current
-     * layout. If this is called after an adapter change but before the new layout, the visibility
-     * determination may not be correct.
-     *
-     * @param animate {@code true} if the scrollbar should animate to its new position.
-     *                {@code false} if no animation is used
-     */
-    private void updatePaginationButtons(boolean animate) {
-
-        boolean isAtStart = isAtStart();
-        boolean isAtEnd = isAtEnd();
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-
-        if ((isAtStart && isAtEnd) || layoutManager == null || layoutManager.getItemCount() == 0) {
-            mScrollView.setVisibility(View.INVISIBLE);
-        } else {
-            mScrollView.setVisibility(View.VISIBLE);
-        }
-        setUpEnabled(!isAtStart);
-        setDownEnabled(!isAtEnd);
-
-        if (layoutManager == null) {
-            return;
-        }
-
-        if (layoutManager.canScrollVertically()) {
-            setParameters(
-                    getRecyclerView().computeVerticalScrollRange(),
-                    getRecyclerView().computeVerticalScrollOffset(),
-                    getRecyclerView().computeVerticalScrollExtent(), animate);
-        } else {
-            setParameters(
-                    getRecyclerView().computeHorizontalScrollRange(),
-                    getRecyclerView().computeHorizontalScrollOffset(),
-                    getRecyclerView().computeHorizontalScrollExtent(), animate);
-        }
-
-        mScrollView.invalidate();
-    }
-
-    /** Returns {@code true} if the RecyclerView is completely displaying the first item. */
-    boolean isAtStart() {
-        return mSnapHelper.isAtStart(getRecyclerView().getLayoutManager());
-    }
-
-    /** Returns {@code true} if the RecyclerView is completely displaying the last item. */
-    boolean isAtEnd() {
-        return mSnapHelper.isAtEnd(getRecyclerView().getLayoutManager());
-    }
-
-    /**
-     * Scrolls to the given position in the PagedRecyclerView.
-     *
-     * @param position The position in the list to scroll to.
-     */
-    private void scrollToPosition(int position) {
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-        if (layoutManager == null) {
-            return;
-        }
-
-        RecyclerView.SmoothScroller smoothScroller = mSnapHelper.createScroller(layoutManager);
-        smoothScroller.setTargetPosition(position);
-
-        layoutManager.startSmoothScroll(smoothScroller);
-
-        // Sometimes #scrollToPosition doesn't change the scroll state so we need to make sure
-        // the pagination arrows actually get updated. See b/15801119
-        mHandler.post(() -> updatePaginationButtons(true /*animate*/));
-    }
-
-    /**
-     * Snap to the given position. This method will snap instantly to a position that's "close" to
-     * the given position and then animate a short decelerate to indicate the direction that the
-     * snap happened.
-     *
-     * @param position The position in the list to scroll to.
-     */
-    void snapToPosition(int position) {
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-
-        if (layoutManager == null) {
-            return;
-        }
-
-        int startPosition = position;
-        if ((layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
-            PointF vector = ((RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager)
-                    .computeScrollVectorForPosition(position);
-            // A positive value in the vector means scrolling down, so should offset by scrolling to
-            // an item previous in the list.
-            int offsetDirection = (vector == null || vector.y > 0) ? -1 : 1;
-            startPosition += offsetDirection * SNAP_SCROLL_OFFSET_POSITION;
-
-            // Clamp the start position.
-            startPosition = Math.max(0, Math.min(startPosition, layoutManager.getItemCount() - 1));
-        } else {
-            // If the LayoutManager doesn't implement ScrollVectorProvider (the default for
-            // PagedRecyclerView, LinearLayoutManager does, but if the user has overridden it) then
-            // we cannot compute the direction we need to scroll. So just snap instantly instead.
-            Log.w(TAG, "LayoutManager is not a ScrollVectorProvider, can't do snap animation.");
-        }
-
-        if (layoutManager instanceof LinearLayoutManager) {
-            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(startPosition, 0);
-        } else {
-            layoutManager.scrollToPosition(startPosition);
-        }
-
-        if (startPosition != position) {
-            // The actual scroll above happens on the next update, so we wait for that to finish
-            // before doing the smooth scroll.
-            mScrollView.post(() -> scrollToPosition(position));
-        }
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/CarTabLayout.java b/car-apps-common/src/com/android/car/apps/common/widget/CarTabLayout.java
deleted file mode 100644
index 4dd427f..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/CarTabLayout.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.apps.common.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.LayoutRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StyleRes;
-
-import com.android.car.apps.common.R;
-import com.android.car.apps.common.util.Themes;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Custom tab layout which supports adding tabs dynamically
- *
- * <p>It supports two layout modes:
- * <ul><li>Flexible layout which will fill the width
- * <li>Non-flexible layout which wraps content with a minimum tab width. By setting tab gravity,
- * it can left aligned, right aligned or center aligned.
- *
- * <p>Scrolling function is not supported. If a tab item runs out of the tab layout bound, there
- * is no way to access it. It's better to set the layout mode to flexible in this case.
- *
- * <p>Default tab item inflates from R.layout.car_tab_item, but it also supports custom layout id.
- * By doing this, appearance of tab item view can be customized.
- *
- * <p>Touch feedback is using @android:attr/selectableItemBackground.
- *
- * @param <T> Presents a CarTab entity
- * @deprecated Use {@link com.android.car.ui.TabLayout} instead
- */
-@Deprecated
-public class CarTabLayout<T extends CarTabLayout.CarTab> extends LinearLayout {
-
-    /**
-     * Listener that listens the car tab selection change.
-     *
-     * @param <T> Presents a CarTab entity that has state update on a tab select action
-     */
-    public interface OnCarTabSelectedListener<T extends CarTab> {
-        /** Callback triggered when a car tab is selected. */
-        void onCarTabSelected(T carTab);
-
-        /** Callback triggered when a car tab is unselected. */
-        void onCarTabUnselected(T carTab);
-
-        /** Callback triggered when a car tab is reselected. */
-        void onCarTabReselected(T carTab);
-    }
-
-    /**
-     * No-op implementation of {@link OnCarTabSelectedListener}.
-     *
-     * @param <T> See {@link OnCarTabSelectedListener}
-     */
-    public static class SimpleOnCarTabSelectedListener<T extends CarTab> implements
-            OnCarTabSelectedListener<T> {
-
-        @Override
-        public void onCarTabSelected(T carTab) {
-            // No-op
-        }
-
-        @Override
-        public void onCarTabUnselected(T carTab) {
-            // No-op
-        }
-
-        @Override
-        public void onCarTabReselected(T carTab) {
-            // No-op
-        }
-    }
-
-    // View attributes
-    private final boolean mTabFlexibleLayout;
-    private final int mTabPaddingX;
-
-    private final Set<OnCarTabSelectedListener<T>> mOnCarTabSelectedListeners;
-
-    private final CarTabAdapter<T> mCarTabAdapter;
-
-    public CarTabLayout(@NonNull Context context) {
-        this(context, null);
-    }
-
-    public CarTabLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CarTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        mOnCarTabSelectedListeners = new ArraySet<>();
-
-        TypedArray ta = context.obtainStyledAttributes(
-                attrs, R.styleable.CarTabLayout, defStyle, 0);
-        mTabPaddingX = ta.getDimensionPixelSize(R.styleable.CarTabLayout_tabPaddingX,
-                context.getResources().getDimensionPixelSize(R.dimen.car_tab_padding_x));
-        mTabFlexibleLayout = ta.getBoolean(R.styleable.CarTabLayout_tabFlexibleLayout,
-                context.getResources().getBoolean(R.bool.car_tab_flexible_layout));
-        int tabItemLayout = ta.getResourceId(R.styleable.CarTabLayout_tabItemLayout,
-                R.layout.car_tab_item);
-        ta.recycle();
-
-        mCarTabAdapter = new CarTabAdapter(context, tabItemLayout, this);
-    }
-
-    /**
-     * Add a tab to this layout. The tab will be added at the end of the list. If this is the first
-     * tab to be added it will become the selected tab.
-     */
-    public void addCarTab(T carTab) {
-        mCarTabAdapter.add(carTab);
-        // If there is only one tab in the group, set it to be selected.
-        if (mCarTabAdapter.getCount() == 1) {
-            mCarTabAdapter.selectCarTab(0);
-        }
-    }
-
-    /** Set the tab as the current selected tab. */
-    public void selectCarTab(T carTab) {
-        mCarTabAdapter.selectCarTab(carTab);
-    }
-
-    /** Set the tab at given position as the current selected tab. */
-    public void selectCarTab(int position) {
-        mCarTabAdapter.selectCarTab(position);
-    }
-
-    /** Returns how tab items it has. */
-    public int getCarTabCount() {
-        return mCarTabAdapter.getCount();
-    }
-
-    /** Returns the position of the given car tab. */
-    public int getCarTabPosition(T carTab) {
-        return mCarTabAdapter.getPosition(carTab);
-    }
-
-    /** Return the car tab at the given position. */
-    public T get(int position) {
-        return mCarTabAdapter.getItem(position);
-    }
-
-    /** Clear all car tabs. */
-    public void clearAllCarTabs() {
-        mCarTabAdapter.clear();
-    }
-
-    /** Register a {@link OnCarTabSelectedListener}. Same listener will only be registered once. */
-    public void addOnCarTabSelectedListener(
-            @NonNull OnCarTabSelectedListener onCarTabSelectedListener) {
-        mOnCarTabSelectedListeners.add(onCarTabSelectedListener);
-    }
-
-    /** Unregister a {@link OnCarTabSelectedListener} */
-    public void removeOnCarTabSelectedListener(
-            @NonNull OnCarTabSelectedListener onCarTabSelectedListener) {
-        mOnCarTabSelectedListeners.remove(onCarTabSelectedListener);
-    }
-
-    private void dispatchOnCarTabSelected(T carTab) {
-        for (OnCarTabSelectedListener onCarTabSelectedListener : mOnCarTabSelectedListeners) {
-            onCarTabSelectedListener.onCarTabSelected(carTab);
-        }
-    }
-
-    private void dispatchOnCarTabUnselected(T carTab) {
-        for (OnCarTabSelectedListener onCarTabSelectedListener : mOnCarTabSelectedListeners) {
-            onCarTabSelectedListener.onCarTabUnselected(carTab);
-        }
-    }
-
-    private void dispatchOnCarTabReselected(T carTab) {
-        for (OnCarTabSelectedListener onCarTabSelectedListener : mOnCarTabSelectedListeners) {
-            onCarTabSelectedListener.onCarTabReselected(carTab);
-        }
-    }
-
-    private void addCarTabView(View carTabView, int position) {
-        LayoutParams layoutParams;
-        if (mTabFlexibleLayout) {
-            layoutParams = new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
-            layoutParams.weight = 1;
-        } else {
-            layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT);
-        }
-        addView(carTabView, position, layoutParams);
-    }
-
-    private ViewGroup createCarTabItemView() {
-        LinearLayout carTabItemView = new LinearLayout(mContext);
-        carTabItemView.setOrientation(LinearLayout.VERTICAL);
-        carTabItemView.setGravity(Gravity.CENTER);
-        carTabItemView.setPadding(mTabPaddingX, 0, mTabPaddingX, 0);
-        Drawable backgroundDrawable = Themes.getAttrDrawable(getContext(),
-                R.style.CarTabItemBackground, android.R.attr.background);
-        carTabItemView.setBackground(backgroundDrawable);
-        return carTabItemView;
-    }
-
-    private static class CarTabAdapter<T extends CarTab> extends BaseAdapter {
-        private final Context mContext;
-        private final CarTabLayout mCarTabLayout;
-        @LayoutRes
-        private final int mCarTabItemLayoutRes;
-        private final Typeface mUnselectedTypeface;
-        private final Typeface mSelectedTypeface;
-        private final List<T> mCarTabList;
-
-        private CarTabAdapter(Context context, @LayoutRes int res, CarTabLayout carTabLayout) {
-            mCarTabList = new ArrayList<>();
-            mContext = context;
-            mCarTabItemLayoutRes = res;
-            mCarTabLayout = carTabLayout;
-            mUnselectedTypeface = createStyledTypeface(context, R.style.CarTabItemText);
-            mSelectedTypeface = createStyledTypeface(context, R.style.CarTabSelectedTextTypeface);
-        }
-
-        private void add(@NonNull T carTab) {
-            mCarTabList.add(carTab);
-            notifyItemInserted(mCarTabList.size() - 1);
-        }
-
-        private void clear() {
-            mCarTabList.clear();
-            mCarTabLayout.removeAllViews();
-        }
-
-        private int getPosition(CarTab carTab) {
-            return mCarTabList.indexOf(carTab);
-        }
-
-        @Override
-        public int getCount() {
-            return mCarTabList.size();
-        }
-
-        @Override
-        public T getItem(int position) {
-            return mCarTabList.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        @NonNull
-        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
-            ViewGroup carTabItemView = mCarTabLayout.createCarTabItemView();
-            LayoutInflater.from(mContext).inflate(mCarTabItemLayoutRes, carTabItemView, true);
-
-            presentCarTabItemView(position, carTabItemView);
-            return carTabItemView;
-        }
-
-        private void selectCarTab(CarTab carTab) {
-            selectCarTab(getPosition(carTab));
-        }
-
-        private void selectCarTab(int position) {
-            if (position < 0 || position >= getCount()) {
-                throw new IndexOutOfBoundsException("Invalid position");
-            }
-
-            for (int i = 0; i < getCount(); i++) {
-                CarTab carTabItem = mCarTabList.get(i);
-                boolean isTabSelected = position == i;
-                if (carTabItem.mIsSelected != isTabSelected) {
-                    carTabItem.mIsSelected = isTabSelected;
-                    notifyItemChanged(i);
-                    if (carTabItem.mIsSelected) {
-                        mCarTabLayout.dispatchOnCarTabSelected(carTabItem);
-                    } else {
-                        mCarTabLayout.dispatchOnCarTabUnselected(carTabItem);
-                    }
-                } else if (carTabItem.mIsSelected) {
-                    mCarTabLayout.dispatchOnCarTabReselected(carTabItem);
-                }
-            }
-        }
-
-        /** Represent the car tab item at given position without destroying and recreating UI. */
-        private void notifyItemChanged(int position) {
-            View carTabItemView = mCarTabLayout.getChildAt(position);
-            presentCarTabItemView(position, carTabItemView);
-        }
-
-        private void notifyItemInserted(int position) {
-            View insertedView = getView(position, null, mCarTabLayout);
-            mCarTabLayout.addCarTabView(insertedView, position);
-        }
-
-        private void presentCarTabItemView(int position, @NonNull View carTabItemView) {
-            CarTab carTab = mCarTabList.get(position);
-
-            ImageView iconView = carTabItemView.findViewById(R.id.car_tab_item_icon);
-            TextView textView = carTabItemView.findViewById(R.id.car_tab_item_text);
-
-            carTabItemView.setOnClickListener(view -> selectCarTab(carTab));
-            carTab.bindText(textView);
-            carTab.bindIcon(iconView);
-
-            carTabItemView.setSelected(carTab.mIsSelected);
-            iconView.setSelected(carTab.mIsSelected);
-            textView.setSelected(carTab.mIsSelected);
-            textView.setTypeface(carTab.mIsSelected ? mSelectedTypeface : mUnselectedTypeface);
-        }
-
-        private static Typeface createStyledTypeface(Context context, @StyleRes int styleResId) {
-            // If not specified, default to 0, which stands for normal.
-            int textStyle = Themes.getAttrInteger(context, styleResId, android.R.attr.textStyle);
-            // If not specified, default value will be 0 which is a light font.
-            int textFontWeight = Themes.getAttrInteger(context, styleResId,
-                    android.R.attr.textFontWeight);
-            return Typeface.create(Typeface.defaultFromStyle(textStyle), textFontWeight,
-                    (textStyle & Typeface.ITALIC) != 0);
-        }
-    }
-
-    /** Car tab entity. */
-    public static class CarTab {
-        private final Drawable mIcon;
-        private final CharSequence mText;
-        private boolean mIsSelected;
-
-        public CarTab(@Nullable Drawable icon, @Nullable CharSequence text) {
-            mIcon = icon;
-            mText = text;
-        }
-
-        /** Set tab text. */
-        protected void bindText(TextView textView) {
-            textView.setText(mText);
-        }
-
-        /** Set icon drawable. TODO(b/139444064): revise this api. */
-        protected void bindIcon(ImageView imageView) {
-            imageView.setImageDrawable(mIcon);
-        }
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerView.java b/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerView.java
deleted file mode 100644
index 2917967..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerView.java
+++ /dev/null
@@ -1,695 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.apps.common.widget;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.CarUxRestrictionsUtil;
-import com.android.car.apps.common.R;
-import com.android.car.apps.common.util.ScrollBarUI;
-
-import java.lang.annotation.Retention;
-
-/**
- * View that extends a {@link RecyclerView} and creates a nested {@code RecyclerView} with an option
- * to render a custom scroll bar that has page up and down arrows. Interaction with this view is
- * similar to a {@code RecyclerView} as it takes the same adapter and the layout manager.
- */
-public final class PagedRecyclerView extends RecyclerView {
-
-    private static final boolean DEBUG = false;
-    private static final String TAG = "PagedRecyclerView";
-
-    private final CarUxRestrictionsUtil mCarUxRestrictionsUtil;
-    private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener mListener;
-
-    private boolean mScrollBarEnabled;
-    private int mScrollBarContainerWidth;
-    private @ScrollBarPosition int mScrollBarPosition;
-    private boolean mScrollBarAboveRecyclerView;
-    private String mScrollBarClass;
-    private int mScrollBarPaddingStart;
-    private int mScrollBarPaddingEnd;
-    private boolean mFullyInitialized;
-
-    @Gutter
-    private int mGutter;
-    private int mGutterSize;
-    private RecyclerView mNestedRecyclerView;
-    private Adapter mAdapter;
-    private ScrollBarUI mScrollBarUI;
-
-    /**
-     * The possible values for @{link #setGutter}. The default value is actually
-     * {@link PagedRecyclerView.Gutter#BOTH}.
-     */
-    @IntDef({
-            Gutter.NONE,
-            Gutter.START,
-            Gutter.END,
-            Gutter.BOTH,
-    })
-
-    @Retention(SOURCE)
-    public @interface Gutter {
-        /**
-         * No gutter on either side of the list items. The items will span the full width of the
-         * RecyclerView
-         */
-        int NONE = 0;
-
-        /**
-         * Include a gutter only on the start side (that is, the same side as the scroll bar).
-         */
-        int START = 1;
-
-        /**
-         * Include a gutter only on the end side (that is, the opposite side of the scroll bar).
-         */
-        int END = 2;
-
-        /**
-         * Include a gutter on both sides of the list items. This is the default behaviour.
-         */
-        int BOTH = 3;
-    }
-
-    /**
-     * The possible values for setScrollbarPosition. The default value is actually
-     * {@link PagedRecyclerView.ScrollBarPosition#START}.
-     */
-    @IntDef({
-            ScrollBarPosition.START,
-            ScrollBarPosition.END,
-    })
-
-    @Retention(SOURCE)
-    public @interface ScrollBarPosition {
-        /**
-         * Position the scrollbar to the left of the screen. This is default.
-         */
-        int START = 0;
-
-        /**
-         * Position scrollbar to the right of the screen.
-         */
-        int END = 2;
-    }
-
-    /**
-     * Interface for a {@link RecyclerView.Adapter} to cap the number of items.
-     *
-     * <p>NOTE: it is still up to the adapter to use maxItems in {@link
-     * RecyclerView.Adapter#getItemCount()}.
-     *
-     * <p>the recommended way would be with:
-     *
-     * <pre>{@code
-     * {@literal@}Override
-     * public int getItemCount() {
-     *   return Math.min(super.getItemCount(), mMaxItems);
-     * }
-     * }</pre>
-     */
-    public interface ItemCap {
-        /**
-         * A value to pass to {@link #setMaxItems(int)} that indicates there should be no limit.
-         */
-        int UNLIMITED = -1;
-
-        /**
-         * Sets the maximum number of items available in the adapter. A value less than '0' means
-         * the list should not be capped.
-         */
-        void setMaxItems(int maxItems);
-    }
-
-    /**
-     * Custom layout manager for the outer recyclerview. Since paddings should be applied by the
-     * inner recycler view within its bounds, this layout manager should always have 0 padding.
-     */
-    private class PagedRecyclerViewLayoutManager extends LinearLayoutManager {
-        PagedRecyclerViewLayoutManager(Context context) {
-            super(context);
-        }
-
-        @Override
-        public int getPaddingTop() {
-            return 0;
-        }
-
-        @Override
-        public int getPaddingBottom() {
-            return 0;
-        }
-
-        @Override
-        public int getPaddingStart() {
-            return 0;
-        }
-
-        @Override
-        public int getPaddingEnd() {
-            return 0;
-        }
-
-        @Override
-        public boolean canScrollHorizontally() {
-            return false;
-        }
-
-        @Override
-        public boolean canScrollVertically() {
-            return false;
-        }
-    }
-
-    public PagedRecyclerView(@NonNull Context context) {
-        this(context, null, 0);
-    }
-
-    public PagedRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public PagedRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
-        mListener = this::updateCarUxRestrictions;
-
-        init(context, attrs, defStyle);
-    }
-
-    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
-        TypedArray a = context.obtainStyledAttributes(
-                attrs, R.styleable.PagedRecyclerView, defStyleAttr,
-                R.style.PagedRecyclerView);
-
-        mScrollBarEnabled = a.getBoolean(R.styleable.PagedRecyclerView_scrollBarEnabled,
-                /* defValue= */true);
-        mFullyInitialized = false;
-
-        if (!mScrollBarEnabled) {
-            a.recycle();
-            mFullyInitialized = true;
-            return;
-        }
-
-        mNestedRecyclerView = new RecyclerView(context, attrs,
-                R.style.PagedRecyclerView_NestedRecyclerView);
-
-        super.setLayoutManager(new PagedRecyclerViewLayoutManager(context));
-        super.setAdapter(new PagedRecyclerViewAdapter());
-        super.setNestedScrollingEnabled(false);
-        super.setClipToPadding(false);
-
-        // Gutter
-        mGutter = a.getInt(R.styleable.PagedRecyclerView_gutter, Gutter.BOTH);
-        mGutterSize = getResources().getDimensionPixelSize(R.dimen.car_scroll_bar_margin);
-
-        int carMargin = getResources().getDimensionPixelSize(R.dimen.car_scroll_bar_margin);
-        mScrollBarContainerWidth = a.getDimensionPixelSize(
-                R.styleable.PagedRecyclerView_scrollBarContainerWidth, carMargin);
-
-        mScrollBarPosition = a.getInt(R.styleable.PagedRecyclerView_scrollBarPosition,
-                ScrollBarPosition.START);
-
-        mScrollBarAboveRecyclerView = a.getBoolean(
-                R.styleable.PagedRecyclerView_scrollBarAboveRecyclerView, /* defValue= */true);
-
-        mScrollBarClass = a.getString(R.styleable.PagedRecyclerView_scrollBarCustomClass);
-        a.recycle();
-
-        // Apply inner RV layout changes after the layout has been calculated for this view.
-        this.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-            @Override
-            public void onGlobalLayout() {
-                // View holder layout is still pending.
-                if (PagedRecyclerView.this.findViewHolderForAdapterPosition(0) == null) return;
-
-                PagedRecyclerView.this.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                initNestedRecyclerView();
-                setNestedViewLayout();
-
-                createScrollBarFromConfig();
-
-                mNestedRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
-                        new OnGlobalLayoutListener() {
-                            @Override
-                            public void onGlobalLayout() {
-                                mNestedRecyclerView.getViewTreeObserver()
-                                        .removeOnGlobalLayoutListener(this);
-                                mFullyInitialized = true;
-                            }
-                        });
-            }
-        });
-    }
-
-    /**
-     * Returns {@code true} if the {@PagedRecyclerView} is fully drawn. Using a global layout
-     * listener may not necessarily signify that this view is fully drawn (i.e. when the
-     * scrollbar is enabled). This is because the inner views (scrollbar and inner recycler view)
-     * are drawn after the outer views are finished.
-     */
-    public boolean fullyInitialized() {
-        return mFullyInitialized;
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mCarUxRestrictionsUtil.register(mListener);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mCarUxRestrictionsUtil.unregister(mListener);
-    }
-
-    private void updateCarUxRestrictions(CarUxRestrictions carUxRestrictions) {
-        // If the adapter does not implement ItemCap, then the max items on it cannot be updated.
-        if (!(mAdapter instanceof ItemCap)) {
-            return;
-        }
-
-        int maxItems = ItemCap.UNLIMITED;
-        if ((carUxRestrictions.getActiveRestrictions()
-                & CarUxRestrictions.UX_RESTRICTIONS_LIMIT_CONTENT) != 0) {
-            maxItems = carUxRestrictions.getMaxCumulativeContentItems();
-        }
-
-        int originalCount = mAdapter.getItemCount();
-        ((ItemCap) mAdapter).setMaxItems(maxItems);
-        int newCount = mAdapter.getItemCount();
-
-        if (newCount == originalCount) {
-            return;
-        }
-
-        if (newCount < originalCount) {
-            mAdapter.notifyItemRangeRemoved(
-                    newCount, originalCount - newCount);
-        } else {
-            mAdapter.notifyItemRangeInserted(
-                    originalCount, newCount - originalCount);
-        }
-    }
-
-    @Override
-    public void setClipToPadding(boolean clipToPadding) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setClipToPadding(clipToPadding);
-        } else {
-            super.setClipToPadding(clipToPadding);
-        }
-    }
-
-    @Override
-    public void setAdapter(@Nullable Adapter adapter) {
-        mAdapter = adapter;
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setAdapter(adapter);
-        } else {
-            super.setAdapter(adapter);
-        }
-    }
-
-    @Nullable
-    @Override
-    public Adapter getAdapter() {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.getAdapter();
-        }
-        return super.getAdapter();
-    }
-
-    @Override
-    public void setLayoutManager(@Nullable LayoutManager layout) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setLayoutManager(layout);
-        } else {
-            super.setLayoutManager(layout);
-        }
-    }
-
-    /**
-     * Returns the {@link LayoutManager} for the {@link RecyclerView} displaying the content.
-     *
-     * <p>In cases where the scroll bar is visible and the nested {@link RecyclerView} is
-     * displaying content, {@link #getLayoutManager()} cannot be used because it returns the
-     * {@link LayoutManager} of the outer {@link RecyclerView}. {@link #getLayoutManager()} could
-     * not be overridden to return the effective manager due to interference with accessibility
-     * node tree traversal.
-     */
-    @Nullable
-    public LayoutManager getEffectiveLayoutManager() {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.getLayoutManager();
-        }
-        return super.getLayoutManager();
-    }
-
-    @Override
-    public void setOnScrollChangeListener(OnScrollChangeListener l) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setOnScrollChangeListener(l);
-        } else {
-            super.setOnScrollChangeListener(l);
-        }
-    }
-
-    @Override
-    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setVerticalFadingEdgeEnabled(verticalFadingEdgeEnabled);
-        } else {
-            super.setVerticalFadingEdgeEnabled(verticalFadingEdgeEnabled);
-        }
-    }
-
-    @Override
-    public void setFadingEdgeLength(int length) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setFadingEdgeLength(length);
-        } else {
-            super.setFadingEdgeLength(length);
-        }
-    }
-
-    @Override
-    public void addItemDecoration(@NonNull ItemDecoration decor, int index) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.addItemDecoration(decor, index);
-        } else {
-            super.addItemDecoration(decor, index);
-        }
-    }
-
-    @Override
-    public void addItemDecoration(@NonNull ItemDecoration decor) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.addItemDecoration(decor);
-        } else {
-            super.addItemDecoration(decor);
-        }
-    }
-
-    @Override
-    public void setItemAnimator(@Nullable ItemAnimator animator) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setItemAnimator(animator);
-        } else {
-            super.setItemAnimator(animator);
-        }
-    }
-
-    @Override
-    public void setPadding(int left, int top, int right, int bottom) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setPadding(left, top, right, bottom);
-            if (mScrollBarUI != null) mScrollBarUI.requestLayout();
-        } else {
-            super.setPadding(left, top, right, bottom);
-        }
-    }
-
-    @Override
-    public void setPaddingRelative(int start, int top, int end, int bottom) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setPaddingRelative(start, top, end, bottom);
-            if (mScrollBarUI != null) mScrollBarUI.requestLayout();
-        } else {
-            super.setPaddingRelative(start, top, end, bottom);
-        }
-    }
-
-    @Override
-    public ViewHolder findViewHolderForLayoutPosition(int position) {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.findViewHolderForLayoutPosition(position);
-        } else {
-            return super.findViewHolderForLayoutPosition(position);
-        }
-    }
-
-    @Override
-    public ViewHolder findContainingViewHolder(View view) {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.findContainingViewHolder(view);
-        } else {
-            return super.findContainingViewHolder(view);
-        }
-    }
-
-    @Override
-    @Nullable
-    public View findChildViewUnder(float x, float y) {
-        if (mScrollBarEnabled) {
-            return mNestedRecyclerView.findChildViewUnder(x, y);
-        } else {
-            return super.findChildViewUnder(x, y);
-        }
-    }
-
-    @Override
-    public void addOnScrollListener(@NonNull OnScrollListener listener) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.addOnScrollListener(listener);
-        } else {
-            super.addOnScrollListener(listener);
-        }
-    }
-
-    @Override
-    public void removeOnScrollListener(@NonNull OnScrollListener listener) {
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.removeOnScrollListener(listener);
-        } else {
-            super.removeOnScrollListener(listener);
-        }
-    }
-
-    /**
-     * Calls {@link #layout(int, int, int, int)} for both this RecyclerView and the nested one.
-     */
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    public void layoutBothForTesting(int l, int t, int r, int b) {
-        super.layout(l, t, r, b);
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.layout(l, t, r, b);
-        }
-    }
-
-    @Override
-    public int getPaddingStart() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingStart() : super.getPaddingStart();
-    }
-
-    @Override
-    public int getPaddingEnd() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingEnd() : super.getPaddingEnd();
-    }
-
-    @Override
-    public int getPaddingTop() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingTop() : super.getPaddingTop();
-    }
-
-    @Override
-    public int getPaddingBottom() {
-        return mScrollBarEnabled ? mNestedRecyclerView.getPaddingBottom()
-                : super.getPaddingBottom();
-    }
-
-    @Override
-    public void setVisibility(int visibility) {
-        super.setVisibility(visibility);
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.setVisibility(visibility);
-        }
-    }
-
-    private void initNestedRecyclerView() {
-        PagedRecyclerViewAdapter.NestedRowViewHolder vh =
-                (PagedRecyclerViewAdapter.NestedRowViewHolder)
-                        this.findViewHolderForAdapterPosition(0);
-        if (vh == null) {
-            throw new Error("Outer RecyclerView failed to initialize.");
-        }
-
-        vh.mFrameLayout.addView(mNestedRecyclerView);
-    }
-
-    private void createScrollBarFromConfig() {
-        if (DEBUG) Log.d(TAG, "createScrollBarFromConfig");
-        final String clsName = mScrollBarClass == null
-                ? getContext().getString(R.string.config_scrollBarComponent) : mScrollBarClass;
-        if (clsName == null || clsName.length() == 0) {
-            throw andLog("No scroll bar component configured", null);
-        }
-
-        Class<?> cls;
-        try {
-            cls = getContext().getClassLoader().loadClass(clsName);
-        } catch (Throwable t) {
-            throw andLog("Error loading scroll bar component: " + clsName, t);
-        }
-        try {
-            mScrollBarUI = (ScrollBarUI) cls.newInstance();
-        } catch (Throwable t) {
-            throw andLog("Error creating scroll bar component: " + clsName, t);
-        }
-
-        mScrollBarUI.initialize(getContext(), mNestedRecyclerView, mScrollBarContainerWidth,
-                mScrollBarPosition, mScrollBarAboveRecyclerView);
-
-        mScrollBarUI.setPadding(mScrollBarPaddingStart, mScrollBarPaddingEnd);
-
-        if (DEBUG) Log.d(TAG, "started " + mScrollBarUI.getClass().getSimpleName());
-    }
-
-    /**
-     * Sets the scrollbar's padding start (top) and end (bottom).
-     * This padding is applied in addition to the padding of the inner RecyclerView.
-     */
-    public void setScrollBarPadding(int paddingStart, int paddingEnd) {
-        if (mScrollBarEnabled) {
-            mScrollBarPaddingStart = paddingStart;
-            mScrollBarPaddingEnd = paddingEnd;
-
-            if (mScrollBarUI != null) {
-                mScrollBarUI.setPadding(paddingStart, paddingEnd);
-            }
-        }
-    }
-
-    /**
-     * Set the nested view's layout to the specified value.
-     *
-     * <p>The gutter is the space to the start/end of the list view items and will be equal in size
-     * to the scroll bars. By default, there is a gutter to both the left and right of the list
-     * view items, to account for the scroll bar.
-     */
-    private void setNestedViewLayout() {
-        int startMargin = 0;
-        int endMargin = 0;
-        if ((mGutter & Gutter.START) != 0) {
-            startMargin = mGutterSize;
-        }
-        if ((mGutter & Gutter.END) != 0) {
-            endMargin = mGutterSize;
-        }
-
-        MarginLayoutParams layoutParams =
-                (MarginLayoutParams) mNestedRecyclerView.getLayoutParams();
-
-        layoutParams.setMarginStart(startMargin);
-        layoutParams.setMarginEnd(endMargin);
-
-        layoutParams.height = LayoutParams.MATCH_PARENT;
-        layoutParams.width = super.getLayoutManager().getWidth() - startMargin - endMargin;
-        // requestLayout() isn't sufficient because we also need to resolveLayoutParams().
-        mNestedRecyclerView.setLayoutParams(layoutParams);
-
-        // If there's a gutter, set ClipToPadding to false so that CardView's shadow will still
-        // appear outside of the padding.
-        mNestedRecyclerView.setClipToPadding(startMargin == 0 && endMargin == 0);
-    }
-
-    private RuntimeException andLog(String msg, Throwable t) {
-        Log.e(TAG, msg, t);
-        throw new RuntimeException(msg, t);
-    }
-
-    @Override
-    public Parcelable onSaveInstanceState() {
-        Parcelable superState = super.onSaveInstanceState();
-        SavedState ss = new SavedState(superState, getContext());
-        if (mScrollBarEnabled) {
-            mNestedRecyclerView.saveHierarchyState(ss.mNestedRecyclerViewState);
-        }
-        return ss;
-    }
-
-    @Override
-    public void onRestoreInstanceState(Parcelable state) {
-        if (!(state instanceof SavedState)) {
-            Log.w(TAG, "onRestoreInstanceState called with an unsupported state");
-            super.onRestoreInstanceState(state);
-        } else {
-            SavedState ss = (SavedState) state;
-            super.onRestoreInstanceState(ss.getSuperState());
-            if (mScrollBarEnabled) {
-                mNestedRecyclerView.restoreHierarchyState(ss.mNestedRecyclerViewState);
-            }
-        }
-    }
-
-    static class SavedState extends BaseSavedState {
-        SparseArray mNestedRecyclerViewState;
-        Context mContext;
-
-        SavedState(Parcelable superState, Context c) {
-            super(superState);
-            mContext = c;
-            mNestedRecyclerViewState = new SparseArray();
-        }
-
-        private SavedState(Parcel source, ClassLoader loader) {
-            super(source, loader);
-            mNestedRecyclerViewState = source.readSparseArray(loader);
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flags) {
-            super.writeToParcel(out, flags);
-            out.writeSparseArray(mNestedRecyclerViewState);
-        }
-
-        public static final Parcelable.Creator<SavedState> CREATOR =
-                new Parcelable.Creator<SavedState>() {
-            public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in, getClass().getClassLoader());
-            }
-
-            public SavedState[] newArray(int size) {
-                return new SavedState[size];
-            }
-        };
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerViewAdapter.java b/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerViewAdapter.java
deleted file mode 100644
index bc35a37..0000000
--- a/car-apps-common/src/com/android/car/apps/common/widget/PagedRecyclerViewAdapter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.apps.common.widget;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.apps.common.R;
-
-/**
- * The adapter for the parent recyclerview in {@link PagedRecyclerView} widget.
- */
-final class PagedRecyclerViewAdapter
-        extends RecyclerView.Adapter<PagedRecyclerViewAdapter.NestedRowViewHolder> {
-
-    @Override
-    public PagedRecyclerViewAdapter.NestedRowViewHolder onCreateViewHolder(ViewGroup parent,
-            int viewType) {
-        View v = LayoutInflater.from(parent.getContext())
-                .inflate(R.layout.paged_recycler_view_item, parent, false);
-        return new NestedRowViewHolder(v);
-    }
-
-    // Replace the contents of a view (invoked by the layout manager). Intentionally left empty
-    // since this adapter is an empty shell for the nested recyclerview.
-    @Override
-    public void onBindViewHolder(NestedRowViewHolder holder, int position) {
-    }
-
-    // Return the size of your dataset (invoked by the layout manager)
-    @Override
-    public int getItemCount() {
-        return 1;
-    }
-
-    /**
-     * The viewholder class for the parent recyclerview.
-     */
-    static class NestedRowViewHolder extends RecyclerView.ViewHolder {
-        public FrameLayout mFrameLayout;
-
-        NestedRowViewHolder(View view) {
-            super(view);
-            mFrameLayout = view.findViewById(R.id.nested_recycler_view_layout);
-        }
-    }
-}
diff --git a/car-apps-common/tests/Android.mk b/car-apps-common/tests/Android.mk
deleted file mode 100644
index 9f0a4e8..0000000
--- a/car-apps-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-apps-common/tests/robotests/Android.mk b/car-apps-common/tests/robotests/Android.mk
deleted file mode 100644
index 2438678..0000000
--- a/car-apps-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarAppsCommon app just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarAppsCommon
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_JAVA_LIBRARIES := android.car
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-apps-common
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Apps Common Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarAppsCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-
-LOCAL_INSTRUMENTATION_FOR := CarAppsCommon
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Apps Common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarAppsCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    CarAppsCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarAppsCommon
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-apps-common/tests/robotests/AndroidManifest.xml b/car-apps-common/tests/robotests/AndroidManifest.xml
deleted file mode 100644
index 81f5739..0000000
--- a/car-apps-common/tests/robotests/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2019 Google Inc.
-
-    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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.apps.common.robotests">
-</manifest>
diff --git a/car-apps-common/tests/robotests/config/robolectric.properties b/car-apps-common/tests/robotests/config/robolectric.properties
deleted file mode 100644
index fa63823..0000000
--- a/car-apps-common/tests/robotests/config/robolectric.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2019 Google Inc.
-#
-# 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.
-#
-manifest=packages/apps/Car/libs/car-apps-common/tests/robotests/AndroidManifest.xml
-sdk=NEWEST_SDK
diff --git a/car-apps-common/tests/robotests/src/com/android/car/apps/common/CarUxRestrictionsUtilTest.java b/car-apps-common/tests/robotests/src/com/android/car/apps/common/CarUxRestrictionsUtilTest.java
deleted file mode 100755
index 2cadad3..0000000
--- a/car-apps-common/tests/robotests/src/com/android/car/apps/common/CarUxRestrictionsUtilTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.apps.common;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.car.drivingstate.CarUxRestrictions;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class CarUxRestrictionsUtilTest {
-    private int[] mRestrictionsArray;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mRestrictionsArray = new int[]{
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
-                        | CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
-                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED
-        };
-    }
-
-    @Test
-    public void testNullActiveRestriction() {
-        CarUxRestrictions activeRestrictions = null;
-        boolean[] expectedResults = {true, true, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-
-    @Test
-    public void testOneActiveRestriction() {
-        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD, /* timestamp= */0).build();
-        boolean[] expectedResults = {true, false, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-
-    @Test
-    public void testMultipleActiveRestrictions() {
-        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
-                        | CarUxRestrictions.UX_RESTRICTIONS_NO_TEXT_MESSAGE, /* timestamp= */
-                0).build();
-        boolean[] expectedResults = {true, false, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-}
diff --git a/car-apps-common/tests/robotests/src/com/android/car/apps/common/TestConfig.java b/car-apps-common/tests/robotests/src/com/android/car/apps/common/TestConfig.java
deleted file mode 100644
index baf9b51..0000000
--- a/car-apps-common/tests/robotests/src/com/android/car/apps/common/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.apps.common;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 23;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-apps-common/AndroidManifest.xml";
-}
diff --git a/car-arch-common/Android.bp b/car-arch-common/Android.bp
new file mode 100644
index 0000000..6272d40
--- /dev/null
+++ b/car-arch-common/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2018 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.
+//
+
+// This is an unbundled target, sdk_version must be "system_current". If the car library is ever
+// needed, android."car-stubs" or "android.car-system-stubs" must be used.
+android_library {
+    name: "car-arch-common",
+
+    srcs: ["src/**/*.java"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    sdk_version: "system_current",
+
+    static_libs: [
+        "androidx.lifecycle_lifecycle-extensions",
+        "androidx.lifecycle_lifecycle-common-java8",
+        "androidx.annotation_annotation",
+        "junit",
+    ],
+}
diff --git a/car-arch-common/Android.mk b/car-arch-common/Android.mk
deleted file mode 100644
index 712f170..0000000
--- a/car-arch-common/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-arch-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    androidx.lifecycle_lifecycle-extensions \
-    androidx.lifecycle_lifecycle-common-java8 \
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.annotation_annotation \
-    junit \
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java b/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java
index 632096b..1fc4ff1 100644
--- a/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java
+++ b/car-arch-common/src/com/android/car/arch/common/LiveDataFunctions.java
@@ -18,9 +18,8 @@
 
 import static java.util.Objects.requireNonNull;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.arch.core.util.Function;
 import androidx.core.util.Pair;
 import androidx.lifecycle.LiveData;
diff --git a/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java b/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java
index 625d48c..f553609 100644
--- a/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java
+++ b/car-arch-common/src/com/android/car/arch/common/testing/CaptureObserver.java
@@ -17,8 +17,7 @@
 package com.android.car.arch.common.testing;
 
 
-import android.annotation.Nullable;
-
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.lifecycle.Observer;
 
diff --git a/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java b/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java
index 540581d..c27b51e 100644
--- a/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java
+++ b/car-arch-common/src/com/android/car/arch/common/testing/TestLifecycleOwner.java
@@ -16,8 +16,7 @@
 
 package com.android.car.arch.common.testing;
 
-import android.annotation.NonNull;
-
+import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleOwner;
diff --git a/car-arch-common/tests/Android.mk b/car-arch-common/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-arch-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-arch-common/tests/robotests/Android.bp b/car-arch-common/tests/robotests/Android.bp
new file mode 100644
index 0000000..dbe65bf
--- /dev/null
+++ b/car-arch-common/tests/robotests/Android.bp
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2018 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.
+//
+
+//###########################################################
+// CarArchCommon app just for Robolectric test target.     #
+//###########################################################
+android_app {
+    name: "CarArchCommon",
+
+    platform_apis: true,
+
+    privileged: true,
+
+    static_libs: ["car-arch-common"],
+}
+
+//###############################################
+// Car Arch Common Robolectric test target. #
+//###############################################
+android_robolectric_test {
+    name: "CarArchCommonRoboTests",
+
+    srcs: ["src/**/*.java"],
+
+    java_resource_dirs: ["config"],
+
+    // Include the testing libraries
+    libs: [
+        "androidx.arch.core_core-runtime",
+        "androidx.arch.core_core-common",
+    ],
+
+    instrumentation_for: "CarArchCommon",
+}
diff --git a/car-arch-common/tests/robotests/Android.mk b/car-arch-common/tests/robotests/Android.mk
deleted file mode 100644
index 83ba038..0000000
--- a/car-arch-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarArchCommon app just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarArchCommon
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-arch-common
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Arch Common Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarArchCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    androidx.arch.core_core-runtime \
-    androidx.arch.core_core-common \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_INSTRUMENTATION_FOR := CarArchCommon
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Arch Common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarArchCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    CarArchCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarArchCommon
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-arch-common/tests/robotests/config/robolectric.properties b/car-arch-common/tests/robotests/config/robolectric.properties
index 6b56350..4c863dc 100644
--- a/car-arch-common/tests/robotests/config/robolectric.properties
+++ b/car-arch-common/tests/robotests/config/robolectric.properties
@@ -13,5 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-manifest=packages/apps/Car/libs/car-arch-common/tests/robotests/AndroidManifest.xml
 sdk=NEWEST_SDK
diff --git a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java
index d41db9f..cdcfcb0 100644
--- a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java
+++ b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LiveDataFunctionsTest.java
@@ -42,7 +42,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 import java.util.Objects;
 import java.util.function.BiFunction;
@@ -50,7 +49,6 @@
 import java.util.function.Supplier;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LiveDataFunctionsTest {
 
     @Rule
diff --git a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java
index fd3d883..d64a0c1 100644
--- a/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java
+++ b/car-arch-common/tests/robotests/src/com/android/car/arch/common/LoadingSwitchMapTest.java
@@ -32,10 +32,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LoadingSwitchMapTest {
 
     @Rule
diff --git a/car-arch-common/tests/robotests/src/com/android/car/arch/common/TestConfig.java b/car-arch-common/tests/robotests/src/com/android/car/arch/common/TestConfig.java
deleted file mode 100644
index 1ae5174..0000000
--- a/car-arch-common/tests/robotests/src/com/android/car/arch/common/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.arch.common;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 23;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-arch-common/AndroidManifest.xml";
-}
diff --git a/car-assist-client-lib/src/com/android/car/assist/client/CarAssistUtils.java b/car-assist-client-lib/src/com/android/car/assist/client/CarAssistUtils.java
index 6007637..1f9d915 100644
--- a/car-assist-client-lib/src/com/android/car/assist/client/CarAssistUtils.java
+++ b/car-assist-client-lib/src/com/android/car/assist/client/CarAssistUtils.java
@@ -164,7 +164,8 @@
         return hasMessagingStyle(sbn)
                 && hasRequiredAssistantCallbacks(sbn)
                 && ((getReplyAction(sbn.getNotification()) == null)
-                    || replyCallbackHasRemoteInput(sbn));
+                    || replyCallbackHasRemoteInput(sbn))
+                && assistantCallbacksShowNoUi(sbn);
     }
 
     /** Returns true if the semantic action provided can be supported. */
diff --git a/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java b/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java
index db13ab1..fe8c5ae 100644
--- a/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java
+++ b/car-assist-client-lib/src/com/android/car/assist/client/FallbackAssistant.java
@@ -115,7 +115,6 @@
         }
 
         List<CharSequence> messages = new ArrayList<>();
-
         List<Message> messageList = Message.getMessagesFromBundleArray(messagesBundle);
         if (messageList == null || messageList.isEmpty()) {
             Log.w(TAG, "No messages could be extracted from the bundle");
diff --git a/car-broadcastradio-support/Android.bp b/car-broadcastradio-support/Android.bp
new file mode 100644
index 0000000..cf0b1bb
--- /dev/null
+++ b/car-broadcastradio-support/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 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.
+//
+
+android_library {
+    name: "car-broadcastradio-support",
+
+    srcs: ["src/**/*.java"],
+    aidl: {
+        export_include_dirs: ["src"],
+    },
+    resource_dirs: ["res"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    dist: {
+        targets: ["dist_files"],
+    },
+}
diff --git a/car-broadcastradio-support/Android.mk b/car-broadcastradio-support/Android.mk
deleted file mode 100644
index 67f37ef..0000000
--- a/car-broadcastradio-support/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := car-broadcastradio-support
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/src
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_USE_AAPT2 := true
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq ($(BOARD_IS_AUTOMOTIVE), true)
-$(call dist-for-goals,dist_files,$(full_classes_jar):$(LOCAL_MODULE).jar)
-endif
diff --git a/car-media-common/Android.bp b/car-media-common/Android.bp
new file mode 100644
index 0000000..b85ea3b
--- /dev/null
+++ b/car-media-common/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2016 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.
+//
+
+android_library {
+    name: "car-media-common",
+
+    srcs: ["src/**/*.java"],
+
+    resource_dirs: ["res"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    static_libs: [
+        "androidx.cardview_cardview",
+        "androidx.legacy_legacy-support-v4",
+        "androidx.recyclerview_recyclerview",
+        "androidx.mediarouter_mediarouter",
+        "androidx-constraintlayout_constraintlayout",
+        "car-apps-common",
+        "car-arch-common",
+        "androidx-constraintlayout_constraintlayout-solver",
+    ],
+
+    libs: ["android.car-system-stubs"],
+    sdk_version: "system_current",
+}
diff --git a/car-media-common/Android.mk b/car-media-common/Android.mk
deleted file mode 100644
index c5041c4..0000000
--- a/car-media-common/Android.mk
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-media-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.cardview_cardview \
-    androidx.legacy_legacy-support-v4 \
-    androidx.recyclerview_recyclerview \
-    androidx.mediarouter_mediarouter \
-    androidx-constraintlayout_constraintlayout \
-    car-apps-common \
-    car-arch-common
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    androidx-constraintlayout_constraintlayout-solver
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-media-common-disklrucache-target
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/disklrucache/SNAPSHOT/disklrucache-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-media-common-gifdecoder-target
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/gifdecoder/SNAPSHOT/gifdecoder-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-media-common-glide-target
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/glide/SNAPSHOT/glide-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
\ No newline at end of file
diff --git a/car-media-common/res/drawable/fab_empty_foreground.xml b/car-media-common/res/drawable/fab_empty_foreground.xml
deleted file mode 100644
index 8af802a..0000000
--- a/car-media-common/res/drawable/fab_empty_foreground.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2018, 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.
--->
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:radius="0dp"
-    android:color="@*android:color/car_card" />
diff --git a/car-media-common/res/drawable/seekbar_background.xml b/car-media-common/res/drawable/seekbar_background.xml
deleted file mode 100644
index fcd06a2..0000000
--- a/car-media-common/res/drawable/seekbar_background.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2018, 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.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:id="@android:id/background"
-        android:drawable="@android:color/transparent" />
-
-    <item android:id="@android:id/secondaryProgress">
-        <scale android:scaleWidth="100%"
-            android:drawable="@android:color/transparent" />
-    </item>
-
-    <item android:id="@android:id/progress">
-        <scale android:scaleWidth="100%"
-            android:drawable="@drawable/progressbar" />
-    </item>
-
-</layer-list>
diff --git a/car-media-common/res/layout/minimized_play_pause_stop_button_layout.xml b/car-media-common/res/layout/minimized_play_pause_stop_button_layout.xml
new file mode 100644
index 0000000..1d70c72
--- /dev/null
+++ b/car-media-common/res/layout/minimized_play_pause_stop_button_layout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/play_pause_container"
+    android:focusable="false"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+    <com.android.car.media.common.PlayPauseStopImageView
+        android:id="@+id/play_pause_stop"
+        style="@style/Widget.ActionButton"
+        android:src="@drawable/ic_play_pause_stop_animated"/>
+    <ProgressBar
+        android:id="@+id/circular_progress_bar"
+        android:layout_width="@dimen/fab_spinner_size"
+        android:layout_height="@dimen/fab_spinner_size"
+        android:layout_gravity="center"
+        android:padding="9dp"
+        android:indeterminateDrawable="@drawable/music_buffering"
+        android:indeterminateTint="@color/fab_spinner_indeterminate_color"
+        android:progressDrawable="@drawable/circular_progress_bar"
+        android:progressTint="@color/minimized_progress_bar_highlight"
+        android:progressBackgroundTint="@color/minimized_progress_bar_background"
+        android:focusable="false"
+        android:indeterminateOnly="false"/>
+</FrameLayout>
diff --git a/car-media-common/res/layout/play_pause_stop_button_layout.xml b/car-media-common/res/layout/play_pause_stop_button_layout.xml
index f7700fe..f61a821 100644
--- a/car-media-common/res/layout/play_pause_stop_button_layout.xml
+++ b/car-media-common/res/layout/play_pause_stop_button_layout.xml
@@ -20,11 +20,9 @@
     android:focusable="false"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
-    <!-- The invisible foreground ripple stops Android O from drawing an ugly square over the play button -->
     <com.android.car.media.common.PlayPauseStopImageView
         android:id="@+id/play_pause_stop"
         style="@style/Widget.ActionButton"
-        android:foreground="@drawable/fab_empty_foreground"
         android:src="@drawable/ic_play_pause_stop_animated"/>
     <ProgressBar
         android:id="@+id/circular_progress_bar"
diff --git a/car-media-common/res/layout/playback_fragment.xml b/car-media-common/res/layout/playback_fragment.xml
index 17e10b0..bd77f74 100644
--- a/car-media-common/res/layout/playback_fragment.xml
+++ b/car-media-common/res/layout/playback_fragment.xml
@@ -14,115 +14,145 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<androidx.cardview.widget.CardView
+<com.android.car.ui.FocusArea
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_height="match_parent"
     android:layout_width="match_parent"
-    app:cardElevation="0dp"
-    app:cardCornerRadius="6dp">
+    android:layout_height="match_parent">
 
-    <com.android.car.apps.common.CrossfadeImageView
-        android:id="@+id/album_background"
-        android:foreground="?android:attr/selectableItemBackground"
-        android:layout_width="match_parent"
+    <androidx.cardview.widget.CardView
         android:layout_height="match_parent"
-        android:scaleType="fitStart" />
-
-    <View
-        android:id="@+id/playback_scrim"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/album_art_scrim"
-        android:alpha="@dimen/album_art_scrim_alpha"/>
+        app:cardElevation="0dp"
+        app:cardCornerRadius="6dp">
 
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/playback_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        <com.android.car.apps.common.CrossfadeImageView
+            android:id="@+id/album_background"
+            android:foreground="?android:attr/selectableItemBackground"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:focusable="false"
+            android:scaleType="fitStart"/>
 
-        <ImageView
-            android:id="@+id/app_icon"
-            android:layout_width="@dimen/app_selector_icon_size"
-            android:layout_height="@dimen/app_selector_icon_size"
-            android:layout_gravity="center"
-            android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
-            android:background="?android:attr/selectableItemBackground"
-            android:src="@drawable/ic_app_switch"
-            app:layout_constraintTop_toTopOf="@+id/app_name"
-            app:layout_constraintBottom_toBottomOf="@+id/app_name"
-            app:layout_constraintStart_toStartOf="parent"/>
+        <View
+            android:id="@+id/playback_scrim"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/album_art_scrim"
+            android:focusable="true"
+            android:alpha="@dimen/album_art_scrim_alpha"/>
 
-        <TextView
-            android:id="@+id/app_name"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
-            android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
-            android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:singleLine="true"
-            android:includeFontPadding="false"
-            android:textAlignment="viewStart"
-            app:layout_constraintStart_toEndOf="@+id/app_icon"
-            app:layout_constraintEnd_toStartOf="@+id/app_selector_container"
-            app:layout_constraintTop_toTopOf="parent"/>
-
-        <TextView
-            android:id="@+id/title"
-            style="@style/PlaybackTitleStyle"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
-            android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
-            android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/app_name"/>
-
-        <TextView
-            android:id="@+id/subtitle"
-            style="@style/PlaybackSubtitleStyle"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
-            android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
-            android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toStartOf="@+id/app_selector_container"
-            app:layout_constraintTop_toBottomOf="@+id/title"/>
-
-        <FrameLayout
-            android:id="@+id/app_selector_container"
-            xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="@dimen/app_selector_icon_touch_target"
-            android:layout_height="@dimen/app_selector_icon_touch_target"
-            android:background="?android:attr/selectableItemBackground"
-            android:layout_marginEnd="@dimen/app_selector_margin_x"
-            app:layout_constraintTop_toTopOf="@+id/app_name"
-            app:layout_constraintBottom_toBottomOf="@+id/app_name"
-            app:layout_constraintEnd_toEndOf="parent">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/playback_container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
 
             <ImageView
-                android:id="@+id/app_selector"
+                android:id="@+id/app_icon"
                 android:layout_width="@dimen/app_selector_icon_size"
                 android:layout_height="@dimen/app_selector_icon_size"
                 android:layout_gravity="center"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:background="?android:attr/selectableItemBackground"
                 android:src="@drawable/ic_app_switch"
-                android:tint="@color/icon_tint" />
-        </FrameLayout>
+                app:layout_constraintTop_toTopOf="@+id/app_name"
+                app:layout_constraintBottom_toBottomOf="@+id/app_name"
+                app:layout_constraintStart_toStartOf="parent"/>
 
-        <com.android.car.media.common.PlaybackControlsActionBar
-            android:id="@+id/playback_controls"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/playback_fragment_controls_margin_bottom"
-            app:columns="3"
-            app:enableOverflow="false"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"/>
+            <TextView
+                android:id="@+id/app_name"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:singleLine="true"
+                android:includeFontPadding="false"
+                app:layout_constraintStart_toEndOf="@+id/app_icon"
+                app:layout_constraintEnd_toStartOf="@+id/app_selector_container"
+                app:layout_constraintTop_toTopOf="parent"/>
 
-    </androidx.constraintlayout.widget.ConstraintLayout>
+            <TextView
+                android:id="@+id/title"
+                style="@style/PlaybackTitleStyle"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/app_name"/>
 
-</androidx.cardview.widget.CardView>
+            <TextView
+                android:id="@+id/subtitle"
+                style="@style/PlaybackSubtitleStyle"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/playback_fragment_text_margin_top"
+                android:layout_marginStart="@dimen/playback_fragment_text_margin_x"
+                android:layout_marginEnd="@dimen/playback_fragment_text_margin_x"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toStartOf="@+id/app_selector_container"
+                app:layout_constraintTop_toBottomOf="@+id/title"/>
+
+            <com.android.car.apps.common.UxrTextView
+                android:id="@+id/error_message"
+                style="@style/FullScreenErrorMessageStyle"
+                android:layout_marginHorizontal="@dimen/playback_fragment_text_margin_x"
+                android:maxLines="@integer/widget_error_text_max_lines"
+                app:layout_constraintVertical_chainStyle="packed"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/app_name"
+                app:layout_constraintBottom_toTopOf="@+id/error_button"
+            />
+
+            <com.android.car.apps.common.UxrButton
+                android:id="@+id/error_button"
+                style="@style/FullScreenErrorButtonStyle"
+                android:layout_marginTop="@dimen/playback_fragment_error_button_margin_top"
+                android:layout_marginBottom="@dimen/playback_fragment_error_button_margin_bottom"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/error_message"
+                app:layout_constraintBottom_toBottomOf="parent"
+            />
+
+            <FrameLayout
+                android:id="@+id/app_selector_container"
+                xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="@dimen/app_selector_icon_touch_target"
+                android:layout_height="@dimen/app_selector_icon_touch_target"
+                android:background="?android:attr/selectableItemBackground"
+                android:layout_marginEnd="@dimen/app_selector_margin_x"
+                app:layout_constraintTop_toTopOf="@+id/app_name"
+                app:layout_constraintBottom_toBottomOf="@+id/app_name"
+                app:layout_constraintEnd_toEndOf="parent">
+
+                <ImageView
+                    android:id="@+id/app_selector"
+                    android:layout_width="@dimen/app_selector_icon_size"
+                    android:layout_height="@dimen/app_selector_icon_size"
+                    android:layout_gravity="center"
+                    android:src="@drawable/ic_app_switch"
+                    android:tint="@color/icon_tint"/>
+            </FrameLayout>
+
+            <com.android.car.media.common.PlaybackControlsActionBar
+                android:id="@+id/playback_controls"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="@dimen/playback_fragment_controls_margin_bottom"
+                app:columns="3"
+                app:enableOverflow="false"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+    </androidx.cardview.widget.CardView>
+
+</com.android.car.ui.FocusArea>
diff --git a/car-media-common/res/values-af/strings.xml b/car-media-common/res/values-af/strings.xml
index c4efced..81dc44c 100644
--- a/car-media-common/res/values-af/strings.xml
+++ b/car-media-common/res/values-af/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumkunswerk"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Titelloos"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Iets is fout. Probeer later."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Kan dit nie op die oomblik doen nie"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Hierdie program kan dit nie doen nie"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Meld aan om hierdie program te gebruik"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premiumtoegang word vereis"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Luister tans op te veel toestelle"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Daardie inhoud word geblokkeer"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Kan nie daardie inhoud hier kry nie"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Speel reeds daardie inhoud"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Kan nie meer snitte oorslaan nie"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Kon nie voltooi word nie. Probeer weer."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Daar is niks anders op die waglys nie"</string>
 </resources>
diff --git a/car-media-common/res/values-am/strings.xml b/car-media-common/res/values-am/strings.xml
index 9888274..1d89404 100644
--- a/car-media-common/res/values-am/strings.xml
+++ b/car-media-common/res/values-am/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"የአልበም ስነ ጥበብ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"ርዕስ የለም"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"የሆነ ችግር አለ። በኋላ ይሞክሩ።"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"አሁን ይህን ማድረግ አይቻልም"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ይህ መተግበሪያ ይህን ማድረግ አይችልም"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ይህን መተግበሪያ ለመጠቀም በመለያ ይግቡ"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ፕሪሚየም መዳረሻ ያስፈልጋል"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"ከልክ በላይ ብዙ በሆኑ መሣሪያዎች ላይ በማዳመጥ ላይ"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ይዘቱ ታግዷል"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ይዘቱን እዚህ ማግኘት አልተቻለም"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ይዘቱ አስቀድሞ በመጫወት ላይ"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ተጨማሪ ትራኮችን መዝለል አይቻልም"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"መጨረስ አልተቻለም። እንደገና ይሞክሩ።"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"ሌላ ምንም ነገር ወረፋ አልያዘም"</string>
 </resources>
diff --git a/car-media-common/res/values-ar/strings.xml b/car-media-common/res/values-ar/strings.xml
index 609709e..ca21255 100644
--- a/car-media-common/res/values-ar/strings.xml
+++ b/car-media-common/res/values-ar/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"صورة الألبوم"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"بلا عنوان"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"حدث خطأ. يُرجى المحاولة لاحقًا."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"يتعذّر على التطبيق تنفيذ هذا الإجراء في الوقت الحالي."</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"يتعذّر على التطبيق تنفيذ هذا الإجراء."</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"سجِّل دخولك لاستخدام هذا التطبيق."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"مطلوب الحصول على إذن وصول بحساب مدفوع."</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"يتم الآن الاستماع على أجهزة أكثر من الحدّ المسموح به."</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"تم حظر هذا المحتوى."</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"لا يمكن الحصول على هذا المحتوى من هنا."</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"جارٍ تشغيل هذا المحتوى."</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"لا يمكن تخطّي المزيد من المقاطع الصوتية."</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"تعذَّر الإنهاء. يُرجى إعادة المحاولة."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"لم يتم وضع أي مقطع صوتي آخر في قائمة الانتظار."</string>
 </resources>
diff --git a/car-media-common/res/values-as/strings.xml b/car-media-common/res/values-as/strings.xml
index 1513a5e..6bf03a7 100644
--- a/car-media-common/res/values-as/strings.xml
+++ b/car-media-common/res/values-as/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"এলবাম আৰ্ট"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"কোনো শিৰোনাম নাই"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"কিবা ভুল হ’ল। পাছত চেষ্টা কৰক।"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"সেইটো এই মুহূৰ্তত কৰিব নোৱাৰি"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"এই এপ্‌টোৱে সেইটো কৰিব নোৱাৰে"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"এই এপ্‌টো ব্যৱহাৰ কৰিবলৈ ছাইন ইন কৰক"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium এক্সেছৰ আৱশ্যক"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"বহুকেইটা ডিভাইচত শুনি আছে"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"সেই সমলটো অৱৰোধ কৰা আছে"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"সেই সমলটো ইয়াত পাব নোৱাৰি"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"সেই সমলটো ইতিমধ্যে প্লে’ হৈ আছে"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"আৰু ট্ৰেক এৰি যাব নোৱাৰি"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"সম্পূর্ণ কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰক।"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"শাৰীত অন্য একো নাই"</string>
 </resources>
diff --git a/car-media-common/res/values-az/strings.xml b/car-media-common/res/values-az/strings.xml
index 9e8a836..80509ae 100644
--- a/car-media-common/res/values-az/strings.xml
+++ b/car-media-common/res/values-az/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albom təsviri"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Başlıq yoxdur"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Xəta baş verdi. Sonra cəhd edin."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Hazırda onu etmək olmur"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Bu tətbiq onu edə bilmir"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Bu tətbiqi istifadə etmək üçün daxil olun"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium giriş tələb olunur"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Çox cihazda dinləmə aşkarlanıb"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Bu məzmun bloklanıb"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Bu məzmunu əldə etmək mümkün deyil"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Hazırda bu məzmun oxudulur"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Başqa treki keçmək mümkün deyil"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Bitirmək mümkün olmadı. Yenidən cəhd edin."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Növbədə başqa heç nə yoxdur"</string>
 </resources>
diff --git a/car-media-common/res/values-b+sr+Latn/strings.xml b/car-media-common/res/values-b+sr+Latn/strings.xml
index 60ea824..26310be 100644
--- a/car-media-common/res/values-b+sr+Latn/strings.xml
+++ b/car-media-common/res/values-b+sr+Latn/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Omot albuma"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Bez naslova"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Došlo je do greške. Probajte kasnije."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Trenutno ne može to da uradi"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ova aplikacija ne može to da uradi"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Prijavite se da biste koristili ovu aplikaciju"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Potreban je premijum pristup"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Slušate na previše uređaja"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Taj sadržaj je blokiran"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Ne možete da dobijete taj sadržaj ovde"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Taj sadržaj se već reprodukuje"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Ne možete više da preskačete pesme"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nismo uspeli da dovršimo radnju. Probajte opet."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ništa drugo nije stavljeno u redosled"</string>
 </resources>
diff --git a/car-media-common/res/values-be/strings.xml b/car-media-common/res/values-be/strings.xml
index 4a98eab..d782e53 100644
--- a/car-media-common/res/values-be/strings.xml
+++ b/car-media-common/res/values-be/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Вокладка альбома"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Без назвы"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Узнікла памылка. Паўтарыце спробу пазней."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Не ўдаецца выканаць гэты запыт"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Дзеянне недаступна ў гэтай праграме"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Каб выкарыстоўваць гэту праграму, увайдзіце"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Патрабуецца платны доступ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Праслухоўванне адбываецца на занадта вялікай колькасці прылад"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Гэта змесціва заблакіравана"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"У вашым рэгіёне загрузіць гэта змесціва нельга"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Гэта змесціва ўжо прайграецца"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Прапускаць трэкі больш нельга"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Не ўдалося завяршыць. Паўтарыце спробу."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"У чарзе пуста"</string>
 </resources>
diff --git a/car-media-common/res/values-bg/strings.xml b/car-media-common/res/values-bg/strings.xml
index f595ed8..980e0fb 100644
--- a/car-media-common/res/values-bg/strings.xml
+++ b/car-media-common/res/values-bg/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Обложка на албума"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Няма заглавие"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Нещо не е наред. Опитайте по-късно."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Понастоящем тази заявка не може да се изпълни"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Приложението не може да изпълни тази заявка"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Влезте в профила си, за да използвате това приложение"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"За достъп се изисква платен профил"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Слуша се на твърде много устройства"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Това съдържание е блокирано"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Това съдържание не е налице за региона ви"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Това съдържание вече се възпроизвежда"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Не могат да се пропускат повече записи"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Не можа да завърши. Опитайте отново."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Няма нищо друго в опашката"</string>
 </resources>
diff --git a/car-media-common/res/values-bn/strings.xml b/car-media-common/res/values-bn/strings.xml
index c7366d7..d02e247 100644
--- a/car-media-common/res/values-bn/strings.xml
+++ b/car-media-common/res/values-bn/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"অ্যালবাম আর্ট"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"কোনও শীর্ষক নেই"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"কোনও সমস্যা হয়েছে। পরে চেষ্টা করুন।"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"এই কাজটি এখন করা যাবে না"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"এই অ্যাপে এই কাজটি করা যাবে না"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"এই অ্যাপ ব্যবহার করতে সাইন-ইন করুন"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium অ্যাক্সেস থাকতে হবে"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"একাধিক ডিভাইসে শোনা হচ্ছে"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ওই কন্টেন্টটি ব্লক করা আছে"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ওই কন্টেন্টটি এখানে পাওয়া যাবে না"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"কন্টেন্টটি আগে থেকেই চলছে"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"আর কোনও ট্র্যাক এড়িয়ে যেতে পারবেন না"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"সম্পূর্ণ করা যায়নি। আবার চেষ্টা করুন।"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"সারিতে আর কিছু নেই"</string>
 </resources>
diff --git a/car-media-common/res/values-bs/strings.xml b/car-media-common/res/values-bs/strings.xml
index 60ea824..4f1df52 100644
--- a/car-media-common/res/values-bs/strings.xml
+++ b/car-media-common/res/values-bs/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Omot albuma"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Bez naslova"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Nešto nije uredu. Pokušajte kasnije."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Taj zahtjev trenutno nije moguće izvršiti"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ova aplikacija ne može izvršiti taj zahtjev"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Prijavite se da koristite ovu aplikaciju"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Potreban je premijum pristup"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Previše je uređaja na kojima se sluša"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Sadržaj je blokiran"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Nije moguće preuzeti taj sadržaj ovdje"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Reproduciranje tog sadržaja je već u toku"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Ne možete više preskakati numere"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Dovršavanje nije uspjelo. Pokušajte ponovo."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ništa više nije postavljeno u red čekanja"</string>
 </resources>
diff --git a/car-media-common/res/values-ca/strings.xml b/car-media-common/res/values-ca/strings.xml
index c672d9b..7a44b13 100644
--- a/car-media-common/res/values-ca/strings.xml
+++ b/car-media-common/res/values-ca/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Imatge de l\'àlbum"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Sense títol"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"S\'ha produït un error. Prova-ho més tard."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Ara mateix aquesta acció no es pot dur a terme"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"L\'aplicació no pot dur a terme aquesta acció"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Inicia la sessió per utilitzar aquesta aplicació"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Es requereix accés Premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"S\'està escoltant contingut en massa dispositius"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Aquest contingut està bloquejat"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"El contingut no està disponible en aquesta regió"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Aquest contingut ja s\'està reproduint"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"No es poden saltar més cançons"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"No s\'ha pogut acabar. Torna-ho a provar."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"No hi ha res més a la cua"</string>
 </resources>
diff --git a/car-media-common/res/values-cs/strings.xml b/car-media-common/res/values-cs/strings.xml
index dfcffe0..0a45e6d 100644
--- a/car-media-common/res/values-cs/strings.xml
+++ b/car-media-common/res/values-cs/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Obal alba"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Bez názvu"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Někde se stala chyba. Zkuste to později."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Tuto akci teď nelze provést"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Tuto akci aplikace nedokáže provést"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Chcete-li aplikaci použít, přihlaste se"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Je vyžadován prémiový přístup"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Poslech je aktivován v příliš mnoha zařízeních"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Obsah je blokován"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Tento obsah tu nelze načíst"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Tento obsah se už přehrává"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Další skladby nelze přeskočit"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nelze dokončit. Zkuste to znovu."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ve frontě není nic dalšího"</string>
 </resources>
diff --git a/car-media-common/res/values-da/strings.xml b/car-media-common/res/values-da/strings.xml
index 1640516..a875184 100644
--- a/car-media-common/res/values-da/strings.xml
+++ b/car-media-common/res/values-da/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumgrafik"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Ingen titel"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Der er noget galt. Prøv senere."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Det er ikke muligt lige nu"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Det kan denne app ikke gøre"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Log ind for at bruge denne app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Dette kræver en Premium-konto"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Du lytter på for mange enheder"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Indholdet er blokeret"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Der er ikke adgang til indholdet her"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Indholdet afspilles allerede"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Du kan ikke springe flere numre over"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Handlingen kunne ikke afsluttes. Prøv igen."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Der er ikke mere i køen"</string>
 </resources>
diff --git a/car-media-common/res/values-de/strings.xml b/car-media-common/res/values-de/strings.xml
index 7bafae6..b5894cb 100644
--- a/car-media-common/res/values-de/strings.xml
+++ b/car-media-common/res/values-de/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumcover"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Kein Titel"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Ein Fehler ist aufgetreten. Versuch es später noch mal."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Das ist gerade nicht möglich"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Diese App kann das nicht"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Damit du diese App verwenden kannst, musst du dich zuerst anmelden"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premiumzugriff erforderlich"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Es wird auf zu vielen Geräten gleichzeitig gestreamt"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Der Inhalt ist gesperrt"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Der Inhalt kann hier nicht abgerufen werden"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Der Inhalt wird bereits wiedergegeben"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Du kannst keine weiteren Titel überspringen"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Die Aktion konnte nicht abgeschlossen werden. Versuch es noch einmal."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Es ist sonst nichts in der Warteschlange"</string>
 </resources>
diff --git a/car-media-common/res/values-el/strings.xml b/car-media-common/res/values-el/strings.xml
index 0b5de6d..9bc13cd 100644
--- a/car-media-common/res/values-el/strings.xml
+++ b/car-media-common/res/values-el/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Εξώφυλλο άλμπουμ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Χωρίς τίτλο"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε αργότερα."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Δεν είναι δυνατή η εκτέλεση του αιτήματος αυτήν τη στιγμή."</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Δεν είναι δυνατή η εκτέλεση του αιτήματος από αυτήν την εφαρμογή."</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Συνδεθείτε, για να χρησιμοποιήσετε αυτήν την εφαρμογή."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Απαιτείται premium πρόσβαση."</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Ακρόαση πάρα πολλών συσκευών"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Αυτό το περιεχόμενο είναι αποκλεισμένο."</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Δεν είναι δυνατή η λήψη αυτού του περιεχομένου εδώ."</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Γίνεται ήδη αναπαραγωγή αυτού του περιεχομένου."</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Δεν είναι δυνατή η παράβλεψη περισσότερων κομματιών."</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Δεν ήταν δυνατή η ολοκλήρωση. Δοκιμάστε ξανά."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Δεν υπάρχει κάτι άλλο στην ουρά."</string>
 </resources>
diff --git a/car-media-common/res/values-en-rAU/strings.xml b/car-media-common/res/values-en-rAU/strings.xml
index 98e3148..b9c3337 100644
--- a/car-media-common/res/values-en-rAU/strings.xml
+++ b/car-media-common/res/values-en-rAU/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Album Art"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"No title"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Something’s wrong. Try later."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Can’t do that at the moment"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"This app can’t do that"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Sign in to use this app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium access required"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Listening on too many devices"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"That content is blocked"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Can’t get that content here"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Already playing that content"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Can’t skip any more tracks"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Couldn’t finish. Try again."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nothing else is queued up"</string>
 </resources>
diff --git a/car-media-common/res/values-en-rCA/strings.xml b/car-media-common/res/values-en-rCA/strings.xml
index 98e3148..b9c3337 100644
--- a/car-media-common/res/values-en-rCA/strings.xml
+++ b/car-media-common/res/values-en-rCA/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Album Art"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"No title"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Something’s wrong. Try later."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Can’t do that at the moment"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"This app can’t do that"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Sign in to use this app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium access required"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Listening on too many devices"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"That content is blocked"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Can’t get that content here"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Already playing that content"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Can’t skip any more tracks"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Couldn’t finish. Try again."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nothing else is queued up"</string>
 </resources>
diff --git a/car-media-common/res/values-en-rGB/strings.xml b/car-media-common/res/values-en-rGB/strings.xml
index 98e3148..b9c3337 100644
--- a/car-media-common/res/values-en-rGB/strings.xml
+++ b/car-media-common/res/values-en-rGB/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Album Art"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"No title"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Something’s wrong. Try later."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Can’t do that at the moment"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"This app can’t do that"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Sign in to use this app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium access required"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Listening on too many devices"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"That content is blocked"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Can’t get that content here"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Already playing that content"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Can’t skip any more tracks"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Couldn’t finish. Try again."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nothing else is queued up"</string>
 </resources>
diff --git a/car-media-common/res/values-en-rIN/strings.xml b/car-media-common/res/values-en-rIN/strings.xml
index 98e3148..b9c3337 100644
--- a/car-media-common/res/values-en-rIN/strings.xml
+++ b/car-media-common/res/values-en-rIN/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Album Art"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"No title"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Something’s wrong. Try later."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Can’t do that at the moment"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"This app can’t do that"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Sign in to use this app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium access required"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Listening on too many devices"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"That content is blocked"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Can’t get that content here"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Already playing that content"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Can’t skip any more tracks"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Couldn’t finish. Try again."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nothing else is queued up"</string>
 </resources>
diff --git a/car-media-common/res/values-en-rXC/strings.xml b/car-media-common/res/values-en-rXC/strings.xml
index ecdf930..326c0ff 100644
--- a/car-media-common/res/values-en-rXC/strings.xml
+++ b/car-media-common/res/values-en-rXC/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎Album Art‎‏‎‎‏‎"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎No Title‎‏‎‎‏‎"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎Something’s wrong. Try later.‎‏‎‎‏‎"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎Can’t do that right now‎‏‎‎‏‎"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎‎‏‎This app can’t do that‎‏‎‎‏‎"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‎Sign in to use this app‎‏‎‎‏‎"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎Premium access required‎‏‎‎‏‎"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎Listening on too many devices‎‏‎‎‏‎"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎That content is blocked‎‏‎‎‏‎"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎Can’t get that content here‎‏‎‎‏‎"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‏‎Already playing that content‎‏‎‎‏‎"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎Can’t skip any more tracks‎‏‎‎‏‎"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎Couldn’t finish. Try again.‎‏‎‎‏‎"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎Nothing else is queued up‎‏‎‎‏‎"</string>
 </resources>
diff --git a/car-media-common/res/values-es-rUS/strings.xml b/car-media-common/res/values-es-rUS/strings.xml
index 18ba657..48d6213 100644
--- a/car-media-common/res/values-es-rUS/strings.xml
+++ b/car-media-common/res/values-es-rUS/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Imagen del álbum"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Sin título"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Se produjo un error. Vuelve a intentarlo más tarde."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"No se puede realizar esa acción en este momento"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Esta app no puede realizar esa acción"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Accede para usar esta app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Se requiere acceso Premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Se está escuchando contenido en demasiados dispositivos"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Ese contenido está bloqueado"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"No se puede acceder a ese contenido en esta región"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Ya se está reproduciendo ese contenido"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"No se pueden omitir más pistas"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"No se pudo completar la acción. Vuelve a intentarlo."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"No hay más contenido en la cola"</string>
 </resources>
diff --git a/car-media-common/res/values-es/strings.xml b/car-media-common/res/values-es/strings.xml
index 18ba657..f70760a 100644
--- a/car-media-common/res/values-es/strings.xml
+++ b/car-media-common/res/values-es/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Imagen del álbum"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Sin título"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Se ha producido un error. Inténtalo más tarde."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"No se puede hacer en estos momentos"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"No se puede hacer con esta aplicación"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Inicia sesión para utilizar esta aplicación"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Se necesita acceso premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Se está escuchando en demasiados dispositivos"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Ese contenido está bloqueado"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Aquí no se puede reproducir ese contenido"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Ya se está reproduciendo ese contenido"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"No se pueden saltar más pistas"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"No se ha podido finalizar. Inténtalo de nuevo."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"No hay nada más en la cola"</string>
 </resources>
diff --git a/car-media-common/res/values-et/strings.xml b/car-media-common/res/values-et/strings.xml
index 8ca4cf2..a5d7fc3 100644
--- a/car-media-common/res/values-et/strings.xml
+++ b/car-media-common/res/values-et/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumi kujundus"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Pealkiri puudub"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Midagi on valesti. Proovige hiljem."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Seda ei saa praegu teha"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"See rakendus ei saa seda teha"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Rakenduse kasutamiseks logige sisse"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Vaja on Premium-tasemel juurdepääsu"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Kuulatakse liiga paljudes seadmetes"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"See sisu on blokeeritud"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Seda sisu ei saa siin esitada"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Seda sisu juba esitatakse"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Rohkem lugusid ei saa vahele jätta"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Ei saanud lõpetada. Proovige uuesti."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Midagi muud pole järjekorras"</string>
 </resources>
diff --git a/car-media-common/res/values-eu/strings.xml b/car-media-common/res/values-eu/strings.xml
index 896aa2c..c989683 100644
--- a/car-media-common/res/values-eu/strings.xml
+++ b/car-media-common/res/values-eu/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumaren azala"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Izenik gabea"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Arazoren bat izan da. Saiatu geroago."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Ezin da egin halakorik une honetan"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Aplikazio honek ezin du egin halakorik"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Aplikazioa erabiltzeko, hasi saioa"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium-eko sarbidea behar da"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Gailu gehiegitatik jasotzen ari da soinua"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Eduki hori blokeatuta dago"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Ezin da eskuratu eduki hori lurralde honetan"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Dagoeneko ari da erreproduzitzen eduki hori"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Ezin da saltatu pista gehiagorik"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Ezin izan da amaitu ekintza. Saiatu berriro."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ez dago beste ezer ilaran"</string>
 </resources>
diff --git a/car-media-common/res/values-fa/strings.xml b/car-media-common/res/values-fa/strings.xml
index 24bac8e..b3168a0 100644
--- a/car-media-common/res/values-fa/strings.xml
+++ b/car-media-common/res/values-fa/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"عکس روی جلد آلبوم"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"بدون عنوان"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"مشکلی رخ داد. بعداً امتحان کنید."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"درحال‌حاضر انجام نمی‌شود"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"این برنامه نمی‌تواند این کار را انجام دهد"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"برای استفاده از این برنامه، به سیستم وارد شوید"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"دسترسی ممتاز لازم است"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"درحال گوش کردن به تعداد زیادی دستگاه"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"این محتوا مسدود شده است"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"نمی‌توان این محتوا را در اینجا دریافت کرد"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"این محتوا از قبل درحال پخش است"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"از هیچ آهنگ دیگری نمی‌توان رد شد"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"تکمیل نشد. دوباره امتحان کنید."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"هیچ مورد دیگری در صف پخش نیست"</string>
 </resources>
diff --git a/car-media-common/res/values-fi/strings.xml b/car-media-common/res/values-fi/strings.xml
index 0fcaaf5..c558794 100644
--- a/car-media-common/res/values-fi/strings.xml
+++ b/car-media-common/res/values-fi/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumin kansitaide"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Ei nimeä"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Jotain meni pieleen. Yritä myöhemmin."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Tämä ei juuri nyt onnistu"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Sovellus ei tue pyyntöä"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Kirjaudu sisään käyttääksesi tätä sovellusta"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Edellyttää premium-tilausta"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Kuuntelu käynnissä liian monella laitteella"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Tämä sisältö on estetty"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Sisältö ei ole saatavilla täällä"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Sisältöä toistetaan jo"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Enimmäismäärä kappaleita ohitettu"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Ei onnistunut. Yritä uudelleen."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ei muuta jonossa"</string>
 </resources>
diff --git a/car-media-common/res/values-fr-rCA/strings.xml b/car-media-common/res/values-fr-rCA/strings.xml
index 66e06e1..eb784b4 100644
--- a/car-media-common/res/values-fr-rCA/strings.xml
+++ b/car-media-common/res/values-fr-rCA/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Image de l\'album"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Aucun titre"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Une erreur s\'est produite. Réessayez plus tard."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Impossible d\'effectuer cette action pour le moment"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Cette application ne peut pas effectuer cette action"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Connectez-vous pour utiliser cette application"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Un accès payant est requis"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Écoute en cours sur trop d\'appareils"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Ce contenu est bloqué"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Impossible d\'obtenir ce contenu ici"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Ce contenu est déjà en cours de lecture"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Impossible de passer à d\'autres chansons"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Impossible de terminer l\'action. Réessayez."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Rien d\'autre n\'est dans la file d\'attente"</string>
 </resources>
diff --git a/car-media-common/res/values-fr/strings.xml b/car-media-common/res/values-fr/strings.xml
index dfbc082..8a86806 100644
--- a/car-media-common/res/values-fr/strings.xml
+++ b/car-media-common/res/values-fr/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Image de l\'album"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Sans titre"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Une erreur s\'est produite. Réessayez plus tard."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Impossible d\'effectuer cette opération pour le moment"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Cette application ne peut pas effectuer cette opération"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Connectez-vous pour utiliser cette application"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Accès Premium requis"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Écoute en cours sur trop d\'appareils"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Ce contenu est bloqué"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Impossible d\'accéder à ce contenu ici"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Ce contenu est déjà en cours de lecture"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Impossible de passer d\'autres titres"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Impossible de terminer l\'opération. Veuillez réessayer."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Aucun autre titre dans la file d\'attente"</string>
 </resources>
diff --git a/car-media-common/res/values-gl/strings.xml b/car-media-common/res/values-gl/strings.xml
index 6971016..a1a8fc5 100644
--- a/car-media-common/res/values-gl/strings.xml
+++ b/car-media-common/res/values-gl/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Portada de álbum"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Sen título"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Produciuse un problema. Téntao máis tarde."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Nestes momentos non se pode realizar a acción"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Esta aplicación non pode realizar a acción"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Inicia sesión para utilizar esta aplicación"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Requírese acceso premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Estase escoitando contido en demasiados dispositivos"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Ese contido está bloqueado"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Aquí non se pode acceder a ese contido"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Xa se está reproducindo ese contido"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Non se poden saltar máis pistas"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Non se puido completar a acción. Téntao de novo."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Non hai nada máis na cola"</string>
 </resources>
diff --git a/car-media-common/res/values-gu/strings.xml b/car-media-common/res/values-gu/strings.xml
index 569394f..b59fa2a 100644
--- a/car-media-common/res/values-gu/strings.xml
+++ b/car-media-common/res/values-gu/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"આલ્બમ આર્ટ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"કોઈ શીર્ષક નથી"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"કંઈક ખોટું થયું. થોડા સમય પછી પ્રયાસ કરો."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"તે અત્યારે કરી શકતા નથી"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"આ ઍપ તે કરી શકતી નથી"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"આ ઍપનો ઉપયોગ કરવા માટે સાઇન ઇન કરો"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"પ્રીમિયમ ઍક્સેસ જરૂરી છે"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"ઘણા બધા ડિવાઇસ પર સાંભળી રહ્યાં છે"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"તે કન્ટેન્ટ બ્લૉક કર્યું છે"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"તે કન્ટેન્ટ અહીં મેળવી શકાતું નથી"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"તે કન્ટેન્ટ પહેલાંથી ચલાવી રહ્યાં છે"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"કોઈ વધુ ટ્રૅક છોડી શકાતા નથી"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"સમાપ્ત કરી શક્યાં નથી. ફરી પ્રયાસ કરો."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"બીજું કંઈ કતારમાં નથી"</string>
 </resources>
diff --git a/car-media-common/res/values-hi/strings.xml b/car-media-common/res/values-hi/strings.xml
index f13088f..58fed76 100644
--- a/car-media-common/res/values-hi/strings.xml
+++ b/car-media-common/res/values-hi/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"एल्‍बम आर्ट"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"कोई शीर्षक नहीं"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"कोई गड़बड़ी हुई. बाद में कोशिश करें."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"अभी नहीं किया जा सकता"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"इस ऐप्लिकेशन पर यह काम नहीं किया जा सकता"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"इस ऐप्लिकेशन का इस्तेमाल करने के लिए साइन इन करें"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"इसके लिए Premium का ऐक्सेस ज़रूरी है"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"आप इसे बहुत सारे डिवाइस पर चला रहे/रही हैं"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"कॉन्टेंट पर रोक लगा दी गई है"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"यह कॉन्टेंट यहां नहीं चलाया जा सकता"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"यह कॉन्टेंट पहले से ही चल रहा है"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"इससे ज़्यादा गाने नहीं छोड़े जा सकते"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"कार्रवाई पूरी नहीं हो सकी. फिर से कोशिश करें."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"सूची में और कुछ नहीं है"</string>
 </resources>
diff --git a/car-media-common/res/values-hr/strings.xml b/car-media-common/res/values-hr/strings.xml
index 00e19d1..007109e 100644
--- a/car-media-common/res/values-hr/strings.xml
+++ b/car-media-common/res/values-hr/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Slika naslovnice albuma"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Bez naslova"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Nešto nije u redu. Pokušajte kasnije."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Trenutačno to ne možemo učiniti"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ova aplikacija nema tu mogućnost"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Prijavite se za upotrebu te aplikacije."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Potreban je pristup uz dodatnu naplatu"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Slušate na previše uređaja"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Taj je sadržaj blokiran"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Taj sadržaj nije dostupan ovdje"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Taj se sadržaj već reproducira"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Ne možete više preskakati pjesme"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Završavanje nije uspjelo. Pokušajte ponovo."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nema više ničeg u redu čekanja"</string>
 </resources>
diff --git a/car-media-common/res/values-hu/strings.xml b/car-media-common/res/values-hu/strings.xml
index 8631465..a56ebba 100644
--- a/car-media-common/res/values-hu/strings.xml
+++ b/car-media-common/res/values-hu/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Lemezborító"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Nincs cím"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Hiba történt. Próbálja újra később."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Jelenleg nem lehetséges"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ez az alkalmazás nem képes erre"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Az alkalmazás használatához jelentkezzen be"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Prémium hozzáférés szükséges"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Túl sok eszköz van használatban"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"A tartalom le van tiltva"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Nem lehet betölteni a tartalmat"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"A tartalom lejátszása már folyamatban van"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Nem lehet több számot átugrani"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nem sikerült befejezni. Próbálkozzon újra."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Semmi más nincs a sorban"</string>
 </resources>
diff --git a/car-media-common/res/values-hy/strings.xml b/car-media-common/res/values-hy/strings.xml
index 197a067..5fd71be 100644
--- a/car-media-common/res/values-hy/strings.xml
+++ b/car-media-common/res/values-hy/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Ալբոմի շապիկ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Անանուն"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Սխալ առաջացավ։ Փորձեք ավելի ուշ։"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Այս պահին հնարավոր չէ անել դա"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Հավելվածը չի աջակցում այդ գործողությունը"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Մուտք գործեք՝ հավելվածն օգտագործելու համար"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Անհրաժեշտ է պրեմիում հաշիվ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Չափից շատ սարքերում է բովանդակություն նվագարկվում"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Բովանդակությունն արգելափակված է"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Բովանդակությունն անհասանելի է այս տարածաշրջանում"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Բովանդակությունն արդեն նվագարկվում է"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Այլևս հնարավոր չէ կատարումներ բաց թողնել"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Չհաջողվեց ավարտել։ Նորից փորձեք։"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Հերթացանկը դատարկ է"</string>
 </resources>
diff --git a/car-media-common/res/values-in/strings.xml b/car-media-common/res/values-in/strings.xml
index e331c0a..3c287f2 100644
--- a/car-media-common/res/values-in/strings.xml
+++ b/car-media-common/res/values-in/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Sampul Album"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Tanpa Judul"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Terjadi masalah. Coba nanti."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Tidak dapat melakukannya saat ini"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Aplikasi ini tidak dapat melakukannya"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Login untuk menggunakan aplikasi ini"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Perlu akses premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Terlalu banyak perangkat digunakan untuk mendengarkan"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Konten tersebut diblokir"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Tidak dapat memuat konten tersebut di sini"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Sedang memutar konten tersebut"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Tidak dapat melewati lagu lagi"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Tidak dapat diselesaikan. Coba lagi."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Tidak ada antrean lagi"</string>
 </resources>
diff --git a/car-media-common/res/values-is/strings.xml b/car-media-common/res/values-is/strings.xml
index b26c4c6..34102e5 100644
--- a/car-media-common/res/values-is/strings.xml
+++ b/car-media-common/res/values-is/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Plötuumslag"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Enginn titill"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Eitthvað er ekki í lagi. Reyndu síðar."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Ekki er hægt að framkvæma þetta eins og er"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Forritið getur ekki framkvæmt þetta"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Skráðu þig inn til að nota þetta forrit"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium-aðgangur er nauðsynlegur"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Hlustað í of mörgum tækjum"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Þetta efni er á bannlista"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Efnið er ekki tiltækt hér"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Þegar að spila þetta efni"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Ekki er hægt að sleppa fleiri lögum"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Ekki tókst að ljúka aðgerð. Reyndu aftur."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ekkert annað er í röð"</string>
 </resources>
diff --git a/car-media-common/res/values-it/strings.xml b/car-media-common/res/values-it/strings.xml
index bab7f0a..d0ef413 100644
--- a/car-media-common/res/values-it/strings.xml
+++ b/car-media-common/res/values-it/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Copertina dell\'album"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Nessun titolo"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Si è verificato un problema. Prova più tardi."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Al momento non è possibile svolgere l\'operazione"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Questa app non supporta l\'azione richiesta"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Accedi per usare questa app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"È necessario l\'accesso Premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Ascolto attivo su troppi dispositivi"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Contenuti bloccati"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Qui non è possibile scaricare questi contenuti"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Contenuti già in riproduzione"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Impossibile saltare altre tracce"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Impossibile completare. Riprova."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nient\'altro in coda"</string>
 </resources>
diff --git a/car-media-common/res/values-iw/strings.xml b/car-media-common/res/values-iw/strings.xml
index 9e12f85..a0118e1 100644
--- a/car-media-common/res/values-iw/strings.xml
+++ b/car-media-common/res/values-iw/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"עטיפת אלבום"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"ללא שם"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"משהו השתבש. יש לנסות מאוחר יותר."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"לא ניתן לבצע את הפעולה הזו כרגע"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"אי אפשר לבצע פעולה זו באפליקציה הזו"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"יש להיכנס לחשבון כדי להשתמש באפליקציה הזו"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"נדרשת גישה ל-Premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"מתבצעת האזנה ביותר מדי מכשירים"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"התוכן הזה חסום"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"לא ניתן לקבל את התוכן הזה כאן"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"התוכן הזה כבר פועל"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"לא ניתן לדלג יותר על טראקים"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"לא ניתן היה לסיים. יש לנסות שוב."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"אין עוד שירים ברשימת השירים"</string>
 </resources>
diff --git a/car-media-common/res/values-ja/strings.xml b/car-media-common/res/values-ja/strings.xml
index 8d46866..b1a0da3 100644
--- a/car-media-common/res/values-ja/strings.xml
+++ b/car-media-common/res/values-ja/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"アルバムアート"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"タイトルなし"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"エラーが発生しました。しばらくしてからお試しください。"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"現在、利用できません"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"このアプリではサポートされていません"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"このアプリを使用するにはログインしてください"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"プレミアム アカウントが必要です"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"再生しているデバイスが多すぎます"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"このコンテンツはブロックされています"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"このコンテンツはこの地域では利用できません"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"このコンテンツはすでに再生中です"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"これ以上トラックをスキップできません"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"完了できません。もう一度お試しください。"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"キューが一杯で追加できません"</string>
 </resources>
diff --git a/car-media-common/res/values-ka/strings.xml b/car-media-common/res/values-ka/strings.xml
index 1e467fe..39b2549 100644
--- a/car-media-common/res/values-ka/strings.xml
+++ b/car-media-common/res/values-ka/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ალბომის გარეკანი"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"უსათაურო"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"წარმოიქმნა შეფერხება. ცადეთ მოგვიანებით."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ამჟამად ამის გაკეთება შეუძლებელია"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ეს აპი ამას ვერ გააკეთებს"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ამ აპით სარგებლობისთვის შედით სისტემაში"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"საჭიროა პრემიუმ ტიპის წვდომა"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"მოსმენა მიმდინარეობს მეტისმეტად ბევრ მოწყობილობაზე"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ეს კონტენტი დაბლოკილია"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ამ კონტენტს აქ ვერ მიიღებთ"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ეს კონტენტი უკვე იკვრება"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"მეტ ჩანაწერს ვერ გამოტოვებთ"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"დასრულება ვერ მოხერხდა. ცადეთ ხელახლა."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"რიგში აღარაფერია"</string>
 </resources>
diff --git a/car-media-common/res/values-kk/strings.xml b/car-media-common/res/values-kk/strings.xml
index ec84f1a..0225852 100644
--- a/car-media-common/res/values-kk/strings.xml
+++ b/car-media-common/res/values-kk/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Альбом мұқабасы"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Атауы жоқ"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Бірдеңе дұрыс емес. Кейінірек қайталап көріңіз."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Мұны дәл қазір істеу мүмкін емес."</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Бұл қолданба мұны істей алмайды."</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Бұл қолданбаны пайдалану үшін есептік жазбаға кіріңіз."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Премиум рұқсат қажет."</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Тым көп құрылғыларда тыңдалып жатыр."</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Бұл мазмұнға тыйым салынған."</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Мазмұнды алу мүмкін емес."</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Әлдеқашан ойнатылып жатыр."</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Басқа тректерді өткізіп жіберу мүмкін емес."</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Аяқталмады. Қайталап көріңіз."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Кезекке басқа ештеңе қойылмаған."</string>
 </resources>
diff --git a/car-media-common/res/values-km/strings.xml b/car-media-common/res/values-km/strings.xml
index a9320b1..95399ff 100644
--- a/car-media-common/res/values-km/strings.xml
+++ b/car-media-common/res/values-km/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"​ក្រប​អាល់ប៊ុម"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"គ្មាន​ចំណងជើងទេ"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"មានអ្វីមួយ​ខុស​ប្រក្រតី។ សូមព្យាយាម​នៅពេលក្រោយ។"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"មិនអាច​ធ្វើតាមសំណើនោះ​ឥឡូវនេះ​បានទេ"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"កម្មវិធីនេះ​មិនអាចធ្វើ​តាមសំណើនោះ​បានទេ"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ចូលគណនី ដើម្បីប្រើកម្មវិធីនេះ"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"តម្រូវឱ្យមាន​ការចូលប្រើ​លំដាប់ខ្ពស់"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"កំពុងស្ដាប់​នៅលើ​ឧបករណ៍​ច្រើនពេក"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ខ្លឹមសារនោះ​ត្រូវបានទប់ស្កាត់"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"មិនអាច​យក​ខ្លឹមសារនោះ​នៅទីនេះ​បានទេ"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"កំពុងចាក់​ខ្លឹមសារនោះ​ស្រាប់ហើយ"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"មិនអាច​រំលងចម្រៀង​បានទៀតទេ"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"មិនអាច​បញ្ចប់បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"មិនមានអ្វី​ផ្សេងទៀត​នៅក្នុង​ជួរទេ"</string>
 </resources>
diff --git a/car-media-common/res/values-kn/strings.xml b/car-media-common/res/values-kn/strings.xml
index 4a02cfd..e690790 100644
--- a/car-media-common/res/values-kn/strings.xml
+++ b/car-media-common/res/values-kn/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ಆಲ್ಬಮ್ ಕಲೆ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"ಯಾವುದೇ ಶೀರ್ಷಿಕೆಯಿಲ್ಲ"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ನಂತರ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ಸದ್ಯಕ್ಕೆ ಅದನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ಈ ಆ್ಯಪ್‌ನಿಂದ ಅದನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ಈ ಆ್ಯಪ್ ಬಳಸಲು ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ಪ್ರೀಮಿಯಂ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"ಹಲವಾರು ಸಾಧನಗಳಲ್ಲಿ ಆಲಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ವಿಷಯವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ಆ ವಿಷಯವನ್ನು ಇಲ್ಲಿ ಪಡೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ಈಗಾಗಲೇ ಆ ವಿಷಯವನ್ನು ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ಇನ್ನು ಮುಂದೆ ಟ್ರ್ಯಾಕ್‌ಗಳನ್ನು ಸ್ಕಿಪ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"ಪೂರ್ಣಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"ಸರದಿಯಲ್ಲಿ ಯಾವುದು ಬಾಕಿ ಉಳಿದಿಲ್ಲ"</string>
 </resources>
diff --git a/car-media-common/res/values-ko/strings.xml b/car-media-common/res/values-ko/strings.xml
index 568f6de..d50fd0f 100644
--- a/car-media-common/res/values-ko/strings.xml
+++ b/car-media-common/res/values-ko/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"앨범아트"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"제목 없음"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"문제가 발생했습니다. 나중에 다시 시도해 주세요."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"지금은 요청한 작업을 할 수 없습니다."</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"요청한 작업이 이 앱에서 지원되지 않습니다."</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"이 앱을 사용하려면 로그인하세요."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"프리미엄 액세스 권한이 필요합니다."</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"너무 많은 기기에서 스트리밍하고 있습니다."</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"차단된 콘텐츠입니다."</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"이 지역에서 재생할 수 없는 콘텐츠입니다."</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"요청한 콘텐츠가 이미 재생 중입니다."</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"트랙을 더 이상 건너뛸 수 없습니다."</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"완료할 수 없습니다. 다시 시도해 주세요."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"현재 재생목록이 비어있습니다."</string>
 </resources>
diff --git a/car-media-common/res/values-ky/strings.xml b/car-media-common/res/values-ky/strings.xml
index 5dd1ccc..8ca5ae0 100644
--- a/car-media-common/res/values-ky/strings.xml
+++ b/car-media-common/res/values-ky/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Альбом мукабасы"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Аталышы жок"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Бир жерден ката кетти. Бир аздан кийин кайталап көрүңүз."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Аны азыр аткаруу мүмкүн эмес"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Бул колдонмо аны аткара албайт"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Бул колдонмону пайдалануу үчүн аккаунтуңузга кириңиз"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Артыкчылыктуу кирүү мүмкүнчүлүгү талап кылынат"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Өтө көп түзмөк угулууда"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Ал мазмун бөгөттөлгөн"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Ал мазмунду алуу мүмкүн эмес"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Ал мазмун ойнотулууда"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Эми тректерди өткөрүп жиберүүгө болбойт"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Аягына чыккан жок. Кайталап көрүңүз."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Кезекте эч нерсе жок"</string>
 </resources>
diff --git a/car-media-common/res/values-lo/strings.xml b/car-media-common/res/values-lo/strings.xml
index aee4892..7e92949 100644
--- a/car-media-common/res/values-lo/strings.xml
+++ b/car-media-common/res/values-lo/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ໜ້າປົກອະລະບ້ຳ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"ບໍ່ມີຊື່"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"ມີບ່າງຢ່າງຜິດພາດ. ລອງໃໝ່ພາຍຫຼັງ."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ບໍ່ສາມາດເຮັດໄດ້ຕອນນີ້"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ແອັບນີ້ບໍ່ສາມາດເຮັດສິ່ງນັ້ນໄດ້"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ເຂົ້າສູ່ລະບົບເພື່ອໃຊ້ແອັບນີ້"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ຕ້ອງມີສິດເຂົ້າເຖິງລະດັບພຣີມຽມ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"ກຳລັງຟັງຢູ່ໃນຫຼາຍອຸປະກອນເກີນໄປ"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ເນື້ອຫານັ້ນຖືກບລັອກໄວ້"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ບໍ່ສາມາດຮັບເນື້ອຫານັ້ນຢູ່ບ່ອນນີ້"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ຫຼິ້ນເນື້ອຫານັ້ນແລ້ວ"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ຂ້າມເພງບໍ່ໄດ້ອີກແລ້ວ"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"ບໍ່ສາມາດສຳເລັດໄດ້. ລອງໃໝ່."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"ບໍ່ມີລາຍການອື່ນໃນຄິວ"</string>
 </resources>
diff --git a/car-media-common/res/values-lt/strings.xml b/car-media-common/res/values-lt/strings.xml
index b4f1926..be85d02 100644
--- a/car-media-common/res/values-lt/strings.xml
+++ b/car-media-common/res/values-lt/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumo viršelis"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Nėra pavadinimo"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Kažkas nepavyko. Bandykite vėliau."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Dabar negalima atlikti to veiksmo"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ši programa negali atlikti to veiksmo"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Prisijunkite, kad galėtumėte naudoti šią programą"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Būtina mokama prieiga"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Klausoma naudojant per daug įrenginių"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Tas turinys užblokuotas"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Negalima gauti to turinio čia"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Tas turinys jau leidžiamas"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Daugiau takelių praleisti nebegalima"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nepavyko užbaigti. Bandykite dar kartą."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Eilėje nieko nebėra"</string>
 </resources>
diff --git a/car-media-common/res/values-lv/strings.xml b/car-media-common/res/values-lv/strings.xml
index d4b6044..754a59d 100644
--- a/car-media-common/res/values-lv/strings.xml
+++ b/car-media-common/res/values-lv/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albuma noformējums"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Bez nosaukuma"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Radās problēma. Mēģiniet vēlāk."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Pašlaik nevar veikt šo darbību."</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Šo darbību nevar veikt šajā lietotnē."</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Pierakstieties, lai izmantotu šo lietotni."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Nepieciešama maksas piekļuve."</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Klausīšanās notiek pārāk daudz ierīcēs."</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Šis saturs ir bloķēts."</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Nevar šeit parādīt šo saturu."</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Šis saturs jau tiek atskaņots."</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Vairs nevar izlaist nevienu ierakstu."</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nevarēja pabeigt. Mēģiniet vēlreiz."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Rindā vairs nav nekā cita."</string>
 </resources>
diff --git a/car-media-common/res/values-mk/strings.xml b/car-media-common/res/values-mk/strings.xml
index d46c551..5e71b5a 100644
--- a/car-media-common/res/values-mk/strings.xml
+++ b/car-media-common/res/values-mk/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Корица на албум"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Без наслов"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Нешто не е во ред. Обидете се подоцна."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Не може да се направи тоа во моментов"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Апликацијава не може да го направи тоа"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Најавете се за да ја користите апликацијава"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Потребен е пристап со Premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Се слуша на премногу уреди"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Таа содржина е блокирана"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Не може да се добие таа содржина тука"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Веќе е пуштена таа содржина"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Не може да прескокне повеќе песни"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Не може да заврши. Обидете се повторно."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Веќе ништо не чека на ред"</string>
 </resources>
diff --git a/car-media-common/res/values-ml/strings.xml b/car-media-common/res/values-ml/strings.xml
index cd1743b..edcd0e1 100644
--- a/car-media-common/res/values-ml/strings.xml
+++ b/car-media-common/res/values-ml/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ആൽബം ആർട്ട്"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"പേരില്ല"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"എന്തോ കുഴപ്പമുണ്ട്. പിന്നീട് ശ്രമിക്കുക."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"അത് ഇപ്പോൾ ചെയ്യാനാകില്ല"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ഈ ആപ്പിന് അത് ചെയ്യാനാകില്ല"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ഈ ആപ്പ് ഉപയോഗിക്കാൻ സെെൻ ഇൻ ചെയ്യുക"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"പ്രീമിയം ആക്‌സസ് ആവശ്യമാണ്"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"നിരവധി ഉപകരണങ്ങളിൽ കേൾക്കുന്നു"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ആ ഉള്ളടക്കം ബ്ലോക്ക് ചെയ്‌തിരിക്കുന്നു"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ആ ഉള്ളടക്കം ഇവിടെ ലഭ്യമല്ല"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ആ ഉള്ളടക്കം നിലവിൽ പ്ലേ ചെയ്യുകയാണ്"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ഇനിയും ട്രാക്കുകൾ ഒഴിവാക്കാനാകില്ല"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"പൂർത്തിയാക്കാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"മറ്റൊന്നും ക്യൂവിലില്ല"</string>
 </resources>
diff --git a/car-media-common/res/values-mn/strings.xml b/car-media-common/res/values-mn/strings.xml
index 0cbec6a..b9cb37c 100644
--- a/car-media-common/res/values-mn/strings.xml
+++ b/car-media-common/res/values-mn/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Цомгийн зураг"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Гарчиг алга"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Алдаа гарлаа. Дараа оролдоно уу."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Яг одоо үүнийг хийх боломжгүй"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Энэ апп үүнийг хийх боломжгүй"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Энэ аппыг ашиглахын тулд нэвтэрнэ үү"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium хандалт шаардлагатай"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Хэт олон төхөөрөмж дээр сонсож байна"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Энэ контентыг блоклосон байна"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Энэ контентыг энд авах боломжгүй"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Энэ контентыг аль хэдийн тоглуулж байна"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Бичлэг дахин алгасах боломжгүй"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Дуусгаж чадсангүй. Дахин оролдоно уу."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Дараалалд өөр юу ч алга"</string>
 </resources>
diff --git a/car-media-common/res/values-mr/strings.xml b/car-media-common/res/values-mr/strings.xml
index 450fddd..27547ba 100644
--- a/car-media-common/res/values-mr/strings.xml
+++ b/car-media-common/res/values-mr/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"अल्बम कला"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"शीर्षक नाही"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"काहीतरी चूक झाली. नंतर प्रयत्न करा."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ते आता करू शकत नाही"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"हे ॲप ते करू शकत नाही"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"हे ॲप वापरण्यासाठी साइन इन करा"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"प्रीमियम ॲक्सेस आवश्यक आहे"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"खूप जास्‍त डिव्हाइसवर ऐकले जात आहे"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"तो आशय ब्लॉक केलेला आहे"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"तो आशय येथे मिळवू शकत नाही"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"तो आशय आधीपासून प्ले करत आहे"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"आणखी ट्रॅक वगळू शकत नाही"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"पूर्ण करता आले नाही. पुन्हा प्रयत्न करा."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"इतर काहीही क्यू केलेले नाही"</string>
 </resources>
diff --git a/car-media-common/res/values-ms/strings.xml b/car-media-common/res/values-ms/strings.xml
index f5660bf..3a16397 100644
--- a/car-media-common/res/values-ms/strings.xml
+++ b/car-media-common/res/values-ms/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Seni Album"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Tiada Tajuk"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Ada yang tidak kena. Cuba nanti."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Tidak dapat berbuat demikian sekarang"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Apl ini tidak dapat berbuat demikian"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Log masuk untuk menggunakan apl ini"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Akses premium diperlukan"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Mendengar pada terlalu banyak peranti"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Kandungan itu disekat"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Tidak boleh mendapatkan kandungan itu di sini"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Sudah pun memainkan kandungan itu"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Tidak boleh melangkau apa-apa lagu lagi"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Tidak dapat diselesaikan. Cuba lagi."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Tiada lagu lain dalam baris gilir"</string>
 </resources>
diff --git a/car-media-common/res/values-my/strings.xml b/car-media-common/res/values-my/strings.xml
index e717f45..f4723b0 100644
--- a/car-media-common/res/values-my/strings.xml
+++ b/car-media-common/res/values-my/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"အယ်လ်ဘမ်ပုံ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"ခေါင်းစဉ် မရှိပါ"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"တစ်ခုခု မှားနေသည်။ နောက်မှ စမ်းကြည့်ပါ။"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"၎င်းကို ယခု မပြုလုပ်နိုင်ပါ"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ဤအက်ပ်က ၎င်းကို မပြုလုပ်နိုင်ပါ"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ဤအက်ပ်အသုံးပြုရန် လက်မှတ်ထိုးဝင်ပါ"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ပရီမီယံ အသုံးပြုခွင့် လိုအပ်သည်"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"စက်ပစ္စည်းအများအပြားတွင် နားထောင်နေသည်"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ထိုအကြောင်းအရာကို ပိတ်ထားသည်"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ထိုအကြောင်းအရာကို ဤနေရာတွင် မရရှိနိုင်ပါ"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ထိုအကြောင်းအရာကို ဖွင့်နေပြီဖြစ်သည်"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"နောက်ထပ်သီချင်းပုဒ်များ ကျော်၍မရတော့ပါ"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"အပြီးသတ်၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"အခြားစီထားသည်များ မရှိပါ"</string>
 </resources>
diff --git a/car-media-common/res/values-nb/strings.xml b/car-media-common/res/values-nb/strings.xml
index b01654e..878beb2 100644
--- a/car-media-common/res/values-nb/strings.xml
+++ b/car-media-common/res/values-nb/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumgrafikk"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Ingen tittel"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Noe gikk galt. Prøv senere."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Kan ikke gjøre det akkurat nå"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Denne appen kan ikke gjøre det"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Logg på for å bruke denne appen"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premiumtilgang kreves"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Du lytter på for mange enheter"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Innholdet er blokkert"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Innholdet er ikke tilgjengelig her"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Du spiller allerede av innholdet"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Kan ikke hoppe over flere spor"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Kunne ikke fullføre. Prøv på nytt."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ingenting annet står i køen"</string>
 </resources>
diff --git a/car-media-common/res/values-ne/strings.xml b/car-media-common/res/values-ne/strings.xml
index 8e2bf79..5eed37d 100644
--- a/car-media-common/res/values-ne/strings.xml
+++ b/car-media-common/res/values-ne/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"एल्बम आर्ट"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"शीर्षक छैन"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"केही चिज गडबड छ। पछि प्रयास गर्नुहोस्।"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"त्यो कार्य अहिले नै गर्न सकिँदैन"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"यस अनुप्रयोगले उक्त कार्य गर्न सक्दैन"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"यो एप प्रयोग गर्न साइन इन गर्नुहोस्"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"यसका लागि प्रिमियम खातामाथिको पहुँच आवश्यक हुन्छ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"अत्यधिक यन्त्रहरूबाट सुनिँदै छ"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"उक्त सामग्री ब्लक गरिएको छ"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"उक्त सामग्री यहाँ प्राप्त गर्न सकिँदैन"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"उक्त सामग्री प्ले भइरहेको छ"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"योभन्दा धेरै गीतहरू स्किप गर्न सकिँदैन"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"कार्य पूरा गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"सूचीमा अरू केही पनि छैन"</string>
 </resources>
diff --git a/car-media-common/res/values-nl/strings.xml b/car-media-common/res/values-nl/strings.xml
index 8259676..e8acdbc 100644
--- a/car-media-common/res/values-nl/strings.xml
+++ b/car-media-common/res/values-nl/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albumhoes"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Geen titel"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Er is iets misgegaan. Probeer het later opnieuw."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Kan dat nu niet doen"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Deze app kan dat niet doen"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Log in om deze app te gebruiken"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium toegang vereist"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Er wordt op te veel apparaten geluisterd"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Die content is geblokkeerd"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Kan die content hier niet krijgen"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Die content wordt al afgespeeld"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Kan geen nummers meer overslaan"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Kan niet voltooien. Probeer het opnieuw."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Er staat niets anders in de wachtrij"</string>
 </resources>
diff --git a/car-media-common/res/values-or/strings.xml b/car-media-common/res/values-or/strings.xml
index a714293..e503cd8 100644
--- a/car-media-common/res/values-or/strings.xml
+++ b/car-media-common/res/values-or/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ଆଲବମ୍ ଆର୍ଟ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"କୌଣସି ଟାଇଟେଲ୍ ନାହିଁ"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"କିଛି ସମସ୍ୟା ଅଛି। ପରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ବର୍ତ୍ତମାନ ତାହା କରାଯାଇପାରିବ ନାହିଁ"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ଏହି ଆପ୍ ତାହା କରିପାରିବ ନାହିଁ"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ଏହି ଆପ୍ ବ୍ୟବହାର କରିବାକୁ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ପ୍ରିମିୟମ୍ ଆକ୍ସେସ୍ ଆବଶ୍ୟକ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"ଅନେକ ଡିଭାଇସରେ ଶୁଣାଯାଉଛି"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ସେହି ବିଷୟବସ୍ତୁକୁ ବ୍ଲକ୍ କରାଯାଇଛି"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ଏଠାରେ ସେହି ବିଷୟବସ୍ତୁ ପାଇପାରିବେ ନାହିଁ"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ପୂର୍ବରୁ ସେହି ବିଷୟବସ୍ତୁ ଚଲାଯାଉଛି"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ଆଉ ଅଧିକ ଟ୍ରାକକୁ ବାଦ୍ ଦିଆଯାଇପାରିବ ନାହିଁ"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"ସମାପ୍ତ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"ଧାଡ଼ିରେ ଆଉ କିଛି ନାହିଁ"</string>
 </resources>
diff --git a/car-media-common/res/values-pa/strings.xml b/car-media-common/res/values-pa/strings.xml
index e3a607b..5d02f20 100644
--- a/car-media-common/res/values-pa/strings.xml
+++ b/car-media-common/res/values-pa/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ਐਲਬਮ ਕਲਾ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"ਕੋਈ ਗੜਬੜ ਹੈ। ਬਾਅਦ ਵਿੱਚ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ਫਿਲਹਾਲ ਇਹ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ਇਹ ਐਪ ਇਹ ਨਹੀਂ ਕਰ ਸਕਦੀ"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ਇਸ ਐਪ ਨੂੰ ਵਰਤਣ ਲਈ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ਪ੍ਰੀਮੀਅਮ ਪਹੁੰਚ ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਡੀਵਾਈਸਾਂ \'ਤੇ ਸੁਣਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ਇਸ ਸਮੱਗਰੀ ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ਇੱਥੇ ਇਹ ਸਮੱਗਰੀ ਨਹੀਂ ਮਿਲ ਸਕਦੀ"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ਇਹ ਸਮੱਗਰੀ ਪਹਿਲਾਂ ਹੀ ਚੱਲ ਰਹੀ ਹੈ"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ਕਿਸੇ ਹੋਰ ਟਰੈਕ ਨੂੰ ਛੱਡਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"ਪੂਰਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"ਹੋਰ ਕੁਝ ਵੀ ਕਤਾਰਬੱਧ ਨਹੀਂ ਹੈ"</string>
 </resources>
diff --git a/car-media-common/res/values-pl/strings.xml b/car-media-common/res/values-pl/strings.xml
index fd00ae5..1bdcf9a 100644
--- a/car-media-common/res/values-pl/strings.xml
+++ b/car-media-common/res/values-pl/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Okładka albumu"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Bez tytułu"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Coś poszło nie tak. Spróbuj później."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Teraz nie można tego zrobić"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ta aplikacja nie ma takiej funkcji"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Zaloguj się, by używać tej aplikacji"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Wymagany jest dostęp na poziomie premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Słuchasz na zbyt wielu urządzeniach"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Te materiały są zablokowane"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Te materiały są niedostępne w tym regionie"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Te materiały są już odtwarzane"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Nie można pominąć większej liczby utworów"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nie udało się dokończyć. Spróbuj ponownie."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nie ma już nic w kolejce"</string>
 </resources>
diff --git a/car-media-common/res/values-port/dimens.xml b/car-media-common/res/values-port/dimens.xml
deleted file mode 100644
index 721ed93..0000000
--- a/car-media-common/res/values-port/dimens.xml
+++ /dev/null
@@ -1,20 +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.
--->
-<resources>
-    <!-- App bar -->
-    <dimen name="appbar_second_row_height">@*android:dimen/car_app_bar_height</dimen>
-</resources>
diff --git a/car-media-common/res/values-pt-rPT/strings.xml b/car-media-common/res/values-pt-rPT/strings.xml
index 2ae65bf..ab6e0ff 100644
--- a/car-media-common/res/values-pt-rPT/strings.xml
+++ b/car-media-common/res/values-pt-rPT/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Imagem do álbum"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Sem título"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Ocorreu um problema. Tente mais tarde."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Não é possível responder a esse pedido neste momento."</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Esta app não consegue responder a esse pedido."</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Inicie sessão para utilizar esta app."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Acesso premium necessário."</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"A ouvir em demasiados dispositivos."</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Esse conteúdo está bloqueado."</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Não é possível obter esse conteúdo aqui."</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Esse conteúdo já está em reprodução."</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Não é possível ignorar mais faixas."</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Não foi possível terminar. Tente novamente."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Não existem mais elementos em fila."</string>
 </resources>
diff --git a/car-media-common/res/values-pt/strings.xml b/car-media-common/res/values-pt/strings.xml
index 1b39a7b..2a295f8 100644
--- a/car-media-common/res/values-pt/strings.xml
+++ b/car-media-common/res/values-pt/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Arte do álbum"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Sem título"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Algo deu errado. Tente mais tarde."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Não é possível fazer isso no momento"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Não é possível fazer isso com este app"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Faça login para usar este app"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"É necessário ter acesso Premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Ouvindo em muitos dispositivos"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Esse conteúdo está bloqueado"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Não é possível usar esse conteúdo aqui"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Esse conteúdo já está tocando"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Não é possível pular mais faixas"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Não foi possível concluir esta ação. Tente novamente."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Não há mais nada na fila"</string>
 </resources>
diff --git a/car-media-common/res/values-ro/strings.xml b/car-media-common/res/values-ro/strings.xml
index 38c53cc..3bcb08d 100644
--- a/car-media-common/res/values-ro/strings.xml
+++ b/car-media-common/res/values-ro/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Grafica albumului"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Fără titlu"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"A apărut o problemă. Încercați mai târziu."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Acțiunea nu poate fi realizată momentan"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Aplicația nu poate realiza această acțiune"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Conectați-vă pentru a folosi aplicația"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Este necesar accesul premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Se ascultă pe prea multe dispozitive"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Conținutul este blocat"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Conținutul nu poate fi descărcat aici"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Conținutul se redă deja"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Nu mai pot fi omise melodii"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nu s-a putut finaliza. Încercați din nou."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Nu mai există elemente în coadă"</string>
 </resources>
diff --git a/car-media-common/res/values-ru/strings.xml b/car-media-common/res/values-ru/strings.xml
index 990650f..6f4a6ba 100644
--- a/car-media-common/res/values-ru/strings.xml
+++ b/car-media-common/res/values-ru/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Обложка альбома"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Без названия"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Ошибка. Повторите попытку позже."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Сейчас это действие недоступно."</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Действие недоступно в этом приложении."</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Чтобы использовать это приложение, войдите в аккаунт."</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Требуется премиум-доступ."</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Слишком много устройств, на которых воспроизводится аудио."</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Контент заблокирован."</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Контент недоступен в вашем регионе."</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Этот контент уже воспроизводится."</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Пропускать треки больше нельзя."</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Произошла ошибка. Повторите попытку."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"В очереди воспроизведения нет других файлов."</string>
 </resources>
diff --git a/car-media-common/res/values-si/strings.xml b/car-media-common/res/values-si/strings.xml
index 7da552b..f748730 100644
--- a/car-media-common/res/values-si/strings.xml
+++ b/car-media-common/res/values-si/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ඇල්බම කලාව"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"මාතෘකාවක් නැත"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"යම් දෙයක් වැරදියි. පසුව උත්සාහ කරන්න."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"මේ දැන් එය කළ නොහැක"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"මෙම යෙදුමට එය කළ නොහැක"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"මෙම යෙදුම භාවිත කිරීමට පුරන්න"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"පාරිතෝෂික ප්‍රවේශය අවශ්‍යයි"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"ඕනෑවට වඩා උපාංග මත සවන් දීම"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"එම අන්තර්ගතය අවහිර කර ඇත"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"එම අන්තර්ගතය මෙතැනින් ලබා ගත නොහැක"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"දැනටමත් එම අන්තර්ගතය වාදනය කරයි"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"තවත් ගීත මඟ හැරිය නොහැක"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"අවසන් කිරීමට නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"වෙන කිසිවක් පෝලිමේ නැත"</string>
 </resources>
diff --git a/car-media-common/res/values-sk/strings.xml b/car-media-common/res/values-sk/strings.xml
index d94bac4..7a12c96 100644
--- a/car-media-common/res/values-sk/strings.xml
+++ b/car-media-common/res/values-sk/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Obrázok albumu"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Bez názvu"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Vyskytol sa problém. Skúste to znova."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Teraz to nie je možné"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Táto aplikácia to nedokáže"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Ak chcete použiť túto aplikáciu, prihláste sa"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Vyžaduje sa prémiový prístup"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Počúva sa na príliš veľa zariadeniach"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Daný obsah je blokovaný"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Daný obsah tu nie je k dispozícii"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Tento obsah sa už prehráva"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Nie je možné preskočiť žiadne ďalšie skladby"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Akciu sa nepodarilo dokončiť. Skúste to znova."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Poradie je prázdne"</string>
 </resources>
diff --git a/car-media-common/res/values-sl/strings.xml b/car-media-common/res/values-sl/strings.xml
index 683507c..aec70f5 100644
--- a/car-media-common/res/values-sl/strings.xml
+++ b/car-media-common/res/values-sl/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Slika albuma"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Brez naslova"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Prišlo je do težave. Poskusite pozneje."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Trenutno to ni izvedljivo"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ta aplikacija ne more izvesti tega"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Prijavite se, če želite uporabljati to aplikacijo"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Potrebujete plačljiv dostop"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Poslušanje v preveč napravah"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Ta vsebina je blokirana"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Te vsebine tukaj ni mogoče pridobiti"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Ta vsebina se že predvaja"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Dosegli ste omejitev preskakovanja skladb"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Ni bilo mogoče dokončati. Poskusite znova."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Čakalna vrsta je prazna"</string>
 </resources>
diff --git a/car-media-common/res/values-sq/strings.xml b/car-media-common/res/values-sq/strings.xml
index 354b5ed..d4d02e1 100644
--- a/car-media-common/res/values-sq/strings.xml
+++ b/car-media-common/res/values-sq/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Kopertina e albumit"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Pa titull"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Ndodhi një gabim. Provo më vonë."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Këtë nuk mund ta bësh në këtë moment"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ky aplikacion nuk mund ta bëjë këtë"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Identifikohu për të përdorur këtë aplikacion"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Kërkohet qasje Premium"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Po dëgjon në shumë pajisje"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Kjo përmbajtje është bllokuar"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Ajo përmbajtje nuk mund të merret këtu"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Ajo përmbajtje po luhet tashmë"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Nuk mund të kapërcejë këngë të tjera"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Nuk mundi të përfundojë. Provo sërish."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Asgjë tjetër nuk është në radhë"</string>
 </resources>
diff --git a/car-media-common/res/values-sr/strings.xml b/car-media-common/res/values-sr/strings.xml
index e6173ba..69c898d 100644
--- a/car-media-common/res/values-sr/strings.xml
+++ b/car-media-common/res/values-sr/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Омот албума"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Без наслова"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Дошло је до грешке. Пробајте касније."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Тренутно не може то да уради"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ова апликација не може то да уради"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Пријавите се да бисте користили ову апликацију"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Потребан је премијум приступ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Слушате на превише уређаја"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Тај садржај је блокиран"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Не можете да добијете тај садржај овде"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Тај садржај се већ репродукује"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Не можете више да прескачете песме"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Нисмо успели да довршимо радњу. Пробајте опет."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ништа друго није стављено у редослед"</string>
 </resources>
diff --git a/car-media-common/res/values-sv/strings.xml b/car-media-common/res/values-sv/strings.xml
index ce52ecf..05a0d28 100644
--- a/car-media-common/res/values-sv/strings.xml
+++ b/car-media-common/res/values-sv/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Skivomslag"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Ingen titel"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Något är fel. Försök igen senare."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Det går inte just nu"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Det går inte med den här appen"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Logga in om du vill använda appen"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium-konto krävs"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"För många enheter streamas"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Det innehållet har blockerats"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Det innehållet är inte tillgängligt här"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Det innehållet spelas redan"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Det går inte att hoppa över fler låtar"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Det gick inte att slutföra. Försök igen."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Inget annat har lagts i uppspelningskön"</string>
 </resources>
diff --git a/car-media-common/res/values-sw/strings.xml b/car-media-common/res/values-sw/strings.xml
index 282555c..30937ac 100644
--- a/car-media-common/res/values-sw/strings.xml
+++ b/car-media-common/res/values-sw/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Sanaa ya Albamu"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Hakuna Jina"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Hitilafu fulani imetokea. Jaribu baadaye."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Imeshindwa kutekeleza ombi kwa sasa"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Programu hii imeshindwa kutekeleza ombi lako"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Ingia katika akaunti ili utumie programu hii"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Unahitaji kutumia akaunti ya kulipia"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Unasikiliza kwenye vifaa vingi mno"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Maudhui hayo yamezuiwa"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Imeshindwa kupata maudhui haya hapa"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Tayari inacheza wimbo huo"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Imeshindwa kuruka nyimbo zaidi"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Imeshindwa kumaliza. Jaribu tena."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Hakuna wimbo mwingine kwenye foleni"</string>
 </resources>
diff --git a/car-media-common/res/values-ta/strings.xml b/car-media-common/res/values-ta/strings.xml
index dd522b8..6fc14ba 100644
--- a/car-media-common/res/values-ta/strings.xml
+++ b/car-media-common/res/values-ta/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ஆல்பம் ஆர்ட்"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"தலைப்பு இல்லை"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"ஏதோ தவறாகிவிட்டது. பிறகு முயலவும்."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"தற்சமயம் இதைச் செய்ய இயலாது"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"இந்த ஆப்ஸால் அதைச் செய்ய இயலாது"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"இந்த ஆப்ஸை உபயோகிக்க உள்நுழைய வேண்டும்"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium அணுகல் தேவை"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"நிறைய சாதனங்களைக் கவனிக்கிறது"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"அந்த உள்ளடக்கம் தடுக்கப்பட்டுள்ளது"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"அந்த உள்ளடக்கத்தை இங்கே பெற முடியவில்லை"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"அந்த உள்ளடக்கம் ஏற்கெனவே பிளே செய்யப்பட்டுக் கொண்டிருக்கிறது"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"இதற்கு மேல் டிராக்குகளைத் தவிர்க்க முடியாது"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"நிறைவடையவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"வேறு எதுவும் வரிசையில் இல்லை"</string>
 </resources>
diff --git a/car-media-common/res/values-te/strings.xml b/car-media-common/res/values-te/strings.xml
index 62a7464..f3dec11 100644
--- a/car-media-common/res/values-te/strings.xml
+++ b/car-media-common/res/values-te/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ఆల్బమ్ ఆర్ట్"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"శీర్షిక లేదు"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"ఏదో తప్పు జరిగింది. తర్వాత ట్రై చేయండి."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"దానిని ఇప్పుడు చేయడం సాధ్యపడదు"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"ఈ యాప్ దానిని చేయలేదు"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ఈ యాప్‌ను ఉపయోగించడానికి సైన్ ఇన్ చేయండి"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ప్రీమియం యాక్సెస్ అవసరం"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"అనేక పరికరాలలో వింటున్నారు"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"ఆ కంటెంట్ బ్లాక్ చేయబడింది"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"ఆ కంటెంట్‌ను ఇక్కడ పొందడం సాధ్యపడదు"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"ఇప్పటికే ఆ కంటెంట్ ప్లే అవుతోంది"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ఇంక ఏ ట్రాక్‌లనూ స్కిప్ చేయడం సాధ్యపడదు"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"పూర్తి చేయడం సాధ్యపడలేదు. మళ్లీ ట్రై చేయండి."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"క్రమ వరుసలో ఏమీ లేదు"</string>
 </resources>
diff --git a/car-media-common/res/values-th/strings.xml b/car-media-common/res/values-th/strings.xml
index f642719..3e3aa59 100644
--- a/car-media-common/res/values-th/strings.xml
+++ b/car-media-common/res/values-th/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"ปกอัลบั้ม"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"ไม่มีชื่อ"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"มีข้อผิดพลาดเกิดขึ้น ลองอีกครั้งในภายหลัง"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ดำเนินการดังกล่าวไม่ได้ในขณะนี้"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"แอปนี้ดำเนินการดังกล่าวไม่ได้"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"ลงชื่อเข้าใช้เพื่อใช้แอปนี้"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"ต้องมีสิทธิ์เข้าถึงระดับพรีเมียม"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"กำลังเปิดฟังจากหลายอุปกรณ์เกินไป"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"เนื้อหาดังกล่าวถูกบล็อก"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"เปิดเนื้อหาดังกล่าวไม่ได้ที่นี่"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"กำลังเล่นเนื้อหาดังกล่าวอยู่แล้ว"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"ข้ามแทร็กอื่นอีกไม่ได้แล้ว"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"ดำเนินการไม่สำเร็จ ลองใหม่"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"ไม่มีรายการอื่นในคิว"</string>
 </resources>
diff --git a/car-media-common/res/values-tl/strings.xml b/car-media-common/res/values-tl/strings.xml
index a2da896..39bc081 100644
--- a/car-media-common/res/values-tl/strings.xml
+++ b/car-media-common/res/values-tl/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Album Art"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Walang Pamagat"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"May problema. Subukan sa ibang pagkakataon."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Hindi iyon magagawa ngayon"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Hindi iyon magagawa ng app na ito"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Mag-sign in para gamitin ang app na ito"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Kailangan ng premium na access"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Nakikinig sa masyadong maraming device"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Naka-block ang content na iyon"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Hindi makukuha ang content na iyon dito"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Pine-play na ang content na iyon"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Hindi na makakalaktaw pa ng track"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Hindi matapos. Subukan ulit."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Wala nang naka-queue"</string>
 </resources>
diff --git a/car-media-common/res/values-tr/strings.xml b/car-media-common/res/values-tr/strings.xml
index 6f717ac..7fc645e 100644
--- a/car-media-common/res/values-tr/strings.xml
+++ b/car-media-common/res/values-tr/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albüm Kapağı"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Başlıksız"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Bir şeyler ters gitti. Daha sonra tekrar deneyin."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"İşlem şu anda gerçekleştirilemiyor"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Uygulama bu işlemi gerçekleştiremiyor"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Bu uygulamayı kullanmak için oturum açın"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Premium erişim gerekli"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Çok fazla cihazda dinleme yapılıyor"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Bu içerik engellendi"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"İçeriğe buradan erişilemiyor"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Bu içerik zaten oynatılıyor"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Daha fazla parça atlanamıyor"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Tamamlanamadı. Tekrar deneyin."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Sıraya eklenmiş başka bir şey yok"</string>
 </resources>
diff --git a/car-media-common/res/values-uk/strings.xml b/car-media-common/res/values-uk/strings.xml
index 0661490..e377c98 100644
--- a/car-media-common/res/values-uk/strings.xml
+++ b/car-media-common/res/values-uk/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Обкладинка альбому"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Без назви"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Сталася помилка. Повторіть спробу пізніше."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Наразі ця дія недоступна"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Додаток не підтримує цю дію"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Увійдіть, щоб використовувати цей додаток"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Потрібен преміум-доступ"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Забагато пристроїв, на яких відтворюється контент"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Цей контент заблоковано"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Цей контент недоступний у вашому регіоні"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Цей контент уже відтворюється"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Більше не можна пропускати композиції"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Не вдалося закінчити. Повторіть спробу."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Черга порожня"</string>
 </resources>
diff --git a/car-media-common/res/values-ur/strings.xml b/car-media-common/res/values-ur/strings.xml
index ccf505c..19dfce7 100644
--- a/car-media-common/res/values-ur/strings.xml
+++ b/car-media-common/res/values-ur/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"البم آرٹ"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"کوئی عنوان نہیں ہے"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"کچھ غلط ہو گیا۔ بعد میں کوشش کریں۔"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"ابھی وہ ایسا نہیں کر سکتا"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"یہ ایپ ایسا نہیں کر سکتی"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"اس ایپ کا استعمال کرنے کے لیے سائن ان کریں"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"پریمیم رسائی درکار ہے"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"بہت سے آلات پر سنا جا رہا ہے"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"وہ مواد مسدود ہے"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"یہاں وہ مواد حاصل نہیں کر سکتے"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"وہ مواد پہلے سے ہی چلایا جا رہا ہے"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"مزید کسی اور ٹریکس کو نظر انداز نہیں کر سکتے"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"پورا نہیں ہو سکا۔ پھر آزمائيں۔"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"مزید کچھ اور کی قطار نہیں ہے"</string>
 </resources>
diff --git a/car-media-common/res/values-uz/strings.xml b/car-media-common/res/values-uz/strings.xml
index f3e8826..b2bfd1e 100644
--- a/car-media-common/res/values-uz/strings.xml
+++ b/car-media-common/res/values-uz/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Albom muqovasi"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Nomsiz"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Nimadir xato ketdi Keyinroq qayta urining."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Buni hozir amalga oshira olmaydi"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Bu ilova bu amalni bajara olmaydi"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Bu ilovadan foydalanish uchun hisobingizga kiring"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Ishonchli ruxsat kerak"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Koʻplab qurilmalar tinglanmoqda"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Bu kontent bloklangan"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Bu kontentni bu yerga olish imkonsiz"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Bu kontent allaqachon ijro etilmoqda"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Boshqa treklarni qoldirib ketish imkonsiz"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Tugallanmadi. Qayta urining."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Ijro navbatida boshqa fayllar mavjud emas"</string>
 </resources>
diff --git a/car-media-common/res/values-vi/strings.xml b/car-media-common/res/values-vi/strings.xml
index 2a99840..f75fe5a 100644
--- a/car-media-common/res/values-vi/strings.xml
+++ b/car-media-common/res/values-vi/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Ảnh bìa album"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Không có tiêu đề"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Đã xảy ra lỗi. Hãy thử lại sau."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Không thể thực hiện yêu cầu đó ngay bây giờ"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Ứng dụng này không thể thực hiện yêu cầu đó"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Hãy đăng nhập để dùng ứng dụng này"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Yêu cầu quyền truy cập đặc biệt"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Đang nghe trên quá nhiều thiết bị"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Nội dung đó đã bị chặn"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Không thể xem nội dung đó tại đây"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Đang phát nội dung đó rồi"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Không thể bỏ qua bản nhạc nào nữa"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Không thể hoàn tất. Hãy thử lại."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Không có nội dung nào khác trong hàng đợi"</string>
 </resources>
diff --git a/car-media-common/res/values-zh-rCN/strings.xml b/car-media-common/res/values-zh-rCN/strings.xml
index b3ddef1..9688f0e 100644
--- a/car-media-common/res/values-zh-rCN/strings.xml
+++ b/car-media-common/res/values-zh-rCN/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"专辑封面"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"无标题"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"出了点问题。请稍后重试。"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"目前无法执行该操作"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"此应用无法执行该操作"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"登录才能使用此应用"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"需要有付费帐号才能访问"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"同时使用太多设备聆听"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"该内容已遭到屏蔽"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"所在地区不提供这项内容"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"系统已在播放这项内容"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"无法再跳过更多曲目"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"无法完成操作。请重试。"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"队列中没有任何其他内容"</string>
 </resources>
diff --git a/car-media-common/res/values-zh-rHK/strings.xml b/car-media-common/res/values-zh-rHK/strings.xml
index 6ce371a..1e84ca7 100644
--- a/car-media-common/res/values-zh-rHK/strings.xml
+++ b/car-media-common/res/values-zh-rHK/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"專輯封面"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"無標題"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"發生錯誤,請稍後再試。"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"目前無法執行此操作"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"應用程式不支援此操作"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"登入帳戶才能使用此應用程式"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"必須付費才能存取"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"同時使用太多裝置聆聽音樂"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"內容已被封鎖"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"所在地區不提供該內容"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"系統已開始播放該內容"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"無法再略過曲目"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"無法完成此操作,請再試一次。"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"序列上沒有其他項目"</string>
 </resources>
diff --git a/car-media-common/res/values-zh-rTW/strings.xml b/car-media-common/res/values-zh-rTW/strings.xml
index 6ce371a..1b50b13 100644
--- a/car-media-common/res/values-zh-rTW/strings.xml
+++ b/car-media-common/res/values-zh-rTW/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"專輯封面"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"無標題"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"發生錯誤,請稍後再試。"</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"目前無法執行這項操作"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"應用程式不支援這項操作"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"必須登入帳戶,才能使用這個應用程式"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"必須付費才能存取"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"同時使用太多裝置聆聽音樂"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"內容已遭到封鎖"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"所在地區不提供該內容"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"系統已開始播放該內容"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"無法再略過曲目"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"無法完成這項操作,請再試一次。"</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"待播清單上沒有其他項目"</string>
 </resources>
diff --git a/car-media-common/res/values-zu/strings.xml b/car-media-common/res/values-zu/strings.xml
index cde3b48..6f06f6d 100644
--- a/car-media-common/res/values-zu/strings.xml
+++ b/car-media-common/res/values-zu/strings.xml
@@ -19,4 +19,16 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="album_art" msgid="3392647029019061691">"Ubuciko be-albhamu"</string>
     <string name="metadata_default_title" msgid="5902775732281325081">"Asikho isihloko"</string>
+    <string name="default_error_message" msgid="4044331619453864482">"Kukhona okungalungile. Zama emuva kwesikhathi."</string>
+    <string name="error_code_app_error" msgid="3608680401453743688">"Ayikwazi ukwenza lokho khona manje"</string>
+    <string name="error_code_not_supported" msgid="8004310657548193089">"Lolu hlelo lokusebenza alukwazi ukwenza lokho"</string>
+    <string name="error_code_authentication_expired" msgid="1727285213286610186">"Ngena ngemvume ukuze usebenzise lolu hlelo lokusebenza"</string>
+    <string name="error_code_premium_account_required" msgid="2328664287270814966">"Ukufinyelela kwe-premium kuyadingeka"</string>
+    <string name="error_code_concurrent_stream_limit" msgid="493048763425570552">"Ilalele kumadivayisi amaningi kakhulu"</string>
+    <string name="error_code_parental_control_restricted" msgid="325145513462419399">"Lokho okuqukethwe kuvinjelwe"</string>
+    <string name="error_code_not_available_in_region" msgid="5840935836875073145">"Ayikwazi ukuletha lokho okuqukethwe lapha"</string>
+    <string name="error_code_content_already_playing" msgid="1306236349553004461">"Isivele idlala lokho okuqukethwe"</string>
+    <string name="error_code_skip_limit_reached" msgid="4203743406433151146">"Ayikwazi ukweqa amanye amathrekhi amaningi"</string>
+    <string name="error_code_action_aborted" msgid="8611777981356536501">"Ayikwazanga ukuqeda. Zama futhi."</string>
+    <string name="error_code_end_of_queue" msgid="6935022448319288887">"Akukho okunye okufakwe kulayini"</string>
 </resources>
diff --git a/car-media-common/res/values/colors.xml b/car-media-common/res/values/colors.xml
index 51927a7..f649ba5 100644
--- a/car-media-common/res/values/colors.xml
+++ b/car-media-common/res/values/colors.xml
@@ -21,12 +21,8 @@
     <!-- App icons selection background -->
     <color name="appbar_view_icon_background_color">#66ffffff</color>
 
-    <!-- ColorChecker.java -->
-    <color name="media_tint_light">@*android:color/car_tint_light</color>
-    <color name="media_tint_dark">@*android:color/car_tint_dark</color>
-
     <!-- Color used on the placeholder album art -->
-    <color name="album_art_placeholder_color">@*android:color/car_grey_800</color>
+    <color name="album_art_placeholder_color">@color/car_grey_800</color>
 
     <!-- Media source's color if not provided -->
     <color name="media_source_default_color">@android:color/background_dark</color>
diff --git a/car-media-common/res/values/dimens.xml b/car-media-common/res/values/dimens.xml
index eedc8a6..058ec8e 100644
--- a/car-media-common/res/values/dimens.xml
+++ b/car-media-common/res/values/dimens.xml
@@ -22,14 +22,16 @@
     <dimen name="fab_spinner_size">128dp</dimen>
 
     <!-- playback_fragment.xml -->
-    <dimen name="playback_fragment_text_margin_top">@*android:dimen/car_padding_4</dimen>
-    <dimen name="playback_fragment_text_margin_x">@*android:dimen/car_padding_4</dimen>
+    <dimen name="playback_fragment_text_margin_top">@dimen/car_ui_padding_4</dimen>
+    <dimen name="playback_fragment_text_margin_x">@dimen/car_ui_padding_4</dimen>
+    <dimen name="playback_fragment_error_button_margin_top">@dimen/car_ui_padding_5</dimen>
+    <dimen name="playback_fragment_error_button_margin_bottom">@dimen/car_ui_padding_4</dimen>
 
-    <dimen name="playback_fragment_app_icon_margin_right">@*android:dimen/car_padding_4</dimen>
-    <dimen name="playback_fragment_controls_margin_bottom">@*android:dimen/car_padding_4</dimen>
+    <dimen name="playback_fragment_app_icon_margin_right">@dimen/car_ui_padding_4</dimen>
+    <dimen name="playback_fragment_controls_margin_bottom">@dimen/car_ui_padding_4</dimen>
 
     <!-- Drawable appbar_view_icon_background.xml -->
-    <dimen name="appbar_view_icon_background_corner_radius">@*android:dimen/car_radius_2</dimen>
+    <dimen name="appbar_view_icon_background_corner_radius">8dp</dimen>
     <dimen name="appbar_view_icon_touch_target_size">76dp</dimen>
     <dimen name="appbar_view_icon_background_radius">38dp</dimen>
 
@@ -37,7 +39,7 @@
     <dimen name="minimized_progress_bar_track_thickness">4dp</dimen>
 
     <!-- App selector -->
-    <dimen name="app_selector_icon_size">@*android:dimen/car_primary_icon_size</dimen>
-    <dimen name="app_selector_icon_touch_target">@*android:dimen/car_touch_target_size</dimen>
-    <dimen name="app_selector_margin_x">@*android:dimen/car_padding_2</dimen>
+    <dimen name="app_selector_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+    <dimen name="app_selector_icon_touch_target">@dimen/car_ui_touch_target_size</dimen>
+    <dimen name="app_selector_margin_x">@dimen/car_ui_padding_2</dimen>
 </resources>
diff --git a/car-media-common/res/values/integers.xml b/car-media-common/res/values/integers.xml
index 2c6177d..cda2e06 100644
--- a/car-media-common/res/values/integers.xml
+++ b/car-media-common/res/values/integers.xml
@@ -36,4 +36,7 @@
     -->
     <integer name="media_items_bitmap_max_size_px">256</integer>
 
+    <!-- The maximum number of lines for the error message in the media widget. -->
+    <integer name="widget_error_text_max_lines">3</integer>
+
 </resources>
diff --git a/car-media-common/res/values/strings.xml b/car-media-common/res/values/strings.xml
index e5831bc..424e9f7 100644
--- a/car-media-common/res/values/strings.xml
+++ b/car-media-common/res/values/strings.xml
@@ -19,4 +19,29 @@
     <string name="album_art">Album Art</string>
     <!-- Default title of current track's metadata. [CHAR LIMIT=50] -->
     <string name="metadata_default_title">No Title</string>
+
+    <!-- Default error message [CHAR LIMIT=100] -->
+    <string name="default_error_message">Something’s wrong. Try later.</string>
+    <!-- Error message set when the application state is invalid to fulfill the request. [CHAR LIMIT=100] -->
+    <string name="error_code_app_error">Can’t do that right now</string>
+    <!-- Error message set when the request is not supported by the application. [CHAR LIMIT=100] -->
+    <string name="error_code_not_supported">This app can’t do that</string>
+    <!-- Error message set when the request cannot be performed because authentication has expired. [CHAR LIMIT=100] -->
+    <string name="error_code_authentication_expired">Sign in to use this app</string>
+    <!-- Error message set when a premium account is required for the request to succeed. [CHAR LIMIT=100] -->
+    <string name="error_code_premium_account_required">Premium access required</string>
+    <!-- Error message set when too many concurrent streams are detected. [CHAR LIMIT=100] -->
+    <string name="error_code_concurrent_stream_limit">Listening on too many devices</string>
+    <!-- Error message set when the content is blocked due to parental controls. [CHAR LIMIT=100] -->
+    <string name="error_code_parental_control_restricted">That content is blocked</string>
+    <!-- Error message set when the content is blocked due to being regionally unavailable. [CHAR LIMIT=100] -->
+    <string name="error_code_not_available_in_region">Can’t get that content here</string>
+    <!-- Error message set when the requested content is already playing. [CHAR LIMIT=100] -->
+    <string name="error_code_content_already_playing">Already playing that content</string>
+    <!-- Error message set when the application cannot skip any more songs because skip limit is reached. [CHAR LIMIT=100] -->
+    <string name="error_code_skip_limit_reached">Can’t skip any more tracks</string>
+    <!-- Error message set when the action is interrupted due to some external event. [CHAR LIMIT=100] -->
+    <string name="error_code_action_aborted">Couldn’t finish. Try again.</string>
+    <!-- Error message set when the playback navigation (previous, next) is not possible because the queue was exhausted. [CHAR LIMIT=100] -->
+    <string name="error_code_end_of_queue">Nothing else is queued up</string>
 </resources>
diff --git a/car-media-common/src/com/android/car/media/common/ColorChecker.java b/car-media-common/src/com/android/car/media/common/ColorChecker.java
deleted file mode 100644
index 722ecb3..0000000
--- a/car-media-common/src/com/android/car/media/common/ColorChecker.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.media.common;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.util.Log;
-
-/**
- * A class that checks to make sure that given colors are within the acceptable contract ratio for
- * the car environment.
- */
-public class ColorChecker {
-    private static final String TAG = "ColorChecker";
-    private static final double MIN_CONTRAST_RATIO = 4.5;
-
-    /**
-     * Calls {@link #getTintColor(int, int...)} with:
-     *     {@code R.color.car_tint_light} and
-     *     {@code R.color.car_tint_dark}
-     */
-    public static int getTintColor(Context context, int backgroundColor) {
-        int lightTintColor = context.getResources().getColor(R.color.media_tint_light);
-        int darkTintColor = context.getResources().getColor(R.color.media_tint_dark);
-
-        return getTintColor(backgroundColor, lightTintColor, darkTintColor);
-    }
-
-    /**
-     * Calls {@link #getTintColor(int, int...)} with {@link #MIN_CONTRAST_RATIO}.
-     */
-    public static int getTintColor(int backgroundColor, int... tintColors) {
-        return getTintColor(MIN_CONTRAST_RATIO, backgroundColor, tintColors);
-    }
-
-    /**
-     *
-     * Determines what color to tint icons given the background color that they sit on.
-     *
-     * @param minAllowedContrastRatio The minimum contrast ratio
-     * @param bgColor The background color that the icons sit on.
-     * @param tintColors A list of potential colors to tint the icons with.
-     * @return The color that the icons should be tinted. Will be the first tinted color that
-     *         meets the requirements. If none of the tint colors meet the minimum requirements,
-     *         either black or white will be returned, whichever has a higher contrast.
-     */
-    public static int getTintColor(double minAllowedContrastRatio, int bgColor, int... tintColors) {
-        for (int tc : tintColors) {
-            double contrastRatio = getContrastRatio(bgColor, tc);
-            if (contrastRatio >= minAllowedContrastRatio) {
-                return tc;
-            }
-        }
-        double blackContrastRatio = getContrastRatio(bgColor, Color.BLACK);
-        double whiteContrastRatio = getContrastRatio(bgColor, Color.WHITE);
-        if (whiteContrastRatio >= blackContrastRatio) {
-            Log.w(TAG, "Tint color does not meet contrast requirements. Using white.");
-            return Color.WHITE;
-        } else {
-            Log.w(TAG, "Tint color does not meet contrast requirements. Using black.");
-            return Color.BLACK;
-        }
-    }
-
-    /**
-     * Returns the contrast radio between the two given colors.
-     */
-    public static double getContrastRatio(int color1, int color2) {
-        return getContrastRatio(getLuminance(color1), getLuminance(color2));
-    }
-
-    /**
-     * Returns the contrast ratio between the two luminances. Luminances maps to colors and is the
-     * result returned from {@link #getLuminance(int)}.
-     */
-    public static double getContrastRatio(double luminance1, double luminance2) {
-        return (Math.max(luminance1, luminance2) + 0.05)
-                / (Math.min(luminance1, luminance2) + 0.05);
-    }
-
-    /**
-     * Calculates the luminance of a color as specified by:
-     *     http://www.w3.org/TR/WCAG20-TECHS/G17.html
-     *
-     * @param color The color to calculate the luminance of.
-     * @return The luminance.
-     */
-    public static double getLuminance(int color) {
-        // Values are in sRGB
-        double r = convert8BitToLuminanceComponent(Color.red(color));
-        double g = convert8BitToLuminanceComponent(Color.green(color));
-        double b = convert8BitToLuminanceComponent(Color.blue(color));
-        return r * 0.2126 + g * 0.7152 + b * 0.0722;
-    }
-
-    /**
-     * Converts am 8 bit color component (0-255) to the luminance component as specified by:
-     *     http://www.w3.org/TR/WCAG20-TECHS/G17.html
-     */
-    private static double convert8BitToLuminanceComponent(double component) {
-        component /= 255.0;
-        if (component <= 0.03928) {
-            return component / 12.92;
-        } else {
-            return Math.pow(((component + 0.055) / 1.055), 2.4);
-        }
-    }
-
-    private ColorChecker() {}
-}
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 9012a3b..3cc9f30 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
@@ -16,11 +16,12 @@
 
 package com.android.car.media.common;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.media.common.playback.PlaybackViewModel.PlaybackStateWrapper;
 
 
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 c281ff7..c399089 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
@@ -41,7 +41,9 @@
 import com.android.car.media.common.source.MediaSourceColors;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -54,6 +56,8 @@
 
     private static final String TAG = "MediaButton";
 
+    private final Map<String, ImageButton> mImageButtons = new HashMap<>();
+
     private Context mContext;
     private PlayPauseStopImageView mPlayPauseStopImageView;
     private View mPlayPauseStopImageContainer;
@@ -80,6 +84,7 @@
         mPlayPauseStopImageContainer.setOnClickListener(this::onPlayPauseStopClicked);
         mPlayPauseStopImageView = mPlayPauseStopImageContainer.findViewById(R.id.play_pause_stop);
         mPlayPauseStopImageView.setVisibility(View.INVISIBLE);
+        mPlayPauseStopImageView.setFocusedByDefault(true);
         mCircularProgressBar = mPlayPauseStopImageContainer.findViewById(
                 R.id.circular_progress_bar);
         mPlayPauseStopImageView.setAction(PlayPauseStopImageView.ACTION_DISABLED);
@@ -133,6 +138,7 @@
         mControlBar.setView(null, ControlBar.SLOT_RIGHT);
         mSkipNextAdded = false;
         mSkipPrevAdded = false;
+        mImageButtons.clear();
     }
 
     private ImageButton createIconButton(Drawable icon) {
@@ -227,12 +233,7 @@
             imageButtons.addAll(state.getCustomActions()
                     .stream()
                     .map(rawAction -> rawAction.fetchDrawable(mContext))
-                    .map(action -> {
-                        ImageButton button = createIconButton(action.mIcon);
-                        button.setOnClickListener(view ->
-                                mController.doCustomAction(action.mAction, action.mExtras));
-                        return button;
-                    })
+                    .map(action -> getOrCreateIconButton(action))
                     .collect(Collectors.toList()));
         }
         if (!mSkipPrevAdded && !imageButtons.isEmpty()) {
@@ -244,6 +245,21 @@
         mControlBar.setViews(imageButtons.toArray(new ImageButton[0]));
     }
 
+    private ImageButton getOrCreateIconButton(CustomPlaybackAction action) {
+        // Reuse the ImageButton with the same action identifier if it exists, because if the
+        // ImageButton is focused, replacing it with a new one will make it lose focus.
+        ImageButton button = mImageButtons.get(action.mAction);
+        if (button != null) {
+            button.setImageDrawable(action.mIcon);
+        } else {
+            button = createIconButton(action.mIcon);
+            mImageButtons.put(action.mAction, button);
+        }
+        button.setOnClickListener(view ->
+                mController.doCustomAction(action.mAction, action.mExtras));
+        return button;
+    }
+
     private void onPlayPauseStopClicked(View view) {
         if (mController == null) {
             return;
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 317bb7a..8b7894c 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
@@ -16,8 +16,6 @@
 
 package com.android.car.media.common;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -35,6 +33,8 @@
 import android.support.v4.media.session.MediaSessionCompat;
 import android.text.TextUtils;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.car.apps.common.BitmapUtils;
diff --git a/car-media-common/src/com/android/car/media/common/MetadataController.java b/car-media-common/src/com/android/car/media/common/MetadataController.java
index 49e5a26..baeca11 100644
--- a/car-media-common/src/com/android/car/media/common/MetadataController.java
+++ b/car-media-common/src/com/android/car/media/common/MetadataController.java
@@ -19,8 +19,6 @@
 import static com.android.car.arch.common.LiveDataFunctions.combine;
 import static com.android.car.arch.common.LiveDataFunctions.pair;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.Size;
@@ -29,6 +27,8 @@
 import android.widget.SeekBar;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.LifecycleOwner;
 
 import com.android.car.apps.common.imaging.ImageViewBinder;
diff --git a/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java b/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java
index 7ce34b2..17a37b2 100644
--- a/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java
+++ b/car-media-common/src/com/android/car/media/common/MinimizedPlaybackControlBar.java
@@ -24,7 +24,9 @@
 import androidx.annotation.NonNull;
 import androidx.lifecycle.LifecycleOwner;
 
+import com.android.car.apps.common.BackgroundImageView;
 import com.android.car.apps.common.MinimizedControlBar;
+import com.android.car.apps.common.imaging.ImageBinder;
 import com.android.car.media.common.playback.PlaybackViewModel;
 
 /**
@@ -39,6 +41,7 @@
     private MetadataController mMetadataController;
     private ProgressBar mLinearProgressBar;
     private ProgressBar mCircularProgressBar;
+    private ImageBinder<MediaItemMetadata.ArtworkRef> mArtBinder = null;
     private PlaybackViewModel mPlaybackViewModel;
 
     private boolean mShowLinearProgressBar;
@@ -59,7 +62,7 @@
 
     private void init(Context context) {
         mMediaButtonController = new MediaButtonController(context, this,
-                R.color.playback_control_color, R.layout.play_pause_stop_button_layout,
+                R.color.playback_control_color, R.layout.minimized_play_pause_stop_button_layout,
                 R.drawable.ic_skip_previous, R.drawable.ic_skip_next);
 
         mShowLinearProgressBar = context.getResources().getBoolean(R.bool.show_linear_progress_bar);
@@ -68,6 +71,15 @@
         mShowCircularProgressBar = context.getResources().getBoolean(
                 R.bool.show_circular_progress_bar);
         mCircularProgressBar = findViewById(R.id.circular_progress_bar);
+
+        BackgroundImageView artBackground = findViewById(R.id.art_background);
+        if (artBackground != null) {
+            int max = getResources().getInteger(R.integer.media_items_bitmap_max_size_px);
+            Size maxArtSize = new Size(max, max);
+            mArtBinder = new ImageBinder<>(
+                    ImageBinder.PlaceholderType.BACKGROUND, maxArtSize,
+                    drawable -> artBackground.setBackgroundDrawable(drawable));
+        }
     }
 
     /** Connects the bar to the {@link PlaybackViewModel}. */
@@ -82,5 +94,11 @@
                 mLinearProgressBar, mShowLinearProgressBar);
         ControlBarHelper.initProgressBar(getContext(), owner, mPlaybackViewModel,
                 mCircularProgressBar, mShowCircularProgressBar);
+
+        if (mArtBinder != null) {
+            mPlaybackViewModel.getMetadata().observe(owner,
+                    item -> mArtBinder.setImage(getContext(),
+                            item != null ? item.getArtworkKey() : null));
+        }
     }
 }
diff --git a/car-media-common/src/com/android/car/media/common/PlaybackErrorViewController.java b/car-media-common/src/com/android/car/media/common/PlaybackErrorViewController.java
new file mode 100644
index 0000000..2d4c7c8
--- /dev/null
+++ b/car-media-common/src/com/android/car/media/common/PlaybackErrorViewController.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 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.car.media.common;
+
+import android.app.PendingIntent;
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.res.Resources;
+import android.util.Log;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import com.android.car.apps.common.UxrButton;
+import com.android.car.apps.common.UxrTextView;
+import com.android.car.apps.common.util.ViewUtils;
+
+
+/** Simple controller for the error message and the error button. */
+public class PlaybackErrorViewController {
+
+    private static final String TAG = "PlaybckErrViewCtrlr";
+
+    // mErrorMessageView is defined explicitly as a UxrTextView instead of a TextView to
+    // provide clarity as it may be misleading to assume that mErrorMessageView extends all TextView
+    // methods. In addition, it increases discoverability of runtime issues that may occur.
+    private final UxrTextView mErrorMessageView;
+    private final UxrButton mErrorButton;
+
+    private final int mFadeDuration;
+
+    public PlaybackErrorViewController(View content) {
+        mErrorMessageView = content.findViewById(R.id.error_message);
+        mErrorButton = content.findViewById(R.id.error_button);
+
+        Resources res = content.getContext().getResources();
+        mFadeDuration = res.getInteger(R.integer.new_album_art_fade_in_duration);
+    }
+
+    /** Animates away the error views. */
+    public void hideError() {
+        ViewUtils.hideViewAnimated(mErrorMessageView, mFadeDuration);
+        ViewUtils.hideViewAnimated(mErrorButton, mFadeDuration);
+    }
+
+    /** Hides the error views without animation. */
+    public void hideErrorNoAnim() {
+        ViewUtils.hideViewAnimated(mErrorMessageView, 0);
+        ViewUtils.hideViewAnimated(mErrorButton, 0);
+    }
+
+    /** Sets the error message and optionally the error button. */
+    public void setError(String message, @Nullable String label,
+            @Nullable PendingIntent pendingIntent, boolean isDistractionOptimized) {
+        mErrorMessageView.setText(message);
+        ViewUtils.showViewAnimated(mErrorMessageView, mFadeDuration);
+
+        // Only show the error button if the error is actionable.
+        if (label != null && pendingIntent != null) {
+            mErrorButton.setText(label);
+
+            mErrorButton.setUxRestrictions(isDistractionOptimized
+                    ? CarUxRestrictions.UX_RESTRICTIONS_BASELINE
+                    : CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP);
+
+            mErrorButton.setOnClickListener(v -> {
+                try {
+                    pendingIntent.send();
+                } catch (PendingIntent.CanceledException e) {
+                    if (Log.isLoggable(TAG, Log.ERROR)) {
+                        Log.e(TAG, "Pending intent canceled");
+                    }
+                }
+            });
+            ViewUtils.showViewAnimated(mErrorButton, mFadeDuration);
+        } else {
+            ViewUtils.hideViewAnimated(mErrorButton, mFadeDuration);
+        }
+    }
+}
diff --git a/car-media-common/src/com/android/car/media/common/PlaybackErrorsHelper.java b/car-media-common/src/com/android/car/media/common/PlaybackErrorsHelper.java
new file mode 100644
index 0000000..475346d
--- /dev/null
+++ b/car-media-common/src/com/android/car/media/common/PlaybackErrorsHelper.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2020 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.car.media.common;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.media.session.PlaybackStateCompat;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.media.common.playback.PlaybackViewModel.PlaybackStateWrapper;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Abstract class to factorize most of the error handling logic.
+ */
+public abstract class PlaybackErrorsHelper {
+
+    private static final Map<Integer, Integer> ERROR_CODE_MESSAGES_MAP;
+
+    static {
+        Map<Integer, Integer> map = new HashMap<>();
+        map.put(PlaybackStateCompat.ERROR_CODE_APP_ERROR, R.string.error_code_app_error);
+        map.put(PlaybackStateCompat.ERROR_CODE_NOT_SUPPORTED, R.string.error_code_not_supported);
+        map.put(PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED,
+                R.string.error_code_authentication_expired);
+        map.put(PlaybackStateCompat.ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED,
+                R.string.error_code_premium_account_required);
+        map.put(PlaybackStateCompat.ERROR_CODE_CONCURRENT_STREAM_LIMIT,
+                R.string.error_code_concurrent_stream_limit);
+        map.put(PlaybackStateCompat.ERROR_CODE_PARENTAL_CONTROL_RESTRICTED,
+                R.string.error_code_parental_control_restricted);
+        map.put(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION,
+                R.string.error_code_not_available_in_region);
+        map.put(PlaybackStateCompat.ERROR_CODE_CONTENT_ALREADY_PLAYING,
+                R.string.error_code_content_already_playing);
+        map.put(PlaybackStateCompat.ERROR_CODE_SKIP_LIMIT_REACHED,
+                R.string.error_code_skip_limit_reached);
+        map.put(PlaybackStateCompat.ERROR_CODE_ACTION_ABORTED, R.string.error_code_action_aborted);
+        map.put(PlaybackStateCompat.ERROR_CODE_END_OF_QUEUE, R.string.error_code_end_of_queue);
+        ERROR_CODE_MESSAGES_MAP = Collections.unmodifiableMap(map);
+    }
+
+    private final Context mContext;
+    private PlaybackStateWrapper mCurrentPlaybackStateWrapper;
+
+    public PlaybackErrorsHelper(Context context) {
+        mContext = context;
+    }
+
+    protected abstract void handleNewPlaybackState(String displayedMessage, PendingIntent intent,
+            String label);
+
+    /**
+     * Triggers updates of the error state.
+     * Must be called when the children list of the root of the browse tree changes AND when
+     * the playback state changes.
+     */
+    public void handlePlaybackState(@NonNull String tag, PlaybackStateWrapper state,
+            boolean ignoreSameState) {
+        if (Log.isLoggable(tag, Log.DEBUG)) {
+            Log.d(tag,
+                    "handlePlaybackState(); state change: " + (mCurrentPlaybackStateWrapper != null
+                            ? mCurrentPlaybackStateWrapper.getState() : null) + " -> " + (
+                            state != null ? state.getState() : null));
+        }
+
+        if (state == null) {
+            mCurrentPlaybackStateWrapper = null;
+            return;
+        }
+
+        String displayedMessage = getDisplayedMessage(mContext, state);
+        if (Log.isLoggable(tag, Log.DEBUG)) {
+            Log.d(tag, "Displayed error message: [" + displayedMessage + "]");
+        }
+        if (ignoreSameState && mCurrentPlaybackStateWrapper != null
+                && mCurrentPlaybackStateWrapper.getState() == state.getState()
+                && TextUtils.equals(displayedMessage,
+                getDisplayedMessage(mContext, mCurrentPlaybackStateWrapper))) {
+            if (Log.isLoggable(tag, Log.DEBUG)) {
+                Log.d(tag, "Ignore same playback state.");
+            }
+            return;
+        }
+
+        mCurrentPlaybackStateWrapper = state;
+
+        PendingIntent intent = getErrorResolutionIntent(state);
+        String label = getErrorResolutionLabel(state);
+        handleNewPlaybackState(displayedMessage, intent, label);
+    }
+
+
+    @Nullable
+    private String getDisplayedMessage(Context ctx, @Nullable PlaybackStateWrapper state) {
+        if (state == null) {
+            return null;
+        }
+        if (!TextUtils.isEmpty(state.getErrorMessage())) {
+            return state.getErrorMessage().toString();
+        }
+        // ERROR_CODE_UNKNOWN_ERROR means there is no error in PlaybackState.
+        if (state.getErrorCode() != PlaybackStateCompat.ERROR_CODE_UNKNOWN_ERROR) {
+            Integer messageId = ERROR_CODE_MESSAGES_MAP.get(state.getErrorCode());
+            return messageId != null ? ctx.getString(messageId) : ctx.getString(
+                    R.string.default_error_message);
+        }
+        if (state.getState() == PlaybackStateCompat.STATE_ERROR) {
+            return ctx.getString(R.string.default_error_message);
+        }
+        return null;
+    }
+
+    @Nullable
+    private PendingIntent getErrorResolutionIntent(@NonNull PlaybackStateWrapper state) {
+        Bundle extras = state.getExtras();
+        return extras == null ? null : extras.getParcelable(
+                MediaConstants.ERROR_RESOLUTION_ACTION_INTENT);
+    }
+
+    @Nullable
+    private String getErrorResolutionLabel(@NonNull PlaybackStateWrapper state) {
+        Bundle extras = state.getExtras();
+        return extras == null ? null : extras.getString(
+                MediaConstants.ERROR_RESOLUTION_ACTION_LABEL);
+    }
+
+}
diff --git a/car-media-common/src/com/android/car/media/common/PlaybackFragment.java b/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
index 36f428d..60f4d18 100644
--- a/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
+++ b/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
@@ -16,13 +16,18 @@
 
 package com.android.car.media.common;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static com.android.car.arch.common.LiveDataFunctions.mapNonNull;
 
 import android.app.Application;
+import android.app.PendingIntent;
 import android.car.Car;
+import android.car.content.pm.CarPackageManager;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.util.Size;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -36,64 +41,105 @@
 import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.ViewModelProviders;
 
 import com.android.car.apps.common.BitmapUtils;
 import com.android.car.apps.common.CrossfadeImageView;
 import com.android.car.apps.common.imaging.ImageBinder;
 import com.android.car.apps.common.imaging.ImageBinder.PlaceholderType;
+import com.android.car.apps.common.util.CarPackageManagerUtils;
 import com.android.car.apps.common.util.ViewUtils;
+import com.android.car.arch.common.FutureData;
+import com.android.car.media.common.browse.BrowsedMediaItems;
+import com.android.car.media.common.browse.MediaBrowserViewModel;
 import com.android.car.media.common.playback.PlaybackViewModel;
+import com.android.car.media.common.playback.PlaybackViewModel.PlaybackStateWrapper;
 import com.android.car.media.common.source.MediaSource;
 import com.android.car.media.common.source.MediaSourceViewModel;
 
+import java.util.List;
+
 /**
  * {@link Fragment} that can be used to display and control the currently playing media item. Its
  * requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by the hosting
  * application.
  */
 public class PlaybackFragment extends Fragment {
+    private static final String TAG = "PlaybackFragmentWidget";
+
+    private Car mCar;
+    private CarPackageManager mCarPackageManager;
     private Intent mAppSelectorIntent;
     private MediaSourceViewModel mMediaSourceViewModel;
+    private PlaybackViewModel mPlaybackViewModel;
     private ImageBinder<MediaItemMetadata.ArtworkRef> mAlbumArtBinder;
+    private ViewModel mInnerViewModel;
+
+    private PlaybackErrorViewController mPlaybackErrorViewController;
+    private PlaybackErrorsHelper mErrorsHelper;
+    private boolean mIsFatalError;
 
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
             Bundle savedInstanceState) {
         FragmentActivity activity = requireActivity();
-        PlaybackViewModel playbackViewModel = PlaybackViewModel.get(activity.getApplication());
-        mMediaSourceViewModel = MediaSourceViewModel.get(activity.getApplication());
+        mCar = Car.createCar(activity);
+        mCarPackageManager = (CarPackageManager) mCar.getCarManager(Car.PACKAGE_SERVICE);
+
+        mPlaybackViewModel = PlaybackViewModel.get(activity.getApplication(),
+                MEDIA_SOURCE_MODE_PLAYBACK);
+        mMediaSourceViewModel = MediaSourceViewModel.get(activity.getApplication(),
+                MEDIA_SOURCE_MODE_PLAYBACK);
         mAppSelectorIntent = MediaSource.getSourceSelectorIntent(getContext(), true);
 
-        ViewModel innerViewModel = ViewModelProviders.of(activity).get(ViewModel.class);
-        innerViewModel.init(mMediaSourceViewModel, playbackViewModel);
+        mInnerViewModel = ViewModelProviders.of(activity).get(ViewModel.class);
+        mInnerViewModel.init(activity, mMediaSourceViewModel, mPlaybackViewModel);
 
         View view = inflater.inflate(R.layout.playback_fragment, container, false);
 
+        mPlaybackErrorViewController = new PlaybackErrorViewController(view);
+
         PlaybackControlsActionBar playbackControls = view.findViewById(R.id.playback_controls);
-        playbackControls.setModel(playbackViewModel, getViewLifecycleOwner());
-        playbackViewModel.getPlaybackStateWrapper().observe(getViewLifecycleOwner(),
-                state -> ViewUtils.setVisible(playbackControls,
-                        (state != null) && state.shouldDisplay()));
+        playbackControls.setModel(mPlaybackViewModel, getViewLifecycleOwner());
+        mPlaybackViewModel.getPlaybackStateWrapper().observe(getViewLifecycleOwner(),
+                state -> {
+                    ViewUtils.setVisible(playbackControls,
+                            (state != null) && state.shouldDisplay());
+                    if (mErrorsHelper != null) {
+                        mErrorsHelper.handlePlaybackState(TAG, state, /*ignoreSameState*/ true);
+                    }
+                });
 
         TextView appName = view.findViewById(R.id.app_name);
-        innerViewModel.getAppName().observe(getViewLifecycleOwner(), appName::setText);
+        mInnerViewModel.getAppName().observe(getViewLifecycleOwner(), appName::setText);
 
         TextView title = view.findViewById(R.id.title);
-        innerViewModel.getTitle().observe(getViewLifecycleOwner(), title::setText);
+        mInnerViewModel.getTitle().observe(getViewLifecycleOwner(), title::setText);
 
         TextView subtitle = view.findViewById(R.id.subtitle);
-        innerViewModel.getSubtitle().observe(getViewLifecycleOwner(), subtitle::setText);
+        mInnerViewModel.getSubtitle().observe(getViewLifecycleOwner(), subtitle::setText);
 
         ImageView appIcon = view.findViewById(R.id.app_icon);
-        innerViewModel.getAppIcon().observe(getViewLifecycleOwner(), appIcon::setImageBitmap);
+        mInnerViewModel.getAppIcon().observe(getViewLifecycleOwner(), appIcon::setImageBitmap);
+
+        mInnerViewModel.getBrowseTreeHasChildren().observe(getViewLifecycleOwner(),
+                this::onBrowseTreeHasChildrenChanged);
+
+        mMediaSourceViewModel.getPrimaryMediaSource().observe(getViewLifecycleOwner(),
+                this::onMediaSourceChanged);
+
+        View playbackScrim = view.findViewById(R.id.playback_scrim);
+        playbackScrim.setOnClickListener(
+                // Let the Media center trampoline figure out what to open.
+                v -> {
+                    if (!mIsFatalError) {
+                        startActivity(new Intent(Car.CAR_INTENT_ACTION_MEDIA_TEMPLATE));
+                    }
+                });
 
         CrossfadeImageView albumBackground = view.findViewById(R.id.album_background);
-        albumBackground.setOnClickListener(
-                // Let the Media center trampoline figure out what to open.
-                v -> startActivity(new Intent(Car.CAR_INTENT_ACTION_MEDIA_TEMPLATE)));
-
         int max = activity.getResources().getInteger(R.integer.media_items_bitmap_max_size_px);
         Size maxArtSize = new Size(max, max);
         mAlbumArtBinder = new ImageBinder<>(PlaceholderType.FOREGROUND, maxArtSize,
@@ -103,16 +149,59 @@
                     albumBackground.setImageBitmap(bitmap, true);
                 });
 
-        playbackViewModel.getMetadata().observe(getViewLifecycleOwner(),
+        mPlaybackViewModel.getMetadata().observe(getViewLifecycleOwner(),
                 item -> mAlbumArtBinder.setImage(PlaybackFragment.this.getContext(),
                         item != null ? item.getArtworkKey() : null));
         View appSelector = view.findViewById(R.id.app_selector_container);
         appSelector.setVisibility(mAppSelectorIntent != null ? View.VISIBLE : View.GONE);
         appSelector.setOnClickListener(e -> getContext().startActivity(mAppSelectorIntent));
 
+
+        mErrorsHelper = new PlaybackErrorsHelper(activity) {
+
+            @Override
+            public void handleNewPlaybackState(String displayedMessage, PendingIntent intent,
+                    String label) {
+                mIsFatalError = false;
+                if (!TextUtils.isEmpty(displayedMessage)) {
+                    Boolean hasChildren = mInnerViewModel.getBrowseTreeHasChildren().getValue();
+                    if (hasChildren != null && !hasChildren) {
+                        boolean isDistractionOptimized =
+                                intent != null && CarPackageManagerUtils.isDistractionOptimized(
+                                        mCarPackageManager, intent);
+                        mPlaybackErrorViewController.setError(displayedMessage, label, intent,
+                                isDistractionOptimized);
+                        mIsFatalError = true;
+                    }
+                }
+
+                if (!mIsFatalError) {
+                    mPlaybackErrorViewController.hideError();
+                }
+            }
+        };
+
         return view;
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        mCar.disconnect();
+        mErrorsHelper = null;
+    }
+
+    private void onBrowseTreeHasChildrenChanged(@Nullable Boolean hasChildren) {
+        if (hasChildren != null && mErrorsHelper != null) {
+            PlaybackStateWrapper state = mPlaybackViewModel.getPlaybackStateWrapper().getValue();
+            mErrorsHelper.handlePlaybackState(TAG, state, /*ignoreSameState*/ false);
+        }
+    }
+
+    private void onMediaSourceChanged(MediaSource source) {
+        mPlaybackErrorViewController.hideErrorNoAnim();
+    }
+
     /**
      * ViewModel for the PlaybackFragment
      */
@@ -123,15 +212,18 @@
         private LiveData<Bitmap> mAppIcon;
         private LiveData<CharSequence> mTitle;
         private LiveData<CharSequence> mSubtitle;
+        private MutableLiveData<Boolean> mBrowseTreeHasChildren = new MutableLiveData<>();
 
         private PlaybackViewModel mPlaybackViewModel;
         private MediaSourceViewModel mMediaSourceViewModel;
+        private MediaBrowserViewModel mRootMediaBrowserViewModel;
 
         public ViewModel(Application application) {
             super(application);
         }
 
-        void init(MediaSourceViewModel mediaSourceViewModel, PlaybackViewModel playbackViewModel) {
+        void init(FragmentActivity activity, MediaSourceViewModel mediaSourceViewModel,
+                PlaybackViewModel playbackViewModel) {
             if (mMediaSourceViewModel == mediaSourceViewModel
                     && mPlaybackViewModel == playbackViewModel) {
                 return;
@@ -140,9 +232,14 @@
             mMediaSourceViewModel = mediaSourceViewModel;
             mMediaSource = mMediaSourceViewModel.getPrimaryMediaSource();
             mAppName = mapNonNull(mMediaSource, MediaSource::getDisplayName);
-            mAppIcon = mapNonNull(mMediaSource, MediaSource::getRoundPackageIcon);
+            mAppIcon = mapNonNull(mMediaSource, MediaSource::getCroppedPackageIcon);
             mTitle = mapNonNull(playbackViewModel.getMetadata(), MediaItemMetadata::getTitle);
             mSubtitle = mapNonNull(playbackViewModel.getMetadata(), MediaItemMetadata::getArtist);
+
+            mRootMediaBrowserViewModel = MediaBrowserViewModel.Factory.getInstanceForBrowseRoot(
+                    mMediaSourceViewModel, ViewModelProviders.of(activity));
+            mRootMediaBrowserViewModel.getBrowsedMediaItems()
+                    .observe(activity, this::onItemsUpdate);
         }
 
         LiveData<CharSequence> getAppName() {
@@ -160,5 +257,22 @@
         LiveData<CharSequence> getSubtitle() {
             return mSubtitle;
         }
+
+        LiveData<Boolean> getBrowseTreeHasChildren() {
+            return mBrowseTreeHasChildren;
+        }
+
+        private void onItemsUpdate(FutureData<List<MediaItemMetadata>> futureData) {
+            if (futureData.isLoading()) {
+                mBrowseTreeHasChildren.setValue(null);
+                return;
+            }
+
+            List<MediaItemMetadata> items =
+                    BrowsedMediaItems.filterItems(/*forRoot*/ true, futureData.getData());
+
+            boolean browseTreeHasChildren = items != null && !items.isEmpty();
+            mBrowseTreeHasChildren.setValue(browseTreeHasChildren);
+        }
     }
 }
diff --git a/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java b/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java
index 5c0a13d..c9a5864 100644
--- a/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java
+++ b/car-media-common/src/com/android/car/media/common/browse/BrowsedMediaItems.java
@@ -16,24 +16,26 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.LiveData;
 
 import com.android.car.media.common.MediaItemMetadata;
 
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
  * A LiveData that provides access the a MediaBrowser's children
  */
 
-class BrowsedMediaItems extends LiveData<List<MediaItemMetadata>> {
+public class BrowsedMediaItems extends LiveData<List<MediaItemMetadata>> {
 
     /**
      * Number of times we will retry obtaining the list of children of a certain node
@@ -58,6 +60,19 @@
         mParentId = parentId;
     }
 
+    /**
+     * Filters the items that are valid for the root (tabs) or the current node. Returns null when
+     * the given list is null to preserve its error signal.
+     */
+    @Nullable
+    public static List<MediaItemMetadata> filterItems(boolean forRoot,
+            @Nullable List<MediaItemMetadata> items) {
+        if (items == null) return null;
+        Predicate<MediaItemMetadata> predicate = forRoot ? MediaItemMetadata::isBrowsable
+                : item -> (item.isPlayable() || item.isBrowsable());
+        return items.stream().filter(predicate).collect(Collectors.toList());
+    }
+
     @Override
     protected void onActive() {
         super.onActive();
diff --git a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java
index 5a4626a..323b4ce 100644
--- a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModel.java
@@ -16,11 +16,11 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UiThread;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.ViewModelProvider;
 
@@ -37,31 +37,11 @@
 public interface MediaBrowserViewModel {
 
     /**
-     * Possible states of the application UI
-     */
-    enum BrowseState {
-        /** There is no content to show */
-        EMPTY,
-        /** We are still in the process of obtaining data */
-        LOADING,
-        /** Data has been loaded */
-        LOADED,
-        /** The content can't be shown due an error */
-        ERROR
-    }
-
-    /**
      * Returns a LiveData that emits the current package name of the browser's service component.
      */
     LiveData<String> getPackageName();
 
     /**
-     * Returns a LiveData that emits the current {@link BrowseState}
-     */
-    LiveData<BrowseState> getBrowseState();
-
-
-    /**
      * Fetches the MediaItemMetadatas for the current browsed id, and the loading status of the
      * fetch operation.
      *
diff --git a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java
index 7d47ba7..949c81d 100644
--- a/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java
+++ b/car-media-common/src/com/android/car/media/common/browse/MediaBrowserViewModelImpl.java
@@ -23,17 +23,16 @@
 import static com.android.car.arch.common.LiveDataFunctions.pair;
 import static com.android.car.arch.common.LiveDataFunctions.split;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.Application;
 import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 import android.text.TextUtils;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MediatorLiveData;
 import androidx.lifecycle.MutableLiveData;
 
 import com.android.car.arch.common.FutureData;
@@ -62,9 +61,6 @@
 
     private final LiveData<FutureData<List<MediaItemMetadata>>> mSearchedMediaItems;
     private final LiveData<FutureData<List<MediaItemMetadata>>> mBrowsedMediaItems;
-
-    private final LiveData<BrowseState> mBrowseState;
-
     private final LiveData<String> mPackageName;
 
     MediaBrowserViewModelImpl(@NonNull Application application, boolean isRoot) {
@@ -94,39 +90,6 @@
                                 (mediaBrowser == null || TextUtils.isEmpty(query))
                                         ? null
                                         : new SearchedMediaItems(mediaBrowser, query)));
-
-        mBrowseState = new MediatorLiveData<BrowseState>() {
-            {
-                setValue(BrowseState.EMPTY);
-                addSource(mBrowsedMediaItems, items -> update());
-            }
-
-            private void update() {
-                setValue(getState());
-            }
-
-            private BrowseState getState() {
-                if (mBrowsedMediaItems.getValue() == null) {
-                    // Uninitialized
-                    return BrowseState.EMPTY;
-                }
-                if (mBrowsedMediaItems.getValue().isLoading()) {
-                    return BrowseState.LOADING;
-                }
-                List<MediaItemMetadata> items = mBrowsedMediaItems.getValue().getData();
-                if (items == null) {
-                    // Normally this could be null if it hasn't been initialized, but in that case
-                    // isLoading would not be false, so this means it must have encountered an
-                    // error.
-                    return BrowseState.ERROR;
-                }
-                if (items.isEmpty()) {
-                    return BrowseState.EMPTY;
-                }
-                return BrowseState.LOADED;
-            }
-        };
-
     }
 
     private static MediaBrowserCompat requireConnected(@Nullable MediaBrowserCompat mediaBrowser) {
@@ -155,11 +118,6 @@
     }
 
     @Override
-    public LiveData<BrowseState> getBrowseState() {
-        return mBrowseState;
-    }
-
-    @Override
     public LiveData<FutureData<List<MediaItemMetadata>>> getBrowsedMediaItems() {
         return mBrowsedMediaItems;
     }
diff --git a/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java b/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java
index 482efdd..1290b20 100644
--- a/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/browse/MutableMediaBrowserViewModel.java
@@ -16,12 +16,12 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UiThread;
 import android.app.Application;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.UiThread;
 
 /** This isn't a comment. */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
diff --git a/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java b/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java
index 1edb484..f1ffc64 100644
--- a/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/browse/RootMediaBrowserViewModel.java
@@ -16,9 +16,9 @@
 
 package com.android.car.media.common.browse;
 
-import android.annotation.NonNull;
 import android.app.Application;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 
 /** This isn't a comment. */
diff --git a/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java b/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java
index 2f7d0c9..b8c7423 100644
--- a/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java
+++ b/car-media-common/src/com/android/car/media/common/browse/SearchedMediaItems.java
@@ -18,11 +18,11 @@
 
 import static java.util.stream.Collectors.toList;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.LiveData;
 
 import com.android.car.media.common.MediaItemMetadata;
diff --git a/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java b/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java
index 0d4c06b..88b3a0b 100644
--- a/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java
+++ b/car-media-common/src/com/android/car/media/common/playback/PlaybackStateAnnotations.java
@@ -16,10 +16,11 @@
 
 package com.android.car.media.common.playback;
 
-import android.annotation.IntDef;
-import android.annotation.LongDef;
 import android.media.session.PlaybackState;
 
+import androidx.annotation.IntDef;
+import androidx.annotation.LongDef;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
diff --git a/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java b/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java
index 94803f5..bcb9893 100644
--- a/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/playback/PlaybackViewModel.java
@@ -16,14 +16,13 @@
 
 package com.android.car.media.common.playback;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static androidx.lifecycle.Transformations.switchMap;
 
 import static com.android.car.arch.common.LiveDataFunctions.dataOf;
 import static com.android.car.media.common.playback.PlaybackStateAnnotations.Actions;
 
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.Application;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -38,6 +37,10 @@
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.util.Log;
 
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
@@ -49,7 +52,6 @@
 import com.android.car.media.common.R;
 import com.android.car.media.common.source.MediaSourceColors;
 import com.android.car.media.common.source.MediaSourceViewModel;
-import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -74,14 +76,22 @@
             "com.android.car.media.common.ACTION_SET_RATING";
     private static final String EXTRA_SET_HEART = "com.android.car.media.common.EXTRA_SET_HEART";
 
-    private static PlaybackViewModel sInstance;
+    private static PlaybackViewModel[] sInstances = new PlaybackViewModel[2];
+
+    /**
+     * Returns the PlaybackViewModel singleton tied to the application.
+     * @deprecated should use get(Application application, int mode) instead
+     */
+    public static PlaybackViewModel get(@NonNull Application application) {
+        return get(application, MEDIA_SOURCE_MODE_PLAYBACK);
+    }
 
     /** Returns the PlaybackViewModel singleton tied to the application. */
-    public static PlaybackViewModel get(@NonNull Application application) {
-        if (sInstance == null) {
-            sInstance = new PlaybackViewModel(application);
+    public static PlaybackViewModel get(@NonNull Application application, int mode) {
+        if (sInstances[mode] == null) {
+            sInstances[mode] = new PlaybackViewModel(application, mode);
         }
-        return sInstance;
+        return sInstances[mode];
     }
 
     /**
@@ -137,8 +147,8 @@
                     state -> state == null ? dataOf(new PlaybackProgress(0L, 0L))
                             : new ProgressLiveData(state.mState, state.getMaxProgress()));
 
-    private PlaybackViewModel(Application application) {
-        this(application, MediaSourceViewModel.get(application).getMediaController());
+    private PlaybackViewModel(Application application, int mode) {
+        this(application, MediaSourceViewModel.get(application, mode).getMediaController());
     }
 
     @VisibleForTesting
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java b/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java
index b16164a..14271e4 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaBrowserConnector.java
@@ -18,14 +18,15 @@
 
 import static com.android.car.apps.common.util.CarAppsDebugUtils.idHash;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Bundle;
 import android.support.v4.media.MediaBrowserCompat;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.media.common.MediaConstants;
 
 /**
@@ -56,7 +57,7 @@
      *
      * @param context The Context with which to build MediaBrowsers.
      */
-    MediaBrowserConnector(@NonNull Context context, @NonNull Callback callback) {
+    public MediaBrowserConnector(@NonNull Context context, @NonNull Callback callback) {
         mContext = context;
         mCallback = callback;
         mMaxBitmapSizePx = mContext.getResources().getInteger(
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 f856eb2..e09c248 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
@@ -16,8 +16,6 @@
 
 package com.android.car.media.common.source;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -26,17 +24,16 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.service.media.MediaBrowserService;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.car.apps.common.BitmapUtils;
+import com.android.car.apps.common.IconCropper;
 import com.android.car.media.common.R;
 
 import java.net.URISyntaxException;
@@ -57,6 +54,8 @@
     private final CharSequence mDisplayName;
     @NonNull
     private final Drawable mIcon;
+    @NonNull
+    private final IconCropper mIconCropper;
 
     /**
      * Creates a {@link MediaSource} for the given {@link ComponentName}
@@ -78,7 +77,7 @@
             CharSequence displayName = extractDisplayName(context, serviceInfo, packageName);
             Drawable icon = extractIcon(context, serviceInfo, packageName);
             ComponentName browseService = new ComponentName(packageName, className);
-            return new MediaSource(browseService, displayName, icon);
+            return new MediaSource(browseService, displayName, icon, new IconCropper(context));
         } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Component not found " + componentName.flattenToString());
             return null;
@@ -86,10 +85,11 @@
     }
 
     private MediaSource(@NonNull ComponentName browseService, @NonNull CharSequence displayName,
-            @NonNull Drawable icon) {
+            @NonNull Drawable icon, @NonNull IconCropper iconCropper) {
         mBrowseService = browseService;
         mDisplayName = displayName;
         mIcon = icon;
+        mIconCropper = iconCropper;
     }
 
     /**
@@ -186,29 +186,11 @@
     }
 
     /**
-     * Returns this media source's icon cropped to a circle.
+     * Returns this media source's icon cropped to a predefined shape (see
+     * {@link #IconCropper(Context)} on where and how the shape is defined).
      */
-    public Bitmap getRoundPackageIcon() {
-        return getRoundCroppedBitmap(BitmapUtils.fromDrawable(mIcon, null));
-    }
-
-    private static Bitmap getRoundCroppedBitmap(Bitmap bitmap) {
-        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
-                Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(output);
-
-        final int color = 0xff424242;
-        final Paint paint = new Paint();
-        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
-
-        paint.setAntiAlias(true);
-        canvas.drawARGB(0, 0, 0, 0);
-        paint.setColor(color);
-        canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
-                bitmap.getWidth() / 2f, paint);
-        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
-        canvas.drawBitmap(bitmap, rect, rect, paint);
-        return output;
+    public Bitmap getCroppedPackageIcon() {
+        return mIconCropper.crop(mIcon);
     }
 
     @Override
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java b/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
index 1d02209..4fbb202 100644
--- a/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSourceViewModel.java
@@ -16,11 +16,11 @@
 
 package com.android.car.media.common.source;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static com.android.car.apps.common.util.CarAppsDebugUtils.idHash;
 import static com.android.car.arch.common.LiveDataFunctions.dataOf;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.Application;
 import android.car.Car;
 import android.car.CarNotConnectedException;
@@ -28,12 +28,13 @@
 import android.content.ComponentName;
 import android.media.session.MediaController;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.support.v4.media.MediaBrowserCompat;
 import android.support.v4.media.session.MediaControllerCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
@@ -48,12 +49,13 @@
 public class MediaSourceViewModel extends AndroidViewModel {
     private static final String TAG = "MediaSourceViewModel";
 
-    private static MediaSourceViewModel sInstance;
+    private static MediaSourceViewModel[] sInstances = new MediaSourceViewModel[2];
     private final Car mCar;
     private CarMediaManager mCarMediaManager;
 
     // Primary media source.
     private final MutableLiveData<MediaSource> mPrimaryMediaSource = dataOf(null);
+
     // Connected browser for the primary media source.
     private final MutableLiveData<MediaBrowserCompat> mConnectedMediaBrowser = dataOf(null);
     // Media controller for the connected browser.
@@ -79,12 +81,20 @@
         MediaSource getMediaSource(ComponentName componentName);
     }
 
-    /** Returns the MediaSourceViewModel singleton tied to the application. */
+    /**
+     * Returns the MediaSourceViewModel singleton tied to the application.
+     * @deprecated should use get(Application application, int mode) instead
+     */
     public static MediaSourceViewModel get(@NonNull Application application) {
-        if (sInstance == null) {
-            sInstance = new MediaSourceViewModel(application);
+        return get(application, MEDIA_SOURCE_MODE_PLAYBACK);
+    }
+
+    /** Returns the MediaSourceViewModel singleton tied to the application. */
+    public static MediaSourceViewModel get(@NonNull Application application, int mode) {
+        if (sInstances[mode] == null) {
+            sInstances[mode] = new MediaSourceViewModel(application, mode);
         }
-        return sInstance;
+        return sInstances[mode];
     }
 
     /**
@@ -92,8 +102,8 @@
      *
      * @see AndroidViewModel
      */
-    private MediaSourceViewModel(@NonNull Application application) {
-        this(application, new InputFactory() {
+    private MediaSourceViewModel(@NonNull Application application, int mode) {
+        this(application, mode, new InputFactory() {
             @Override
             public MediaBrowserConnector createMediaBrowserConnector(
                     @NonNull Application application,
@@ -104,13 +114,7 @@
             @Override
             public MediaControllerCompat getControllerForSession(
                     @Nullable MediaSessionCompat.Token token) {
-                if (token == null) return null;
-                try {
-                    return new MediaControllerCompat(application, token);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Couldn't get MediaControllerCompat", e);
-                    return null;
-                }
+                return token == null ? null : new MediaControllerCompat(application, token);
             }
 
             @Override
@@ -136,7 +140,8 @@
     private final MediaBrowserConnector.Callback mConnectedBrowserCallback;
 
     @VisibleForTesting
-    MediaSourceViewModel(@NonNull Application application, @NonNull InputFactory inputFactory) {
+    MediaSourceViewModel(@NonNull Application application, int mode,
+            @NonNull InputFactory inputFactory) {
         super(application);
 
         mInputFactory = inputFactory;
@@ -166,13 +171,19 @@
 
         try {
             mCarMediaManager = mInputFactory.getCarMediaManager(mCar);
-            mCarMediaManager.registerMediaSourceListener(mMediaSourceListener);
-            updateModelState(mInputFactory.getMediaSource(mCarMediaManager.getMediaSource()));
+            mCarMediaManager.addMediaSourceListener(mMediaSourceListener, mode);
+            updateModelState(mInputFactory.getMediaSource(mCarMediaManager.getMediaSource(mode)));
         } catch (CarNotConnectedException e) {
             Log.e(TAG, "Car not connected", e);
         }
     }
 
+    @Override
+    protected void onCleared() {
+        super.onCleared();
+        mCar.disconnect();
+    }
+
     @VisibleForTesting
     MediaBrowserConnector.Callback getConnectedBrowserCallback() {
         return mConnectedBrowserCallback;
@@ -188,8 +199,8 @@
     /**
      * Updates the primary media source.
      */
-    public void setPrimaryMediaSource(@NonNull MediaSource mediaSource) {
-        mCarMediaManager.setMediaSource(mediaSource.getBrowseServiceComponentName());
+    public void setPrimaryMediaSource(@NonNull MediaSource mediaSource, int mode) {
+        mCarMediaManager.setMediaSource(mediaSource.getBrowseServiceComponentName(), mode);
     }
 
     /**
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSourcesLiveData.java b/car-media-common/src/com/android/car/media/common/source/MediaSourcesLiveData.java
deleted file mode 100644
index 7d423c8..0000000
--- a/car-media-common/src/com/android/car/media/common/source/MediaSourcesLiveData.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2018 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.car.media.common.source;
-
-import android.annotation.NonNull;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.service.media.MediaBrowserService;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.media.common.R;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Singleton that provides access to the list of all possible media sources that can be selected
- * to be played.
- */
-// TODO(arnaudberry) rename to MediaSourcesProvider
-public class MediaSourcesLiveData {
-
-    private static final String TAG = "MediaSources";
-
-    private static MediaSourcesLiveData sInstance;
-    private final Context mAppContext;
-    @Nullable
-    private List<MediaSource> mMediaSources;
-
-    private final BroadcastReceiver mAppInstallUninstallReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            reset();
-        }
-    };
-
-    /** Returns the singleton instance. */
-    public static MediaSourcesLiveData getInstance(@NonNull Context context) {
-        if (sInstance == null) {
-            sInstance = new MediaSourcesLiveData(context);
-        }
-        return sInstance;
-    }
-
-    /** Returns a different instance every time (tests don't like statics) */
-    @VisibleForTesting
-    public static MediaSourcesLiveData createForTesting(@NonNull Context context) {
-        return new MediaSourcesLiveData(context);
-    }
-
-    @VisibleForTesting
-    void reset() {
-        mMediaSources = null;
-    }
-
-    private MediaSourcesLiveData(@NonNull Context context) {
-        mAppContext = context.getApplicationContext();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addDataScheme("package");
-        mAppContext.registerReceiver(mAppInstallUninstallReceiver, filter);
-    }
-
-    /**
-     * Returns the sorted list of available media sources. Sources listed in the array resource
-     * R.array.preferred_media_sources are included first. Other sources follow in alphabetical
-     * order.
-     */
-    public List<MediaSource> getList() {
-        if (mMediaSources == null) {
-            // Get the flattened components to display first.
-            String[] preferredFlats = mAppContext.getResources().getStringArray(
-                    R.array.preferred_media_sources);
-
-            // Make a map of components to display first (the value is the component's index).
-            HashMap<ComponentName, Integer> preferredComps = new HashMap<>(preferredFlats.length);
-            for (int i = 0; i < preferredFlats.length; i++) {
-                preferredComps.put(ComponentName.unflattenFromString(preferredFlats[i]), i);
-            }
-
-            // Prepare an array of the sources to display first (unavailable preferred components
-            // will be excluded).
-            MediaSource[] preferredSources = new MediaSource[preferredFlats.length];
-            List<MediaSource> sortedSources = getComponentNames().stream()
-                    .filter(Objects::nonNull)
-                    .map(componentName -> MediaSource.create(mAppContext, componentName))
-                    .filter(mediaSource -> {
-                        if (mediaSource == null) {
-                            Log.w(TAG, "Media source is null");
-                            return false;
-                        }
-                        ComponentName srcComp = mediaSource.getBrowseServiceComponentName();
-                        if (preferredComps.containsKey(srcComp)) {
-                            // Record the source in the preferred array...
-                            preferredSources[preferredComps.get(srcComp)] = mediaSource;
-                            // And exclude it from the alpha sort.
-                            return false;
-                        }
-                        return true;
-                    })
-                    .sorted(Comparator.comparing(
-                            mediaSource -> mediaSource.getDisplayName().toString()))
-                    .collect(Collectors.toList());
-
-            // Concatenate the non null preferred sources and the sorted ones into the result.
-            mMediaSources = new ArrayList<>(sortedSources.size() + preferredFlats.length);
-            Arrays.stream(preferredSources).filter(Objects::nonNull).forEach(mMediaSources::add);
-            mMediaSources.addAll(sortedSources);
-        }
-        return mMediaSources;
-    }
-
-    /**
-     * Generates a set of all possible media services to choose from.
-     */
-    private Set<ComponentName> getComponentNames() {
-        PackageManager packageManager = mAppContext.getPackageManager();
-        Intent mediaIntent = new Intent();
-        mediaIntent.setAction(MediaBrowserService.SERVICE_INTERFACE);
-        List<ResolveInfo> mediaServices = packageManager.queryIntentServices(mediaIntent,
-                PackageManager.GET_RESOLVED_FILTER);
-
-        Set<ComponentName> components = new HashSet<>();
-        for (ResolveInfo info : mediaServices) {
-            ComponentName componentName = new ComponentName(info.serviceInfo.packageName,
-                    info.serviceInfo.name);
-            components.add(componentName);
-        }
-        return components;
-    }
-
-}
diff --git a/car-media-common/src/com/android/car/media/common/source/MediaSourcesProvider.java b/car-media-common/src/com/android/car/media/common/source/MediaSourcesProvider.java
new file mode 100644
index 0000000..7312589
--- /dev/null
+++ b/car-media-common/src/com/android/car/media/common/source/MediaSourcesProvider.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2018 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.car.media.common.source;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.service.media.MediaBrowserService;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.media.common.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Singleton that provides access to the list of all possible media sources that can be selected
+ * to be played.
+ */
+public class MediaSourcesProvider {
+
+    private static final String TAG = "MediaSources";
+
+    private static MediaSourcesProvider sInstance;
+    private final Context mAppContext;
+    @Nullable
+    private List<MediaSource> mMediaSources;
+
+    private final BroadcastReceiver mAppInstallUninstallReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            reset();
+        }
+    };
+
+    /** Returns the singleton instance. */
+    public static MediaSourcesProvider getInstance(@NonNull Context context) {
+        if (sInstance == null) {
+            sInstance = new MediaSourcesProvider(context);
+        }
+        return sInstance;
+    }
+
+    /** Returns a different instance every time (tests don't like statics) */
+    @VisibleForTesting
+    public static MediaSourcesProvider createForTesting(@NonNull Context context) {
+        return new MediaSourcesProvider(context);
+    }
+
+    @VisibleForTesting
+    void reset() {
+        mMediaSources = null;
+    }
+
+    private MediaSourcesProvider(@NonNull Context context) {
+        mAppContext = context.getApplicationContext();
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addDataScheme("package");
+        mAppContext.registerReceiver(mAppInstallUninstallReceiver, filter);
+    }
+
+    /**
+     * Returns the sorted list of available media sources. Sources listed in the array resource
+     * R.array.preferred_media_sources are included first. Other sources follow in alphabetical
+     * order.
+     */
+    public List<MediaSource> getList() {
+        if (mMediaSources == null) {
+            // Get the flattened components to display first.
+            String[] preferredFlats = mAppContext.getResources().getStringArray(
+                    R.array.preferred_media_sources);
+
+            // Make a map of components to display first (the value is the component's index).
+            HashMap<ComponentName, Integer> preferredComps = new HashMap<>(preferredFlats.length);
+            for (int i = 0; i < preferredFlats.length; i++) {
+                preferredComps.put(ComponentName.unflattenFromString(preferredFlats[i]), i);
+            }
+
+            // Prepare an array of the sources to display first (unavailable preferred components
+            // will be excluded).
+            MediaSource[] preferredSources = new MediaSource[preferredFlats.length];
+            List<MediaSource> sortedSources = getComponentNames().stream()
+                    .filter(Objects::nonNull)
+                    .map(componentName -> MediaSource.create(mAppContext, componentName))
+                    .filter(mediaSource -> {
+                        if (mediaSource == null) {
+                            Log.w(TAG, "Media source is null");
+                            return false;
+                        }
+                        ComponentName srcComp = mediaSource.getBrowseServiceComponentName();
+                        if (preferredComps.containsKey(srcComp)) {
+                            // Record the source in the preferred array...
+                            preferredSources[preferredComps.get(srcComp)] = mediaSource;
+                            // And exclude it from the alpha sort.
+                            return false;
+                        }
+                        return true;
+                    })
+                    .sorted(Comparator.comparing(
+                            mediaSource -> mediaSource.getDisplayName().toString()))
+                    .collect(Collectors.toList());
+
+            // Concatenate the non null preferred sources and the sorted ones into the result.
+            mMediaSources = new ArrayList<>(sortedSources.size() + preferredFlats.length);
+            Arrays.stream(preferredSources).filter(Objects::nonNull).forEach(mMediaSources::add);
+            mMediaSources.addAll(sortedSources);
+        }
+        return mMediaSources;
+    }
+
+    /**
+     * Generates a set of all possible media services to choose from.
+     */
+    private Set<ComponentName> getComponentNames() {
+        PackageManager packageManager = mAppContext.getPackageManager();
+        Intent mediaIntent = new Intent();
+        mediaIntent.setAction(MediaBrowserService.SERVICE_INTERFACE);
+        List<ResolveInfo> mediaServices = packageManager.queryIntentServices(mediaIntent,
+                PackageManager.GET_RESOLVED_FILTER);
+
+        Set<ComponentName> components = new HashSet<>();
+        for (ResolveInfo info : mediaServices) {
+            ComponentName componentName = new ComponentName(info.serviceInfo.packageName,
+                    info.serviceInfo.name);
+            components.add(componentName);
+        }
+        return components;
+    }
+
+}
diff --git a/car-media-common/tests/Android.mk b/car-media-common/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-media-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-media-common/tests/robotests/Android.bp b/car-media-common/tests/robotests/Android.bp
new file mode 100644
index 0000000..13e19f7
--- /dev/null
+++ b/car-media-common/tests/robotests/Android.bp
@@ -0,0 +1,37 @@
+
+
+//###########################################################
+// CarMediaCommon app just for Robolectric test target.     #
+//###########################################################
+android_app {
+    name: "CarMediaCommon",
+
+    platform_apis: true,
+
+    privileged: true,
+
+    static_libs: [
+        "car-arch-common",
+        "car-media-common",
+    ],
+}
+
+//###############################################
+// Car Media Common Robolectric test target. #
+//###############################################
+android_robolectric_test {
+    name: "CarMediaCommonRoboTests",
+
+    srcs: ["src/**/*.java"],
+
+    java_resource_dirs: ["config"],
+
+    // Include the testing libraries
+    libs: [
+        "android.car",
+        "androidx.arch.core_core-runtime",
+        "androidx.arch.core_core-common",
+    ],
+
+    instrumentation_for: "CarMediaCommon",
+}
diff --git a/car-media-common/tests/robotests/Android.mk b/car-media-common/tests/robotests/Android.mk
deleted file mode 100644
index 342f5c0..0000000
--- a/car-media-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,74 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarMediaCommon app just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarMediaCommon
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-arch-common \
-    car-media-common
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Media Common Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarMediaCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    androidx.arch.core_core-runtime \
-    androidx.arch.core_core-common \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-
-LOCAL_INSTRUMENTATION_FOR := CarMediaCommon
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Media Common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarMediaCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    CarMediaCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarMediaCommon
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-media-common/tests/robotests/AndroidManifest.xml b/car-media-common/tests/robotests/AndroidManifest.xml
index 63b3855..83a5e47 100644
--- a/car-media-common/tests/robotests/AndroidManifest.xml
+++ b/car-media-common/tests/robotests/AndroidManifest.xml
@@ -17,5 +17,4 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.car.media.common.robotests">
-
 </manifest>
diff --git a/car-media-common/tests/robotests/config/robolectric.properties b/car-media-common/tests/robotests/config/robolectric.properties
index 715d744..4c863dc 100644
--- a/car-media-common/tests/robotests/config/robolectric.properties
+++ b/car-media-common/tests/robotests/config/robolectric.properties
@@ -13,5 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-manifest=packages/apps/Car/libs/car-media-common/tests/robotests/AndroidManifest.xml
 sdk=NEWEST_SDK
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java
index 1373d4c..81f4066 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/MediaItemMetadataTest.java
@@ -23,10 +23,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MediaItemMetadataTest {
     private static final String EXTRA_METADATA = "metadata";
 
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/TestConfig.java b/car-media-common/tests/robotests/src/com/android/car/media/common/TestConfig.java
deleted file mode 100644
index 8e45ad3..0000000
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2016 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.car.media.common;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 23;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-media-common/AndroidManifest.xml";
-}
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
index 8eb6283..9d00628 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/PlaybackViewModelTest.java
@@ -39,7 +39,6 @@
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
 import com.android.car.media.common.MediaItemMetadata;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -51,13 +50,12 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class PlaybackViewModelTest {
 
     @Rule
@@ -176,7 +174,7 @@
     @Test
     public void testGetHasQueue_true() {
         List<MediaSessionCompat.QueueItem> queue =
-                Collections.singletonList(createQueueItem("title", 1));
+                Arrays.asList(createQueueItem("title1", 1), createQueueItem("title2", 2));
         CaptureObserver<Boolean> observer = new CaptureObserver<>();
         mPlaybackViewModel.hasQueue().observe(mLifecycleOwner, observer);
         observer.reset();
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java
index fc4959c..991e4f2 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/playback/ProgressLiveDataTest.java
@@ -27,7 +27,6 @@
 import com.android.car.arch.common.testing.CaptureObserver;
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -37,13 +36,11 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 
 import java.util.concurrent.TimeUnit;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ProgressLiveDataTest {
     private static final long START_TIME = 500L;
     private static final long START_PROGRESS = 1000L;
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java
index f955e47..eeccb5e 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaBrowserConnectorTest.java
@@ -24,13 +24,13 @@
 import static org.mockito.Mockito.when;
 import static org.robolectric.RuntimeEnvironment.application;
 
-import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.support.v4.media.MediaBrowserCompat;
 
+import androidx.annotation.NonNull;
+
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -42,14 +42,12 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MediaBrowserConnectorTest {
 
     @Rule
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
index b825fa1..b22bba2 100644
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourceViewModelTest.java
@@ -16,13 +16,14 @@
 
 package com.android.car.media.common.source;
 
+import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.robolectric.RuntimeEnvironment.application;
 
-import android.annotation.NonNull;
 import android.app.Application;
 import android.car.Car;
 import android.car.media.CarMediaManager;
@@ -31,12 +32,12 @@
 import android.support.v4.media.session.MediaControllerCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.car.arch.common.testing.CaptureObserver;
 import com.android.car.arch.common.testing.InstantTaskExecutorRule;
 import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -46,10 +47,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class MediaSourceViewModelTest {
 
     private static final String BROWSER_CONTROLLER_PACKAGE_NAME = "browser";
@@ -90,7 +89,8 @@
     }
 
     private void initializeViewModel() {
-        mViewModel = new MediaSourceViewModel(application, new MediaSourceViewModel.InputFactory() {
+        mViewModel = new MediaSourceViewModel(application, MEDIA_SOURCE_MODE_PLAYBACK,
+                new MediaSourceViewModel.InputFactory() {
             @Override
             public MediaBrowserConnector createMediaBrowserConnector(
                     @NonNull Application application,
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesLiveDataTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesLiveDataTest.java
deleted file mode 100644
index d9d4e82..0000000
--- a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesLiveDataTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2018 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.car.media.common.source;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.robolectric.RuntimeEnvironment.application;
-import static org.robolectric.Shadows.shadowOf;
-
-import android.annotation.NonNull;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.os.Bundle;
-import android.service.media.MediaBrowserService;
-
-import com.android.car.arch.common.testing.InstantTaskExecutorRule;
-import com.android.car.arch.common.testing.TestLifecycleOwner;
-import com.android.car.media.common.TestConfig;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowPackageManager;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class MediaSourcesLiveDataTest {
-
-    @Rule
-    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
-    @Rule
-    public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
-    @Rule
-    public final TestLifecycleOwner mLifecycleOwner = new TestLifecycleOwner();
-
-    private static final String TEST_ACTIVITY_PACKAGE_1 = "activity_package1";
-    private static final String TEST_ACTIVITY_PACKAGE_2 = "activity_package2";
-    private static final String TEST_SERVICE_PACKAGE_1 = "service_package1";
-    private static final String TEST_SERVICE_PACKAGE_2 = "service_package2";
-    private static final String TEST_SERVICE_PACKAGE_WITH_METADATA = "service_package3";
-
-    private MediaSourcesLiveData mMediaSources;
-    private Intent mActivityIntent;
-    private Intent mServiceIntent;
-
-    @Before
-    public void setUp() {
-        mMediaSources = MediaSourcesLiveData.createForTesting(application);
-
-        mActivityIntent = new Intent(Intent.ACTION_MAIN, null);
-        mActivityIntent.addCategory(Intent.CATEGORY_APP_MUSIC);
-
-        mServiceIntent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
-        ShadowPackageManager packageManager = shadowOf(application.getPackageManager());
-
-        List<ResolveInfo> activityResolveInfo = buildActivityResolveInfo();
-        List<ResolveInfo> allActivityResolveInfo = new ArrayList<>(activityResolveInfo);
-        allActivityResolveInfo.add(newActivityResolveInfo(TEST_ACTIVITY_PACKAGE_2));
-        for (ResolveInfo info : allActivityResolveInfo) {
-            PackageInfo packageInfo = new PackageInfo();
-            packageInfo.activities = new ActivityInfo[]{info.activityInfo};
-            packageInfo.packageName = info.activityInfo.packageName;
-            packageInfo.applicationInfo = info.activityInfo.applicationInfo;
-            packageManager.addPackage(packageInfo);
-        }
-        List<ResolveInfo> serviceResolveInfo = buildServiceResolveInfo();
-        List<ResolveInfo> allServiceResolveInfo = new ArrayList<>(serviceResolveInfo);
-        allServiceResolveInfo.add(newServiceResolveInfo(TEST_SERVICE_PACKAGE_2));
-        for (ResolveInfo info : allServiceResolveInfo) {
-            PackageInfo packageInfo = new PackageInfo();
-            packageInfo.services = new ServiceInfo[]{info.serviceInfo};
-            packageInfo.packageName = info.serviceInfo.packageName;
-            packageInfo.applicationInfo = info.serviceInfo.applicationInfo;
-            packageManager.addPackage(packageInfo);
-        }
-        setPackageManagerResolveInfos(activityResolveInfo, serviceResolveInfo);
-    }
-
-    @Test
-    public void testGetAppsOnActive() {
-        List<MediaSource> observedValue = mMediaSources.getList();
-        assertThat(observedValue).isNotNull();
-        assertThat(
-                observedValue.stream().map(source -> source.getPackageName())
-                        .collect(Collectors.toList()))
-                .containsExactly(TEST_SERVICE_PACKAGE_1, TEST_SERVICE_PACKAGE_WITH_METADATA);
-    }
-
-    @Test
-    public void testGetAppsOnPackageAdded() {
-        List<ResolveInfo> activityResolveInfo = buildActivityResolveInfo();
-        activityResolveInfo.add(newActivityResolveInfo(TEST_ACTIVITY_PACKAGE_2));
-        List<ResolveInfo> serviceResolveInfo = buildServiceResolveInfo();
-        serviceResolveInfo.add(newServiceResolveInfo(TEST_SERVICE_PACKAGE_2));
-        setPackageManagerResolveInfos(activityResolveInfo, serviceResolveInfo);
-
-        Intent packageAdded = new Intent(Intent.ACTION_PACKAGE_ADDED);
-        ShadowApplication.getInstance().getRegisteredReceivers().stream()
-                .filter(wrapper -> wrapper.intentFilter.hasAction(Intent.ACTION_PACKAGE_ADDED))
-                .map(wrapper -> wrapper.broadcastReceiver)
-                .forEach(broadcastReceiver -> broadcastReceiver.onReceive(application,
-                        packageAdded));
-
-        List<MediaSource> observedValue = mMediaSources.getList();
-        assertThat(observedValue).isNotNull();
-        assertThat(
-                observedValue.stream().map(source -> source.getPackageName())
-                        .collect(Collectors.toList()))
-                .containsExactly(TEST_SERVICE_PACKAGE_1, TEST_SERVICE_PACKAGE_2,
-                        TEST_SERVICE_PACKAGE_WITH_METADATA);
-    }
-
-    @Test
-    public void testGetAppsOnPackageRemoved() {
-        List<ResolveInfo> activityResolveInfo = buildActivityResolveInfo();
-        List<ResolveInfo> serviceResolveInfo = buildServiceResolveInfo();
-        serviceResolveInfo.remove(0);
-        setPackageManagerResolveInfos(activityResolveInfo, serviceResolveInfo);
-
-        Intent packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED);
-        ShadowApplication.getInstance().getRegisteredReceivers().stream()
-                .filter(wrapper -> wrapper.intentFilter.hasAction(Intent.ACTION_PACKAGE_REMOVED))
-                .map(wrapper -> wrapper.broadcastReceiver)
-                .forEach(broadcastReceiver ->
-                        broadcastReceiver.onReceive(application, packageRemoved));
-
-        List<MediaSource> observedValue = mMediaSources.getList();
-        assertThat(observedValue).isNotNull();
-        assertThat(
-                observedValue.stream().map(source -> source.getPackageName())
-                        .collect(Collectors.toList()))
-                .containsExactly(TEST_SERVICE_PACKAGE_WITH_METADATA);
-    }
-
-    @NonNull
-    private List<ResolveInfo> buildActivityResolveInfo() {
-        List<ResolveInfo> activityResolveInfo = new ArrayList<>();
-        activityResolveInfo.add(newActivityResolveInfo(TEST_ACTIVITY_PACKAGE_1));
-        return activityResolveInfo;
-    }
-
-    @NonNull
-    private List<ResolveInfo> buildServiceResolveInfo() {
-        List<ResolveInfo> serviceResolveInfo = new ArrayList<>();
-        serviceResolveInfo.add(newServiceResolveInfo(TEST_SERVICE_PACKAGE_1));
-        ResolveInfo withMetadata = newServiceResolveInfo(TEST_SERVICE_PACKAGE_WITH_METADATA);
-        withMetadata.serviceInfo.applicationInfo.metaData = new Bundle();
-        serviceResolveInfo.add(withMetadata);
-        return serviceResolveInfo;
-    }
-
-    private void setPackageManagerResolveInfos(List<ResolveInfo> activityResolveInfo,
-            List<ResolveInfo> serviceResolveInfo) {
-        ShadowPackageManager packageManager = shadowOf(application.getPackageManager());
-        packageManager.removeResolveInfosForIntent(mActivityIntent, TEST_ACTIVITY_PACKAGE_1);
-        packageManager.removeResolveInfosForIntent(mActivityIntent, TEST_ACTIVITY_PACKAGE_2);
-        packageManager.removeResolveInfosForIntent(mServiceIntent, TEST_SERVICE_PACKAGE_1);
-        packageManager.removeResolveInfosForIntent(mServiceIntent, TEST_SERVICE_PACKAGE_2);
-        packageManager.removeResolveInfosForIntent(mServiceIntent,
-                TEST_SERVICE_PACKAGE_WITH_METADATA);
-
-        packageManager.addResolveInfoForIntent(mActivityIntent, activityResolveInfo);
-
-        packageManager.addResolveInfoForIntent(mServiceIntent, serviceResolveInfo);
-        for (ResolveInfo info : serviceResolveInfo) {
-            Intent intent = new Intent(mServiceIntent);
-            intent.setPackage(info.serviceInfo.packageName);
-            packageManager.addResolveInfoForIntent(intent, info);
-        }
-        mMediaSources.reset();
-    }
-
-
-    private ResolveInfo newActivityResolveInfo(String packageName) {
-        ResolveInfo resolveInfo = new ResolveInfo();
-        ActivityInfo activityInfo = new ActivityInfo();
-        activityInfo.packageName = packageName;
-        activityInfo.name = "activity";
-        activityInfo.nonLocalizedLabel = "Activity Label " + packageName;
-        ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.packageName = packageName;
-        applicationInfo.nonLocalizedLabel = "Activity Label " + packageName;
-        activityInfo.applicationInfo = applicationInfo;
-        resolveInfo.activityInfo = activityInfo;
-        return resolveInfo;
-    }
-
-    private ResolveInfo newServiceResolveInfo(String packageName) {
-        ResolveInfo resolveInfo = new ResolveInfo();
-        ServiceInfo serviceInfo = new ServiceInfo();
-        serviceInfo.packageName = packageName;
-        serviceInfo.name = "service";
-        serviceInfo.nonLocalizedLabel = "Service Label " + packageName;
-        ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.packageName = packageName;
-        applicationInfo.nonLocalizedLabel = "Service Label " + packageName;
-        serviceInfo.applicationInfo = applicationInfo;
-        resolveInfo.serviceInfo = serviceInfo;
-        // ShadowPackageManager#removeResolveInfosForIntent requires activityInfo to be set...
-        resolveInfo.activityInfo = newActivityResolveInfo(packageName).activityInfo;
-        return resolveInfo;
-    }
-}
diff --git a/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesProviderTest.java b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesProviderTest.java
new file mode 100644
index 0000000..79dc196
--- /dev/null
+++ b/car-media-common/tests/robotests/src/com/android/car/media/common/source/MediaSourcesProviderTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2018 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.car.media.common.source;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.RuntimeEnvironment.application;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
+import android.service.media.MediaBrowserService;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.arch.common.testing.InstantTaskExecutorRule;
+import com.android.car.arch.common.testing.TestLifecycleOwner;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowPackageManager;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RunWith(RobolectricTestRunner.class)
+public class MediaSourcesProviderTest {
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Rule
+    public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
+    @Rule
+    public final TestLifecycleOwner mLifecycleOwner = new TestLifecycleOwner();
+
+    private static final String TEST_ACTIVITY_PACKAGE_1 = "activity_package1";
+    private static final String TEST_ACTIVITY_PACKAGE_2 = "activity_package2";
+    private static final String TEST_SERVICE_PACKAGE_1 = "service_package1";
+    private static final String TEST_SERVICE_PACKAGE_2 = "service_package2";
+    private static final String TEST_SERVICE_PACKAGE_WITH_METADATA = "service_package3";
+
+    private MediaSourcesProvider mMediaSources;
+    private Intent mActivityIntent;
+    private Intent mServiceIntent;
+
+    @Before
+    public void setUp() {
+        mMediaSources = MediaSourcesProvider.createForTesting(application);
+
+        mActivityIntent = new Intent(Intent.ACTION_MAIN, null);
+        mActivityIntent.addCategory(Intent.CATEGORY_APP_MUSIC);
+
+        mServiceIntent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
+        ShadowPackageManager packageManager = shadowOf(application.getPackageManager());
+
+        List<ResolveInfo> activityResolveInfo = buildActivityResolveInfo();
+        List<ResolveInfo> allActivityResolveInfo = new ArrayList<>(activityResolveInfo);
+        allActivityResolveInfo.add(newActivityResolveInfo(TEST_ACTIVITY_PACKAGE_2));
+        for (ResolveInfo info : allActivityResolveInfo) {
+            PackageInfo packageInfo = new PackageInfo();
+            packageInfo.activities = new ActivityInfo[]{info.activityInfo};
+            packageInfo.packageName = info.activityInfo.packageName;
+            packageInfo.applicationInfo = info.activityInfo.applicationInfo;
+            packageManager.addPackage(packageInfo);
+        }
+        List<ResolveInfo> serviceResolveInfo = buildServiceResolveInfo();
+        List<ResolveInfo> allServiceResolveInfo = new ArrayList<>(serviceResolveInfo);
+        allServiceResolveInfo.add(newServiceResolveInfo(TEST_SERVICE_PACKAGE_2));
+        for (ResolveInfo info : allServiceResolveInfo) {
+            PackageInfo packageInfo = new PackageInfo();
+            packageInfo.services = new ServiceInfo[]{info.serviceInfo};
+            packageInfo.packageName = info.serviceInfo.packageName;
+            packageInfo.applicationInfo = info.serviceInfo.applicationInfo;
+            packageManager.addPackage(packageInfo);
+        }
+        setPackageManagerResolveInfos(activityResolveInfo, serviceResolveInfo);
+    }
+
+    @Test
+    public void testGetAppsOnActive() {
+        List<MediaSource> observedValue = mMediaSources.getList();
+        assertThat(observedValue).isNotNull();
+        assertThat(
+                observedValue.stream().map(source -> source.getPackageName())
+                        .collect(Collectors.toList()))
+                .containsExactly(TEST_SERVICE_PACKAGE_1, TEST_SERVICE_PACKAGE_WITH_METADATA);
+    }
+
+    @Test
+    public void testGetAppsOnPackageAdded() {
+        List<ResolveInfo> activityResolveInfo = buildActivityResolveInfo();
+        activityResolveInfo.add(newActivityResolveInfo(TEST_ACTIVITY_PACKAGE_2));
+        List<ResolveInfo> serviceResolveInfo = buildServiceResolveInfo();
+        serviceResolveInfo.add(newServiceResolveInfo(TEST_SERVICE_PACKAGE_2));
+        setPackageManagerResolveInfos(activityResolveInfo, serviceResolveInfo);
+
+        Intent packageAdded = new Intent(Intent.ACTION_PACKAGE_ADDED);
+        ShadowApplication.getInstance().getRegisteredReceivers().stream()
+                .filter(wrapper -> wrapper.intentFilter.hasAction(Intent.ACTION_PACKAGE_ADDED))
+                .map(wrapper -> wrapper.broadcastReceiver)
+                .forEach(broadcastReceiver -> broadcastReceiver.onReceive(application,
+                        packageAdded));
+
+        List<MediaSource> observedValue = mMediaSources.getList();
+        assertThat(observedValue).isNotNull();
+        assertThat(
+                observedValue.stream().map(source -> source.getPackageName())
+                        .collect(Collectors.toList()))
+                .containsExactly(TEST_SERVICE_PACKAGE_1, TEST_SERVICE_PACKAGE_2,
+                        TEST_SERVICE_PACKAGE_WITH_METADATA);
+    }
+
+    @Test
+    public void testGetAppsOnPackageRemoved() {
+        List<ResolveInfo> activityResolveInfo = buildActivityResolveInfo();
+        List<ResolveInfo> serviceResolveInfo = buildServiceResolveInfo();
+        serviceResolveInfo.remove(0);
+        setPackageManagerResolveInfos(activityResolveInfo, serviceResolveInfo);
+
+        Intent packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED);
+        ShadowApplication.getInstance().getRegisteredReceivers().stream()
+                .filter(wrapper -> wrapper.intentFilter.hasAction(Intent.ACTION_PACKAGE_REMOVED))
+                .map(wrapper -> wrapper.broadcastReceiver)
+                .forEach(broadcastReceiver ->
+                        broadcastReceiver.onReceive(application, packageRemoved));
+
+        List<MediaSource> observedValue = mMediaSources.getList();
+        assertThat(observedValue).isNotNull();
+        assertThat(
+                observedValue.stream().map(source -> source.getPackageName())
+                        .collect(Collectors.toList()))
+                .containsExactly(TEST_SERVICE_PACKAGE_WITH_METADATA);
+    }
+
+    @NonNull
+    private List<ResolveInfo> buildActivityResolveInfo() {
+        List<ResolveInfo> activityResolveInfo = new ArrayList<>();
+        activityResolveInfo.add(newActivityResolveInfo(TEST_ACTIVITY_PACKAGE_1));
+        return activityResolveInfo;
+    }
+
+    @NonNull
+    private List<ResolveInfo> buildServiceResolveInfo() {
+        List<ResolveInfo> serviceResolveInfo = new ArrayList<>();
+        serviceResolveInfo.add(newServiceResolveInfo(TEST_SERVICE_PACKAGE_1));
+        ResolveInfo withMetadata = newServiceResolveInfo(TEST_SERVICE_PACKAGE_WITH_METADATA);
+        withMetadata.serviceInfo.applicationInfo.metaData = new Bundle();
+        serviceResolveInfo.add(withMetadata);
+        return serviceResolveInfo;
+    }
+
+    private void setPackageManagerResolveInfos(List<ResolveInfo> activityResolveInfo,
+            List<ResolveInfo> serviceResolveInfo) {
+        ShadowPackageManager packageManager = shadowOf(application.getPackageManager());
+        packageManager.removeResolveInfosForIntent(mActivityIntent, TEST_ACTIVITY_PACKAGE_1);
+        packageManager.removeResolveInfosForIntent(mActivityIntent, TEST_ACTIVITY_PACKAGE_2);
+        packageManager.removeResolveInfosForIntent(mServiceIntent, TEST_SERVICE_PACKAGE_1);
+        packageManager.removeResolveInfosForIntent(mServiceIntent, TEST_SERVICE_PACKAGE_2);
+        packageManager.removeResolveInfosForIntent(mServiceIntent,
+                TEST_SERVICE_PACKAGE_WITH_METADATA);
+
+        packageManager.addResolveInfoForIntent(mActivityIntent, activityResolveInfo);
+
+        packageManager.addResolveInfoForIntent(mServiceIntent, serviceResolveInfo);
+        for (ResolveInfo info : serviceResolveInfo) {
+            Intent intent = new Intent(mServiceIntent);
+            intent.setPackage(info.serviceInfo.packageName);
+            packageManager.addResolveInfoForIntent(intent, info);
+        }
+        mMediaSources.reset();
+    }
+
+
+    private ResolveInfo newActivityResolveInfo(String packageName) {
+        ResolveInfo resolveInfo = new ResolveInfo();
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = packageName;
+        activityInfo.name = "activity";
+        activityInfo.nonLocalizedLabel = "Activity Label " + packageName;
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.packageName = packageName;
+        applicationInfo.nonLocalizedLabel = "Activity Label " + packageName;
+        activityInfo.applicationInfo = applicationInfo;
+        resolveInfo.activityInfo = activityInfo;
+        return resolveInfo;
+    }
+
+    private ResolveInfo newServiceResolveInfo(String packageName) {
+        ResolveInfo resolveInfo = new ResolveInfo();
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.packageName = packageName;
+        serviceInfo.name = "service";
+        serviceInfo.nonLocalizedLabel = "Service Label " + packageName;
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.packageName = packageName;
+        applicationInfo.nonLocalizedLabel = "Service Label " + packageName;
+        serviceInfo.applicationInfo = applicationInfo;
+        resolveInfo.serviceInfo = serviceInfo;
+        // ShadowPackageManager#removeResolveInfosForIntent requires activityInfo to be set...
+        resolveInfo.activityInfo = newActivityResolveInfo(packageName).activityInfo;
+        return resolveInfo;
+    }
+}
diff --git a/car-messenger-common/Android.bp b/car-messenger-common/Android.bp
index da0d075..6c7a82f 100644
--- a/car-messenger-common/Android.bp
+++ b/car-messenger-common/Android.bp
@@ -19,21 +19,21 @@
 
     srcs: ["src/**/*.java"],
 
-    manifest: "AndroidManifest.xml",
-
     optimize: {
         enabled: false,
     },
 
-    min_sdk_version: "29",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
 
     libs: ["android.car-system-stubs",],
 
     resource_dirs: ["res"],
 
     static_libs: [
-        "car-apps-common-bp",
+        "car-apps-common",
         "car-messenger-protos",
+        "car-telephony-common",
         "connected-device-protos",
         "libphonenumber",
     ],
diff --git a/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java b/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java
index 6397a47..d5610a2 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/BaseNotificationDelegate.java
@@ -17,17 +17,22 @@
 package com.android.car.messenger.common;
 
 import android.app.Notification;
-import android.app.Notification.Action;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.Person;
 import android.app.RemoteInput;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
 
 import androidx.annotation.Nullable;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationCompat.Action;
+import androidx.core.app.Person;
+import androidx.core.graphics.drawable.IconCompat;
+
+import com.android.car.telephony.common.TelecomUtils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -71,14 +76,14 @@
             "com.android.car.messenger.common.REMOTE_INPUT_KEY";
 
     protected final Context mContext;
-    protected final NotificationManager mNotificationManager;
+    protected NotificationManager mNotificationManager;
     protected final boolean mUseLetterTile;
 
     /**
      * Maps a conversation's Notification Metadata to the conversation's unique key.
      * The extending class should always keep this map updated with the latest new/updated
      * notification information before calling {@link BaseNotificationDelegate#postNotification(
-     * ConversationKey, ConversationNotificationInfo, String, Bitmap)}.
+     * ConversationKey, ConversationNotificationInfo, String)}.
      **/
     protected final Map<ConversationKey, ConversationNotificationInfo> mNotificationInfos =
             new HashMap<>();
@@ -87,14 +92,14 @@
      * Maps a conversation's Notification Builder to the conversation's unique key. When the
      * conversation gets updated, this builder should be retrieved, updated, and reposted.
      **/
-    private final Map<ConversationKey, Notification.Builder> mNotificationBuilders =
+    private final Map<ConversationKey, NotificationCompat.Builder> mNotificationBuilders =
             new HashMap<>();
 
     /**
      * Maps a message's metadata with the message's unique key.
      * The extending class should always keep this map updated with the latest message information
      * before calling {@link BaseNotificationDelegate#postNotification(
-     * ConversationKey, ConversationNotificationInfo, String, Bitmap)}.
+     * ConversationKey, ConversationNotificationInfo, String)}.
      **/
     protected final Map<MessageKey, Message> mMessages = new HashMap<>();
 
@@ -184,7 +189,7 @@
             @Nullable Bitmap avatarIcon) {
         boolean newNotification = !mNotificationBuilders.containsKey(conversationKey);
 
-        Notification.Builder builder = newNotification ? new Notification.Builder(
+        NotificationCompat.Builder builder = newNotification ? new NotificationCompat.Builder(
                 mContext, channelId) : mNotificationBuilders.get(
                 conversationKey);
         builder.setChannelId(channelId);
@@ -198,9 +203,11 @@
         if (avatarIcon != null) {
             builder.setLargeIcon(avatarIcon);
         } else if (mUseLetterTile) {
-            builder.setLargeIcon(Utils.createLetterTile(mContext,
+            BitmapDrawable drawable = (BitmapDrawable) TelecomUtils.createLetterTile(mContext,
                     Utils.getInitials(lastMessage.getSenderName(), ""),
-                    lastMessage.getSenderName(), mBitmapSize, mCornerRadiusPercent));
+                    lastMessage.getSenderName(), mBitmapSize, mCornerRadiusPercent)
+                    .loadDrawable(mContext);
+            builder.setLargeIcon(drawable.getBitmap());
         }
         // Else, no avatar icon will be shown.
 
@@ -213,7 +220,7 @@
         Person user = new Person.Builder()
                 .setName(userName)
                 .build();
-        Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(
+        NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(
                 user);
         Person sender = new Person.Builder()
                 .setName(lastMessage.getSenderName())
@@ -233,14 +240,15 @@
         if (notificationInfo.isGroupConvo()) {
             messagingStyle.setConversationTitle(Utils.constructGroupConversationHeader(
                     lastMessage.getSenderName(), notificationInfo.getConvoTitle(),
-                    mContext.getString(R.string.group_conversation_title_separator)));
+                    mContext.getString(R.string.group_conversation_title_separator)
+            ));
         }
 
         // We are creating this notification for the first time.
         if (newNotification) {
             builder.setCategory(Notification.CATEGORY_MESSAGE);
             if (notificationInfo.getAppIcon() != null) {
-                builder.setSmallIcon(notificationInfo.getAppIcon());
+                builder.setSmallIcon(IconCompat.createFromIcon(notificationInfo.getAppIcon()));
             } else {
                 builder.setSmallIcon(R.drawable.ic_message);
             }
@@ -281,7 +289,7 @@
             int notificationId) {
         final int icon = android.R.drawable.ic_media_play;
 
-        final List<Notification.Action> actionList = new ArrayList<>();
+        final List<NotificationCompat.Action> actionList = new ArrayList<>();
 
         // Reply action
         if (shouldAddReplyAction(conversationKey.getDeviceId())) {
@@ -289,9 +297,14 @@
             PendingIntent replyIntent = createServiceIntent(conversationKey, notificationId,
                     ACTION_REPLY);
             actionList.add(
-                    new Notification.Action.Builder(icon, replyString, replyIntent)
-                            .setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY)
-                            .addRemoteInput(new RemoteInput.Builder(EXTRA_REMOTE_INPUT_KEY).build())
+                    new NotificationCompat.Action.Builder(icon, replyString, replyIntent)
+                            .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY)
+                            .setShowsUserInterface(false)
+                            .addRemoteInput(
+                                    new androidx.core.app.RemoteInput.Builder(
+                                            EXTRA_REMOTE_INPUT_KEY)
+                                            .build()
+                            )
                             .build()
             );
         }
@@ -301,8 +314,9 @@
         PendingIntent markAsReadIntent = createServiceIntent(conversationKey, notificationId,
                 ACTION_MARK_AS_READ);
         actionList.add(
-                new Notification.Action.Builder(icon, markAsRead, markAsReadIntent)
-                        .setSemanticAction(Notification.Action.SEMANTIC_ACTION_MARK_AS_READ)
+                new NotificationCompat.Action.Builder(icon, markAsRead, markAsReadIntent)
+                        .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ)
+                        .setShowsUserInterface(false)
                         .build()
         );
 
diff --git a/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java b/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java
index 1b9b7b9..93a774a 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/ConversationKey.java
@@ -16,6 +16,8 @@
 
 package com.android.car.messenger.common;
 
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -29,6 +31,18 @@
         super(deviceId, key);
     }
 
+    /** Creates a ConversationKey from a BluetoothMapClient intent. **/
+    public static ConversationKey createConversationKey(Intent intent) {
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+        String senderUri = Utils.getSenderUri(intent);
+        String senderName = Utils.getSenderName(intent);
+        String subKey = senderName + "/" + senderUri;
+        if (Utils.isGroupConversation(intent)) {
+            subKey = Utils.getInclusiveRecipientsUrisList(intent).toString();
+        }
+        return new ConversationKey(device.getAddress(), subKey);
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java b/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java
index accebf1..d563d12 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/ConversationNotificationInfo.java
@@ -18,6 +18,8 @@
 
 import static com.android.car.apps.common.util.SafeLog.logw;
 
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.util.Log;
 
@@ -30,6 +32,7 @@
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.PhoneToCarMessage;
 
 import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Represents a conversation notification's metadata that is shared between the conversation's
@@ -44,7 +47,7 @@
     private final String mDeviceName;
     private final String mDeviceId;
     // This is always the sender name for SMS Messages from Bluetooth MAP.
-    private final String mConvoTitle;
+    private String mConvoTitle;
     private final boolean mIsGroupConvo;
 
     /** Only used for {@link NotificationMsg} conversations. **/
@@ -57,6 +60,9 @@
     private final String mUserDisplayName;
     @Nullable
     private final Icon mAppIcon;
+    /** Uris of all members in a MMS Group Conversation. **/
+    @Nullable
+    private final List<String> mCcRecipientsUris;
 
     public final LinkedList<MessageKey> mMessageKeys = new LinkedList<>();
 
@@ -83,9 +89,7 @@
         Icon appIcon = null;
         if (conversation.getAppIcon() != null) {
             byte[] iconBytes = conversation.getAppIcon().toByteArray();
-            if (iconBytes != null && iconBytes.length > 0) {
-                appIcon = Icon.createWithData(iconBytes, 0, iconBytes.length);
-            }
+            appIcon = Icon.createWithData(iconBytes, 0, iconBytes.length);
         }
 
         return new ConversationNotificationInfo(deviceName, deviceId,
@@ -94,14 +98,27 @@
                 conversation.getMessagingAppDisplayName(),
                 conversation.getMessagingAppPackageName(),
                 messagingStyle.getUserDisplayName(),
-                appIcon);
+                appIcon,
+                /* ccUris= */null);
 
     }
+    /** Creates a ConversationNotificationInfo for a BluetoothMapClient intent. **/
+    public static ConversationNotificationInfo createConversationNotificationInfo(Intent intent,
+            String conversationTitle, String appPackageName, @Nullable Icon appIcon) {
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+        return new ConversationNotificationInfo(device.getName(), device.getAddress(),
+                conversationTitle, Utils.isGroupConversation(intent), /* notificationKey */ null,
+                /* appDisplayName */ null, appPackageName, /* userDisplayName */ null,
+                appIcon,
+                Utils.getInclusiveRecipientsUrisList(intent));
+    }
 
     private ConversationNotificationInfo(@Nullable String deviceName, String deviceId,
             String convoTitle, boolean isGroupConvo, @Nullable String notificationKey,
             @Nullable String appDisplayName, String appPackageName,
-            @Nullable String userDisplayName, @Nullable Icon appIcon) {
+            @Nullable String userDisplayName, @Nullable Icon appIcon,
+            @Nullable List<String> ccUris) {
         boolean missingDeviceId = (deviceId == null);
         boolean missingTitle = (convoTitle == null);
         if (missingDeviceId || missingTitle) {
@@ -123,6 +140,7 @@
         this.mAppPackageName = appPackageName;
         this.mUserDisplayName = userDisplayName;
         this.mAppIcon = appIcon;
+        this.mCcRecipientsUris = ccUris;
     }
 
     /** Returns the id that should be used for this object's {@link android.app.Notification} **/
@@ -148,6 +166,11 @@
         return mConvoTitle;
     }
 
+    /** Update the conversation title. **/
+    public void setConvoTitle(String newTitle) {
+        mConvoTitle = newTitle;
+    }
+
     /** Returns {@code true} if this message is in a group conversation **/
     public boolean isGroupConvo() {
         return mIsGroupConvo;
@@ -197,4 +220,13 @@
     public MessageKey getLastMessageKey() {
         return mMessageKeys.getLast();
     }
+
+    /**
+     * Returns the sorted URIs of all the participants of a MMS/SMS/RCS conversation. Returns
+     * {@code null} if this is based on a {@link NotificationMsg} conversation.
+     */
+    @Nullable
+    public List<String> getCcRecipientsUris() {
+        return mCcRecipientsUris;
+    }
 }
diff --git a/car-messenger-common/src/com/android/car/messenger/common/Message.java b/car-messenger-common/src/com/android/car/messenger/common/Message.java
index 462e22d..8e016dd 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/Message.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/Message.java
@@ -17,7 +17,12 @@
 package com.android.car.messenger.common;
 
 import static com.android.car.apps.common.util.SafeLog.logw;
+import static com.android.car.messenger.common.Utils.BMC_EXTRA_MESSAGE_HANDLE;
+import static com.android.car.messenger.common.Utils.BMC_EXTRA_MESSAGE_READ_STATUS;
+import static com.android.car.messenger.common.Utils.BMC_EXTRA_MESSAGE_TIMESTAMP;
 
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
 import android.util.Log;
 
 import androidx.annotation.Nullable;
@@ -92,6 +97,38 @@
                 senderKey);
     }
 
+    /**
+     * Creates a Message based on BluetoothMapClient intent. Returns {@code null} if the
+     * intent is missing required fields.
+     **/
+    public static Message parseFromIntent(Intent intent) {
+        if (!Utils.isValidMapClientIntent(intent)) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                throw new IllegalArgumentException(
+                        "BluetoothMapClient intent is missing required fields");
+            } else {
+                logw(TAG, "BluetoothMapClient intent is missing required fields");
+                return null;
+            }
+        }
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+        String senderUri = Utils.getSenderUri(intent);
+
+        return new Message(
+                Utils.getSenderName(intent),
+                device.getAddress(),
+                intent.getStringExtra(android.content.Intent.EXTRA_TEXT),
+                intent.getLongExtra(BMC_EXTRA_MESSAGE_TIMESTAMP,
+                        System.currentTimeMillis()),
+                intent.getBooleanExtra(BMC_EXTRA_MESSAGE_READ_STATUS,
+                        false),
+                intent.getStringExtra(BMC_EXTRA_MESSAGE_HANDLE),
+                MessageType.BLUETOOTH_MAP_MESSAGE,
+                senderUri,
+                SenderKey.createSenderKey(intent)
+        );
+    }
+
     private Message(String senderName, String deviceId, String messageText, long receivedTime,
             boolean isReadOnPhone, String handle, MessageType messageType,
             @Nullable String senderContactUri, SenderKey senderKey) {
diff --git a/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java b/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java
index 5432563..ddc8fac 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/ProjectionStateListener.java
@@ -37,29 +37,38 @@
  * {@link ProjectionStatus} listener that exposes APIs to detect whether a projection application
  * is active.
  */
-public class ProjectionStateListener implements CarProjectionManager.ProjectionStatusListener{
+public class ProjectionStateListener {
     private static final String TAG = "CMC.ProjectionStateHandler";
     static final String PROJECTION_STATUS_EXTRA_DEVICE_STATE =
             "android.car.projection.DEVICE_STATE";
 
-    private CarProjectionManager mCarProjectionManager;
+    private CarProjectionManager mCarProjectionManager = null;
+    private final CarProjectionManager.ProjectionStatusListener mListener =
+            (state, packageName, details) -> {
+                mProjectionState = state;
+                mProjectionDetails = details;
+            };
     private Car mCar;
 
     private int mProjectionState = ProjectionStatus.PROJECTION_STATE_INACTIVE;
     private List<ProjectionStatus> mProjectionDetails = Collections.emptyList();
 
     public ProjectionStateListener(Context context) {
-        mCar = Car.createCar(context);
-        mCarProjectionManager = (CarProjectionManager) mCar.getCarManager(Car.PROJECTION_SERVICE);
-        if (mCarProjectionManager != null) {
-            mCarProjectionManager.registerProjectionStatusListener(this);
-        }
+        Car.createCar(context, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+                (car, ready) -> {
+                    mCar = car;
+                    mCarProjectionManager = (CarProjectionManager) mCar.getCarManager(
+                            Car.PROJECTION_SERVICE);
+                    if (mCarProjectionManager != null) {
+                        mCarProjectionManager.registerProjectionStatusListener(mListener);
+                    }
+                });
     }
 
     /** Unregisters the listener. Should be called when the caller's lifecycle is ending. **/
     public void destroy() {
         if (mCarProjectionManager != null) {
-            mCarProjectionManager.unregisterProjectionStatusListener(this);
+            mCarProjectionManager.unregisterProjectionStatusListener(mListener);
         }
         if (mCar != null) {
             mCar.disconnect();
@@ -69,14 +78,6 @@
         mProjectionDetails = Collections.emptyList();
     }
 
-
-    @Override
-    public void onProjectionStatusChanged(int state, String packageName,
-            List<ProjectionStatus> details) {
-        mProjectionState = state;
-        mProjectionDetails = details;
-    }
-
     /**
      * Returns {@code true} if the input device currently has a projection app running in the
      * foreground.
diff --git a/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java b/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java
index bf8222c..8e220b4 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/SenderKey.java
@@ -16,6 +16,9 @@
 
 package com.android.car.messenger.common;
 
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg;
 
 /**
@@ -23,6 +26,21 @@
  * unique Key.
  */
 public class SenderKey extends CompositeKey {
+    /** Creates a senderkey for SMS, MMS, and {@link NotificationMsg}. **/
+    private SenderKey(String deviceId, String senderName, String keyMetadata) {
+        super(deviceId, senderName + "/" + keyMetadata);
+    }
+
+    /**
+     * Returns the SenderKey for the BluetoothMapClient intent. This should be unique
+     * for each contact per device.
+     */
+    public static SenderKey createSenderKey(Intent intent) {
+        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+        return new SenderKey(device.getAddress(), Utils.getSenderName(intent),
+                Utils.getSenderUri(intent));
+    }
+
     /**
      * Returns the SenderKey based on a {@link NotificationMsg} DAO. This key is only
      * guaranteed to be unique for a 1-1 conversation. If the ConversationKey is for a
@@ -33,9 +51,4 @@
             NotificationMsg.Person person) {
         return new SenderKey(convoKey.getDeviceId(), person.getName(), convoKey.getSubKey());
     }
-
-    /** Creates a senderkey for SMS, MMS, and {@link NotificationMsg}. **/
-    private SenderKey(String deviceId, String senderName, String keyMetadata) {
-        super(deviceId, senderName + "/" + keyMetadata);
-    }
 }
diff --git a/car-messenger-common/src/com/android/car/messenger/common/Utils.java b/car-messenger-common/src/com/android/car/messenger/common/Utils.java
index 99ec52f..c52cc56 100644
--- a/car-messenger-common/src/com/android/car/messenger/common/Utils.java
+++ b/car-messenger-common/src/com/android/car/messenger/common/Utils.java
@@ -18,7 +18,9 @@
 
 import static com.android.car.apps.common.util.SafeLog.logw;
 
+import android.bluetooth.BluetoothDevice;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.text.BidiFormatter;
@@ -31,6 +33,7 @@
 
 import com.android.car.apps.common.LetterTileDrawable;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg;
+import com.android.car.messenger.NotificationMsgProto.NotificationMsg.AvatarIconSync;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.ConversationNotification;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.MessagingStyle;
 import com.android.car.messenger.NotificationMsgProto.NotificationMsg.MessagingStyleMessage;
@@ -40,6 +43,8 @@
 import com.google.i18n.phonenumbers.PhoneNumberUtil;
 import com.google.i18n.phonenumbers.Phonenumber;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
@@ -54,6 +59,24 @@
      */
     private static final int MAX_SUB_MESSAGE_LENGTH = 5;
 
+    /** The Regex format of a telephone number in a BluetoothMapClient contact URI. **/
+    private static final String MAP_CLIENT_URI_REGEX = "tel:(.+)";
+
+    /** The starting substring index for a string formatted with the MAP_CLIENT_URI_REGEX above. **/
+    private static final int MAP_CLIENT_URI_PHONE_NUMBER_SUBSTRING_INDEX = 4;
+
+    // TODO (150711637): Reference BluetoothMapClient Extras once BluetoothMapClient is SystemApi.
+    protected static final String BMC_EXTRA_MESSAGE_HANDLE =
+            "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE";
+    protected static final String BMC_EXTRA_SENDER_CONTACT_URI =
+            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI";
+    protected static final String BMC_EXTRA_SENDER_CONTACT_NAME =
+            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
+    protected static final String BMC_EXTRA_MESSAGE_TIMESTAMP =
+            "android.bluetooth.mapmce.profile.extra.MESSAGE_TIMESTAMP";
+    protected static final String BMC_EXTRA_MESSAGE_READ_STATUS =
+            "android.bluetooth.mapmce.profile.extra.MESSAGE_READ_STATUS";
+
     /** Gets the latest message for a {@link NotificationMsg} Conversation. **/
     public static MessagingStyleMessage getLatestMessage(
             ConversationNotification notification) {
@@ -163,9 +186,9 @@
     }
 
     /**
-     * Ensure the {@link NotificationMsg.AvatarIconSync} object has all the required fields.
+     * Ensure the {@link AvatarIconSync} object has all the required fields.
      **/
-    public static boolean isValidAvatarIconSync(NotificationMsg.AvatarIconSync iconSync) {
+    public static boolean isValidAvatarIconSync(AvatarIconSync iconSync) {
         if (iconSync == null) {
             logw(TAG, "AvatarIconSync is null");
             return false;
@@ -183,6 +206,29 @@
     }
 
     /**
+     * Ensure the BluetoothMapClient intent has all the required fields.
+     **/
+    public static boolean isValidMapClientIntent(Intent intent) {
+        if (intent == null) {
+            logw(TAG, "BluetoothMapClient intent is null");
+            return false;
+        } else if (intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: device");
+            return false;
+        } else if (intent.getStringExtra(BMC_EXTRA_MESSAGE_HANDLE) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: senderName");
+            return false;
+        } else if (intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_NAME) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: handle");
+            return false;
+        } else if (intent.getStringExtra(android.content.Intent.EXTRA_TEXT) == null) {
+            logw(TAG, "BluetoothMapClient intent is missing required field: messageText");
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Creates a Letter Tile Icon that will display the given initials. If the initials are null,
      * then an avatar anonymous icon will be drawn.
      **/
@@ -236,6 +282,11 @@
         return letterTileDrawable;
     }
 
+    /** Returns whether the BluetoothMapClient intent represents a group conversation. **/
+    public static boolean isGroupConversation(Intent intent) {
+        return (intent.getStringArrayExtra(Intent.EXTRA_CC) != null
+                && intent.getStringArrayExtra(Intent.EXTRA_CC).length > 1);
+    }
 
     /**
      * Returns the initials based on the name and nameAlt.
@@ -257,6 +308,45 @@
         return initials.toString();
     }
 
+    /** Returns the list of sender uri for a BluetoothMapClient intent. **/
+    public static String getSenderUri(Intent intent) {
+        return intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_URI);
+    }
+
+    /** Returns the sender name for a BluetoothMapClient intent. **/
+    public static String getSenderName(Intent intent) {
+        return intent.getStringExtra(BMC_EXTRA_SENDER_CONTACT_NAME);
+    }
+
+    /** Returns the list of recipient uris for a BluetoothMapClient intent. **/
+    public static List<String> getInclusiveRecipientsUrisList(Intent intent) {
+        List<String> ccUris = new ArrayList<>();
+        String uri = getSenderUri(intent);
+        if (isGroupConversation(intent)) {
+            ccUris.addAll(Arrays.asList(intent.getStringArrayExtra(Intent.EXTRA_CC)));
+        }
+        if (!ccUris.contains(uri)) {
+            ccUris.add(uri);
+        }
+        // TODO (b/169183358): remove sorting.
+        Collections.sort(ccUris);
+
+        return ccUris;
+    }
+
+    /**
+     * Extracts the phone number from the BluetoothMapClient contact Uri.
+     **/
+    @Nullable
+    public static String getPhoneNumberFromMapClient(@Nullable String senderContactUri) {
+        if (senderContactUri == null || !senderContactUri.matches(MAP_CLIENT_URI_REGEX)) {
+            logw(TAG, " contactUri is malformed! " + senderContactUri);
+            return null;
+        }
+
+        return senderContactUri.substring(MAP_CLIENT_URI_PHONE_NUMBER_SUBSTRING_INDEX);
+    }
+
     /**
      * Creates a Header for a group conversation, where the senderName and groupName are both shown,
      * separated by a delimiter.
@@ -283,9 +373,9 @@
     public static String constructGroupConversationHeader(String senderName, String groupName,
             String delimiter, BidiFormatter bidiFormatter) {
         String formattedSenderName = bidiFormatter.unicodeWrap(senderName,
-                TextDirectionHeuristics.FIRSTSTRONG_LTR);
+                TextDirectionHeuristics.FIRSTSTRONG_LTR, /* isolate= */ true);
         String formattedGroupName = bidiFormatter.unicodeWrap(groupName,
-                TextDirectionHeuristics.LOCALE);
+                TextDirectionHeuristics.FIRSTSTRONG_LTR, /* isolate= */ true);
         String title = String.join(delimiter, formattedSenderName, formattedGroupName);
         return bidiFormatter.unicodeWrap(title, TextDirectionHeuristics.LOCALE);
     }
@@ -372,4 +462,5 @@
                     }
                 }
             };
+
 }
diff --git a/car-messenger-common/tests/unit/Android.bp b/car-messenger-common/tests/unit/Android.bp
index af73ac8..c5d29fa 100644
--- a/car-messenger-common/tests/unit/Android.bp
+++ b/car-messenger-common/tests/unit/Android.bp
@@ -35,5 +35,5 @@
         "truth-prebuilt",
     ],
 
-    min_sdk_version: "29",
+    platform_apis: true,
 }
\ No newline at end of file
diff --git a/car-messenger-common/tests/unit/src/com.android.car.messenger.common/UtilsTest.java b/car-messenger-common/tests/unit/src/com.android.car.messenger.common/UtilsTest.java
index acdffbd..c64703a 100644
--- a/car-messenger-common/tests/unit/src/com.android.car.messenger.common/UtilsTest.java
+++ b/car-messenger-common/tests/unit/src/com.android.car.messenger.common/UtilsTest.java
@@ -200,4 +200,17 @@
 
         assertThat(actual).isEqualTo(expected);
     }
+
+    @Test
+    public void testTitleConstructorRtl_withTrailingPunctuation() {
+        String actual = Utils.constructGroupConversationHeader("Christopher",
+                "Abcd!!!", TITLE_DELIMITER, /* isRtl */
+                RTL_FORMATTER).trim();
+
+        String expected =
+                "\u200F\u202A\u200F\u202AChristopher\u202C\u200F : \u200F\u202AAbcd!!!"
+                        + "\u202C\u200F\u202C\u200F";
+
+        assertThat(actual).isEqualTo(expected);
+    }
 }
diff --git a/car-settings-lib/Android.mk b/car-settings-lib/Android.mk
deleted file mode 100644
index 9cddc18..0000000
--- a/car-settings-lib/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-settings-lib
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    androidx.annotation_annotation \
-    androidx.loader_loader
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_MIN_SDK_VERSION := 24
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Use the following include to make our test apk.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/car-settings-lib/AndroidManifest.xml b/car-settings-lib/AndroidManifest.xml
deleted file mode 100644
index 5c2e6c9..0000000
--- a/car-settings-lib/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2018 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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.settingslib">
-    <uses-sdk android:minSdkVersion="24"/>
-    <application />
-</manifest>
\ No newline at end of file
diff --git a/car-settings-lib/OWNERS b/car-settings-lib/OWNERS
deleted file mode 100644
index e8ed8af..0000000
--- a/car-settings-lib/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# People who can approve changes for submission.
-davidln@google.com
-rogerxue@google.com
-roshanagrawal@google.com
diff --git a/car-settings-lib/README.txt b/car-settings-lib/README.txt
deleted file mode 100644
index 8dcdb8a..0000000
--- a/car-settings-lib/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Library Project for Car settings.
-Intended for sharing related code between Car Settings and CarSetUpWizard.
\ No newline at end of file
diff --git a/car-settings-lib/res/values-af/strings.xml b/car-settings-lib/res/values-af/strings.xml
deleted file mode 100644
index 38a0e1b..0000000
--- a/car-settings-lib/res/values-af/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Voorgestel"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle tale"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Veld kan nie leeg wees nie."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Ingevoerde gebruikernaam is ongeldig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-am/strings.xml b/car-settings-lib/res/values-am/strings.xml
deleted file mode 100644
index 7aec3e0..0000000
--- a/car-settings-lib/res/values-am/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"የተጠቆሙ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ሁሉም ቋንቋዎች"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"መስክ ባዶ መሆን አይችልም።"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"የገባው ተጠቃሚ ስም የማይሠራ ነው።"</string>
-</resources>
diff --git a/car-settings-lib/res/values-ar/strings.xml b/car-settings-lib/res/values-ar/strings.xml
deleted file mode 100644
index 2fb7894..0000000
--- a/car-settings-lib/res/values-ar/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"اللغات المقترحة"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"جميع اللغات"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"يجب عدم ترك الحقل فارغًا."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"اسم المستخدم المُدخل غير صالح."</string>
-</resources>
diff --git a/car-settings-lib/res/values-as/strings.xml b/car-settings-lib/res/values-as/strings.xml
deleted file mode 100644
index 747e8ab..0000000
--- a/car-settings-lib/res/values-as/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"পৰামৰ্শ দিয়া ভাষা"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"সকলো ভাষা"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"এই খালী ঠাই পূৰ নকৰাকৈ এৰিব নোৱাৰি।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"আপুনি দিয়া ব্য়ৱহাৰকাৰীৰ নাম মান্য় নহয়।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-az/strings.xml b/car-settings-lib/res/values-az/strings.xml
deleted file mode 100644
index 29f7cfb..0000000
--- a/car-settings-lib/res/values-az/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Təklif edilmiş"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Bütün dillər"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Sahə boş ola bilməz."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Daxil edilən istifadəçi adı yanlışdır."</string>
-</resources>
diff --git a/car-settings-lib/res/values-b+sr+Latn/strings.xml b/car-settings-lib/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index c9450b1..0000000
--- a/car-settings-lib/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predloženi"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Svi jezici"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne sme da bude prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Korisničko ime koje ste uneli je nevažeće."</string>
-</resources>
diff --git a/car-settings-lib/res/values-be/strings.xml b/car-settings-lib/res/values-be/strings.xml
deleted file mode 100644
index 0a55864..0000000
--- a/car-settings-lib/res/values-be/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Прапанавана"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Усе мовы"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поле не можа быць пустым."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Уведзена несапраўднае імя карыстальніка"</string>
-</resources>
diff --git a/car-settings-lib/res/values-bg/strings.xml b/car-settings-lib/res/values-bg/strings.xml
deleted file mode 100644
index 7427987..0000000
--- a/car-settings-lib/res/values-bg/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Предложени"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Всички езици"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Полето трябва да се попълни."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Въведеното потребителско име е невалидно."</string>
-</resources>
diff --git a/car-settings-lib/res/values-bn/strings.xml b/car-settings-lib/res/values-bn/strings.xml
deleted file mode 100644
index 2023f4f..0000000
--- a/car-settings-lib/res/values-bn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"প্রস্তাবিত"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"সমস্ত ভাষা"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ক্ষেত্র খালি রাখা যাবে না।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"প্রদান করা ব্যবহারকারীর নামটি সঠিক নয়।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-bs/strings.xml b/car-settings-lib/res/values-bs/strings.xml
deleted file mode 100644
index adf86c9..0000000
--- a/car-settings-lib/res/values-bs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predloženo"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Svi jezici"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne može biti prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Korisničko ime koje ste unijeli je nevažeće."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ca/strings.xml b/car-settings-lib/res/values-ca/strings.xml
deleted file mode 100644
index ee2b958..0000000
--- a/car-settings-lib/res/values-ca/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggerits"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tots els idiomes"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"El camp no pot estar en blanc."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"El nom d\'usuari que has introduït no és vàlid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-cs/strings.xml b/car-settings-lib/res/values-cs/strings.xml
deleted file mode 100644
index fca045b..0000000
--- a/car-settings-lib/res/values-cs/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Navrženo"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Všechny jazyky"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Pole nesmí být prázdné."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Zadané uživatelské jméno není platné."</string>
-</resources>
diff --git a/car-settings-lib/res/values-da/strings.xml b/car-settings-lib/res/values-da/strings.xml
deleted file mode 100644
index 2a585cb..0000000
--- a/car-settings-lib/res/values-da/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Foreslået"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle sprog"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Feltet må ikke være tomt."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Det brugernavn, du har angivet, er ugyldigt."</string>
-</resources>
diff --git a/car-settings-lib/res/values-de/strings.xml b/car-settings-lib/res/values-de/strings.xml
deleted file mode 100644
index a138ce7..0000000
--- a/car-settings-lib/res/values-de/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Vorgeschlagen"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle Sprachen"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Das Feld darf nicht leer sein."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Der eingegebene Nutzername ist ungültig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-el/strings.xml b/car-settings-lib/res/values-el/strings.xml
deleted file mode 100644
index 2496924..0000000
--- a/car-settings-lib/res/values-el/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Προτεινόμενες"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Όλες οι γλώσσες"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Το πεδίο δεν μπορεί να παραμείνει κενό."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Το όνομα χρήστη που καταχωρίστηκε είναι μη έγκυρο."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rAU/strings.xml b/car-settings-lib/res/values-en-rAU/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rCA/strings.xml b/car-settings-lib/res/values-en-rCA/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rGB/strings.xml b/car-settings-lib/res/values-en-rGB/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rIN/strings.xml b/car-settings-lib/res/values-en-rIN/strings.xml
deleted file mode 100644
index 96a64e0..0000000
--- a/car-settings-lib/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggested"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"All languages"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Field can\'t be blank."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Username entered is invalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-en-rXC/strings.xml b/car-settings-lib/res/values-en-rXC/strings.xml
deleted file mode 100644
index 80192d2..0000000
--- a/car-settings-lib/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎Suggested‎‏‎‎‏‎"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‎All languages‎‏‎‎‏‎"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎Field can’t be blank.‎‏‎‎‏‎"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎Username entered is invalid.‎‏‎‎‏‎"</string>
-</resources>
diff --git a/car-settings-lib/res/values-es-rUS/strings.xml b/car-settings-lib/res/values-es-rUS/strings.xml
deleted file mode 100644
index 92eff9f..0000000
--- a/car-settings-lib/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerencias"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos los idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Este campo no puede quedar vacío."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"El nombre de usuario ingresado no es válido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-es/strings.xml b/car-settings-lib/res/values-es/strings.xml
deleted file mode 100644
index 0e70ac6..0000000
--- a/car-settings-lib/res/values-es/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerencias"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos los idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"El campo no puede estar vacío."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"El nombre de usuario introducido no es válido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-et/strings.xml b/car-settings-lib/res/values-et/strings.xml
deleted file mode 100644
index 0282368..0000000
--- a/car-settings-lib/res/values-et/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Soovitatud"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Kõik keeled"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Väli ei tohi olla tühi."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Sisestatud kasutajanimi on sobimatu."</string>
-</resources>
diff --git a/car-settings-lib/res/values-eu/strings.xml b/car-settings-lib/res/values-eu/strings.xml
deleted file mode 100644
index c8c0e10..0000000
--- a/car-settings-lib/res/values-eu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Iradokitakoak"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Hizkuntza guztiak"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Eremuak ezin du hutsik egon."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Idatzitako erabiltzaile-izenak ez du balio."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fa/strings.xml b/car-settings-lib/res/values-fa/strings.xml
deleted file mode 100644
index 3ce1002..0000000
--- a/car-settings-lib/res/values-fa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"پیشنهادشده"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"همه زبان‌ها"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"این فیلد نمی‌تواند خالی باشد."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"نام کاربری واردشده نامعتبر است."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fi/strings.xml b/car-settings-lib/res/values-fi/strings.xml
deleted file mode 100644
index cb5f2c9..0000000
--- a/car-settings-lib/res/values-fi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ehdotettu"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Kaikki kielet"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Kenttä ei voi olla tyhjä."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Annettu käyttäjänimi on virheellinen."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fr-rCA/strings.xml b/car-settings-lib/res/values-fr-rCA/strings.xml
deleted file mode 100644
index ee93f50..0000000
--- a/car-settings-lib/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggestions"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Toutes les langues"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Champ obligatoire."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Le nom d\'utilisateur entré n\'est pas valide."</string>
-</resources>
diff --git a/car-settings-lib/res/values-fr/strings.xml b/car-settings-lib/res/values-fr/strings.xml
deleted file mode 100644
index 250d38a..0000000
--- a/car-settings-lib/res/values-fr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggestion"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Toutes les langues"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Champ obligatoire."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Le nom d\'utilisateur saisi est incorrect."</string>
-</resources>
diff --git a/car-settings-lib/res/values-gl/strings.xml b/car-settings-lib/res/values-gl/strings.xml
deleted file mode 100644
index e2a772a..0000000
--- a/car-settings-lib/res/values-gl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Idiomas suxeridos"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos os idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"O campo non pode estar en branco."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"O nome de usuario que introduciches non é válido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-gu/strings.xml b/car-settings-lib/res/values-gu/strings.xml
deleted file mode 100644
index 22826c7..0000000
--- a/car-settings-lib/res/values-gu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"સૂચવેલા"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"બધી ભાષાઓ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ફીલ્ડ ખાલી રાખી શકાય નહીં."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"દાખલ કરેલું વપરાશકર્તાનું નામ અમાન્ય છે."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hi/strings.xml b/car-settings-lib/res/values-hi/strings.xml
deleted file mode 100644
index 042be3b..0000000
--- a/car-settings-lib/res/values-hi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"सुझाए गए"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"सभी भाषाएं"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"नाम लिखने की जगह (फ़ील्ड) खाली नहीं रखी जा सकती."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"डाला गया उपयोगकर्ता नाम गलत है."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hr/strings.xml b/car-settings-lib/res/values-hr/strings.xml
deleted file mode 100644
index c0a69ff..0000000
--- a/car-settings-lib/res/values-hr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predloženo"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Svi jezici"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne može biti prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Uneseno korisničko ime nije važeće."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hu/strings.xml b/car-settings-lib/res/values-hu/strings.xml
deleted file mode 100644
index 275ea75..0000000
--- a/car-settings-lib/res/values-hu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Javasolt"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Minden nyelv"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"A mező nem lehet üres."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"A megadott felhasználónév érvénytelen."</string>
-</resources>
diff --git a/car-settings-lib/res/values-hy/strings.xml b/car-settings-lib/res/values-hy/strings.xml
deleted file mode 100644
index fcab9c7..0000000
--- a/car-settings-lib/res/values-hy/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Առաջարկվող"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Բոլոր լեզուները"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Դաշտը չի կարող դատարկ լինել:"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Մուտքագրված օգտանունն անվավեր է։"</string>
-</resources>
diff --git a/car-settings-lib/res/values-in/strings.xml b/car-settings-lib/res/values-in/strings.xml
deleted file mode 100644
index 51e4d3e..0000000
--- a/car-settings-lib/res/values-in/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Disarankan"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Semua bahasa"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Kolom harus diisi."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Nama pengguna yang dimasukkan tidak valid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-is/strings.xml b/car-settings-lib/res/values-is/strings.xml
deleted file mode 100644
index 3dffde3..0000000
--- a/car-settings-lib/res/values-is/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Tillögur"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Öll tungumál"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Reiturinn má ekki vera auður."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Ógilt notandanafn var slegið inn."</string>
-</resources>
diff --git a/car-settings-lib/res/values-it/strings.xml b/car-settings-lib/res/values-it/strings.xml
deleted file mode 100644
index 69e1425..0000000
--- a/car-settings-lib/res/values-it/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Suggerite"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tutte le lingue"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Il campo non può essere vuoto."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Il nome utente inserito non è valido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-iw/strings.xml b/car-settings-lib/res/values-iw/strings.xml
deleted file mode 100644
index 180b3e8..0000000
--- a/car-settings-lib/res/values-iw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"הצעות"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"כל השפות"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"חובה למלא את השדה."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"שם המשתמש שהוזן לא חוקי."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ja/strings.xml b/car-settings-lib/res/values-ja/strings.xml
deleted file mode 100644
index 6374217..0000000
--- a/car-settings-lib/res/values-ja/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"言語の候補"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"すべての言語"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"フィールドは空欄にできません。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"入力されたユーザー名が無効です。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-ka/strings.xml b/car-settings-lib/res/values-ka/strings.xml
deleted file mode 100644
index 6f93ba9..0000000
--- a/car-settings-lib/res/values-ka/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"რეკომენდებული"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ყველა ენა"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"არ შეიძლება ველი ცარიელი იყოს."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"მომხმარებლის სახელი არასწორადაა შეყვანილი."</string>
-</resources>
diff --git a/car-settings-lib/res/values-kk/strings.xml b/car-settings-lib/res/values-kk/strings.xml
deleted file mode 100644
index ebf2013..0000000
--- a/car-settings-lib/res/values-kk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ұсынылған"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Барлық тілдер"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Өріс бос болмауы керек."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Енгізілген пайдаланушы аты жарамсыз."</string>
-</resources>
diff --git a/car-settings-lib/res/values-km/strings.xml b/car-settings-lib/res/values-km/strings.xml
deleted file mode 100644
index 2274c4c..0000000
--- a/car-settings-lib/res/values-km/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"បាន​ណែនាំ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ភាសាទាំងអស់"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"កន្លែងបញ្ចូលមិន​អាច​ទទេឡើយ។"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ឈ្មោះ​អ្នកប្រើប្រាស់​ដែល​បាន​បញ្ចូល​គឺមិនត្រឹមត្រូវទេ។"</string>
-</resources>
diff --git a/car-settings-lib/res/values-kn/strings.xml b/car-settings-lib/res/values-kn/strings.xml
deleted file mode 100644
index c5815cc..0000000
--- a/car-settings-lib/res/values-kn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ಸೂಚಿಸಲಾಗಿರುವುದು"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ಕ್ಷೇತ್ರವು ಖಾಲಿ ಇರುವಂತಿಲ್ಲ."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ನಮೂದಿಸಿದ ಬಳಕೆದಾರರ ಹೆಸರು ಅಮಾನ್ಯವಾಗಿದೆ."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ko/strings.xml b/car-settings-lib/res/values-ko/strings.xml
deleted file mode 100644
index 1a818d9..0000000
--- a/car-settings-lib/res/values-ko/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"추천"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"모든 언어"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"입력란을 비워 둘 수 없습니다."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"입력한 사용자 이름이 올바르지 않습니다."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ky/strings.xml b/car-settings-lib/res/values-ky/strings.xml
deleted file mode 100644
index 03e5756..0000000
--- a/car-settings-lib/res/values-ky/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Сунушталган тилдер"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Бардык тилдер"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Талаа бош болбошу керек."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Киргизилген колдонуучунун аты жараксыз."</string>
-</resources>
diff --git a/car-settings-lib/res/values-lo/strings.xml b/car-settings-lib/res/values-lo/strings.xml
deleted file mode 100644
index 439bafa..0000000
--- a/car-settings-lib/res/values-lo/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ແນະນຳ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ທຸກພາສາ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ຊ່ອງຂໍ້ມູນບໍ່ສາມາດຫວ່າງເປົ່າໄດ້."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ຊື່ຜູ້ໃຊ້ທີ່ປ້ອນເຂົ້າບໍ່ຖືກຕ້ອງ."</string>
-</resources>
diff --git a/car-settings-lib/res/values-lt/strings.xml b/car-settings-lib/res/values-lt/strings.xml
deleted file mode 100644
index 3b3f481..0000000
--- a/car-settings-lib/res/values-lt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Siūloma"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Visos kalbos"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Laukas negali būti tuščias."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Įvestas naudotojo vardas yra netinkamas."</string>
-</resources>
diff --git a/car-settings-lib/res/values-lv/strings.xml b/car-settings-lib/res/values-lv/strings.xml
deleted file mode 100644
index 856dcf4..0000000
--- a/car-settings-lib/res/values-lv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ieteiktās"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Visas valodas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Lauks nedrīkst būt tukšs."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Ievadītais lietotājvārds nav derīgs."</string>
-</resources>
diff --git a/car-settings-lib/res/values-mk/strings.xml b/car-settings-lib/res/values-mk/strings.xml
deleted file mode 100644
index f344b18..0000000
--- a/car-settings-lib/res/values-mk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Предложени"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Сите јазици"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Полето не може да биде празно."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Внесеното корисничко име е неважечко."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ml/strings.xml b/car-settings-lib/res/values-ml/strings.xml
deleted file mode 100644
index afb887d..0000000
--- a/car-settings-lib/res/values-ml/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"നിര്‍‌ദ്ദേശിക്കുന്നവ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"എല്ലാ ഭാഷകളും"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ഫീൽഡ് ശൂന്യമായിടരുത്."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"നൽകിയ ഉപയോക്തൃ നാമം അസാധുവാണ്."</string>
-</resources>
diff --git a/car-settings-lib/res/values-mn/strings.xml b/car-settings-lib/res/values-mn/strings.xml
deleted file mode 100644
index d747c7b..0000000
--- a/car-settings-lib/res/values-mn/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Санал болгосон"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Бүх хэл"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Талбар хоосон байж болохгүй."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Оруулсан хэрэглэгчийн нэр буруу байна."</string>
-</resources>
diff --git a/car-settings-lib/res/values-mr/strings.xml b/car-settings-lib/res/values-mr/strings.xml
deleted file mode 100644
index f915f65..0000000
--- a/car-settings-lib/res/values-mr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"सूचित"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"सर्व भाषा"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"फील्ड रिकामे असू शकत नाही."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"एंटर केलेले वापरकर्ता नाव चुकीचे आहे."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ms/strings.xml b/car-settings-lib/res/values-ms/strings.xml
deleted file mode 100644
index e67f995..0000000
--- a/car-settings-lib/res/values-ms/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Dicadangkan"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Semua bahasa"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Medan tidak boleh kosong."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Nama pengguna yang dimasukkan tidak sah."</string>
-</resources>
diff --git a/car-settings-lib/res/values-my/strings.xml b/car-settings-lib/res/values-my/strings.xml
deleted file mode 100644
index dd448fa..0000000
--- a/car-settings-lib/res/values-my/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"အကြံပြုထားသော"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ဘာသာစကားအားလုံး"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"အကွက်ကို ကွက်လပ်ထား၍ မရပါ။"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ထည့်ထားသော အသုံးပြုသူအမည် မမှန်ကန်ပါ။"</string>
-</resources>
diff --git a/car-settings-lib/res/values-nb/strings.xml b/car-settings-lib/res/values-nb/strings.xml
deleted file mode 100644
index 77dc43a..0000000
--- a/car-settings-lib/res/values-nb/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Foreslått"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle språk"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Feltet må fylles ut."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Brukernavnet du skrev inn, er ugyldig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ne/strings.xml b/car-settings-lib/res/values-ne/strings.xml
deleted file mode 100644
index 6d32ddc..0000000
--- a/car-settings-lib/res/values-ne/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"सुझाव दिइयो"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"सम्पूर्ण भाषाहरू"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"फिल्ड खाली हुन सक्दैन।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"प्रविष्ट गरिएको प्रयोगकर्ता नाम अमान्य छ।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-nl/strings.xml b/car-settings-lib/res/values-nl/strings.xml
deleted file mode 100644
index 25f84ef..0000000
--- a/car-settings-lib/res/values-nl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Voorgesteld"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alle talen"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Veld mag niet leeg zijn."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"De ingevoerde gebruikersnaam is ongeldig."</string>
-</resources>
diff --git a/car-settings-lib/res/values-or/strings.xml b/car-settings-lib/res/values-or/strings.xml
deleted file mode 100644
index 3690ef6..0000000
--- a/car-settings-lib/res/values-or/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ପରାମର୍ଶିତ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ସମସ୍ତ ଭାଷା"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ସ୍ଥାନକୁ ଖାଲି ଛାଡ଼ି ହେବନାହିଁ।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ଲେଖାଯାଇଥିବା ଉପଯୋଗକର୍ତ୍ତାନାମଟି ଠିକ୍‍ ନାହିଁ।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-pa/strings.xml b/car-settings-lib/res/values-pa/strings.xml
deleted file mode 100644
index c501aaf..0000000
--- a/car-settings-lib/res/values-pa/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"ਸੁਝਾਏ ਗਏ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ਖੇਤਰ ਖਾਲੀ ਨਹੀਂ ਛੱਡਿਆ ਜਾ ਸਕਦਾ।"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ਦਾਖਲ ਕੀਤਾ ਗਿਆ ਵਰਤੋਂਕਾਰ ਨਾਮ ਅਵੈਧ ਹੈ।"</string>
-</resources>
diff --git a/car-settings-lib/res/values-pl/strings.xml b/car-settings-lib/res/values-pl/strings.xml
deleted file mode 100644
index 00bbad3..0000000
--- a/car-settings-lib/res/values-pl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerowane"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Wszystkie języki"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Pole nie może być puste."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Podana nazwa użytkownika jest nieprawidłowa."</string>
-</resources>
diff --git a/car-settings-lib/res/values-pt-rPT/strings.xml b/car-settings-lib/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 7ad6367..0000000
--- a/car-settings-lib/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugeridos"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos os idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"O campo não pode estar em branco."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"O nome de utilizador introduzido é inválido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-pt/strings.xml b/car-settings-lib/res/values-pt/strings.xml
deleted file mode 100644
index ac5fb11..0000000
--- a/car-settings-lib/res/values-pt/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugeridos"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Todos os idiomas"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"O campo não pode ficar em branco."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"O nome de usuário informado é inválido."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ro/strings.xml b/car-settings-lib/res/values-ro/strings.xml
deleted file mode 100644
index b79ede1..0000000
--- a/car-settings-lib/res/values-ro/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugerate"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Toate limbile"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Câmpul trebuie completat."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Numele de utilizator introdus este nevalid."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ru/strings.xml b/car-settings-lib/res/values-ru/strings.xml
deleted file mode 100644
index d5f064c..0000000
--- a/car-settings-lib/res/values-ru/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Рекомендуемые"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Все языки"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поле должно быть заполнено."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Указано недопустимое имя пользователя."</string>
-</resources>
diff --git a/car-settings-lib/res/values-si/strings.xml b/car-settings-lib/res/values-si/strings.xml
deleted file mode 100644
index 79e83f7..0000000
--- a/car-settings-lib/res/values-si/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"යෝජිත"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"සියලු භාෂා"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ක්ෂේත්‍රය හිස් විය නොහැක."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ඇතුළු කළ පරිශීලක නාමය අවලංගුය."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sk/strings.xml b/car-settings-lib/res/values-sk/strings.xml
deleted file mode 100644
index 7bf3819..0000000
--- a/car-settings-lib/res/values-sk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Navrhované"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Všetky jazyky"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Pole nesmie byť prázdne."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Zadané používateľské meno je neplatné."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sl/strings.xml b/car-settings-lib/res/values-sl/strings.xml
deleted file mode 100644
index 5f46458..0000000
--- a/car-settings-lib/res/values-sl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Predlagano"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Vsi jeziki"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Polje ne sme biti prazno."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Vneseno uporabniško ime ni veljavno."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sq/strings.xml b/car-settings-lib/res/values-sq/strings.xml
deleted file mode 100644
index 18cbe0f..0000000
--- a/car-settings-lib/res/values-sq/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Sugjeruar"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Të gjitha gjuhët"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Fusha nuk mund të lihet bosh."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Emri i përdoruesit që fute është i pavlefshëm."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sr/strings.xml b/car-settings-lib/res/values-sr/strings.xml
deleted file mode 100644
index 46b5008..0000000
--- a/car-settings-lib/res/values-sr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Предложени"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Сви језици"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поље не сме да буде празно."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Корисничко име које сте унели је неважеће."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sv/strings.xml b/car-settings-lib/res/values-sv/strings.xml
deleted file mode 100644
index d9e2309..0000000
--- a/car-settings-lib/res/values-sv/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Förslag"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Alla språk"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Fältet får inte vara tomt."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Du har angett ett ogiltigt användarnamn."</string>
-</resources>
diff --git a/car-settings-lib/res/values-sw/strings.xml b/car-settings-lib/res/values-sw/strings.xml
deleted file mode 100644
index dbe4958..0000000
--- a/car-settings-lib/res/values-sw/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Zinazopendekezwa"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Lugha zote"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Ni lazima ujaze sehemu hii"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Jina uliloweka la mtumiaji si sahihi."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ta/strings.xml b/car-settings-lib/res/values-ta/strings.xml
deleted file mode 100644
index e21d564..0000000
--- a/car-settings-lib/res/values-ta/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"பரிந்துரைகள்"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"எல்லா மொழிகளும்"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"புலம், வெறுமையாக இருக்கக்கூடாது."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"பயனர்பெயரைத் தவறாக உள்ளிட்டுள்ளீர்கள்."</string>
-</resources>
diff --git a/car-settings-lib/res/values-te/strings.xml b/car-settings-lib/res/values-te/strings.xml
deleted file mode 100644
index 38b470d..0000000
--- a/car-settings-lib/res/values-te/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"సూచించినవి"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"అన్ని భాషలు"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ఫీల్డ్ ఖాళీగా ఉండరాదు."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"నమోదు చేసిన వినియోగదారు పేరు చెల్లదు."</string>
-</resources>
diff --git a/car-settings-lib/res/values-th/strings.xml b/car-settings-lib/res/values-th/strings.xml
deleted file mode 100644
index 10ac43a..0000000
--- a/car-settings-lib/res/values-th/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"แนะนำ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"ทุกภาษา"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"ต้องกรอกข้อมูลในช่อง"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"ชื่อผู้ใช้ที่ป้อนไม่ถูกต้อง"</string>
-</resources>
diff --git a/car-settings-lib/res/values-tl/strings.xml b/car-settings-lib/res/values-tl/strings.xml
deleted file mode 100644
index 852721f..0000000
--- a/car-settings-lib/res/values-tl/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Iminumungkahi"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Lahat ng wika"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Hindi maaaring blangko ang field."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Invalid ang inilagay na username."</string>
-</resources>
diff --git a/car-settings-lib/res/values-tr/strings.xml b/car-settings-lib/res/values-tr/strings.xml
deleted file mode 100644
index bb7499e..0000000
--- a/car-settings-lib/res/values-tr/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Önerilen"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tüm diller"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Alan boş olamaz."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Girilen kullanıcı adı geçersiz."</string>
-</resources>
diff --git a/car-settings-lib/res/values-uk/strings.xml b/car-settings-lib/res/values-uk/strings.xml
deleted file mode 100644
index 4429605..0000000
--- a/car-settings-lib/res/values-uk/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Пропонується"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Усі мови"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Поле не може бути порожнім."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Введене ім’я користувача недійсне."</string>
-</resources>
diff --git a/car-settings-lib/res/values-ur/strings.xml b/car-settings-lib/res/values-ur/strings.xml
deleted file mode 100644
index 64f8d4a..0000000
--- a/car-settings-lib/res/values-ur/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"تجویز کردہ"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"سبھی زبانیں"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"فیلڈ خالی نہیں رہ سکتی۔"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"درج کردہ صارف نام غلط ہے۔"</string>
-</resources>
diff --git a/car-settings-lib/res/values-uz/strings.xml b/car-settings-lib/res/values-uz/strings.xml
deleted file mode 100644
index 1947548..0000000
--- a/car-settings-lib/res/values-uz/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Taklif qilingan"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Barcha tillar"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Maydon bo‘sh qoldirilishi mumkin emas."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Kiritilgan foydalanuvchi nomi xato."</string>
-</resources>
diff --git a/car-settings-lib/res/values-vi/strings.xml b/car-settings-lib/res/values-vi/strings.xml
deleted file mode 100644
index 6dbc7d7..0000000
--- a/car-settings-lib/res/values-vi/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Ðược đề xuất"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Tất cả ngôn ngữ"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Không được để trống trường."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Tên người dùng đã nhập là không hợp lệ."</string>
-</resources>
diff --git a/car-settings-lib/res/values-zh-rCN/strings.xml b/car-settings-lib/res/values-zh-rCN/strings.xml
deleted file mode 100644
index f9462c5..0000000
--- a/car-settings-lib/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"建议"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"所有语言"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"此字段不能留空。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"输入的用户名无效。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-zh-rHK/strings.xml b/car-settings-lib/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 8c5d191..0000000
--- a/car-settings-lib/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"建議"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"所有語言"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"欄位不得留空。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"輸入的使用者名稱無效。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-zh-rTW/strings.xml b/car-settings-lib/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 8e9c84a..0000000
--- a/car-settings-lib/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"建議"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"所有語言"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"欄位不能空白。"</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"輸入的使用者名稱無效。"</string>
-</resources>
diff --git a/car-settings-lib/res/values-zu/strings.xml b/car-settings-lib/res/values-zu/strings.xml
deleted file mode 100644
index 2e55b3f..0000000
--- a/car-settings-lib/res/values-zu/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    Copyright (C) 2018 Google Inc.
-
-    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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="language_picker_list_suggested_header" msgid="8931437200168779395">"Okuphakanyisiwe"</string>
-    <string name="language_picker_list_all_header" msgid="3907663373765943630">"Zonke izilimi"</string>
-    <string name="name_input_blank_error" msgid="5460631644831377461">"Inkundla ayikwazi ukungabi nalutho."</string>
-    <string name="name_input_invalid_error" msgid="8735081597199782922">"Igama lomsebenzisi elifakiwe alivumelekile."</string>
-</resources>
diff --git a/car-settings-lib/res/values/strings.xml b/car-settings-lib/res/values/strings.xml
deleted file mode 100644
index c9f76e7..0000000
--- a/car-settings-lib/res/values/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Copyright (C) 2018 Google Inc.
-
-    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>
-
-    <!-- Language picker list suggested locale header [CHAR LIMIT=40] -->
-    <string name="language_picker_list_suggested_header">Suggested</string>
-
-    <!-- Language picker list all other locales header [CHAR LIMIT=40] -->
-    <string name="language_picker_list_all_header">All languages</string>
-
-    <!-- An error message indicating that the name input field has been left blank and cannot be. [CHAR_LIMIT=50] -->
-    <string name="name_input_blank_error">Field can\u2019t be blank.</string>
-
-    <!-- An error message indicating that the name the user has entered is invalid. [CHAR_LIMIT=50] -->
-    <string name="name_input_invalid_error">Username entered is invalid.</string>
-
-</resources>
\ No newline at end of file
diff --git a/car-settings-lib/src/com/android/car/settingslib/language/LanguagePickerUtils.java b/car-settings-lib/src/com/android/car/settingslib/language/LanguagePickerUtils.java
deleted file mode 100644
index ef5dc46..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/language/LanguagePickerUtils.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * 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.car.settingslib.language;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.app.LocaleHelper;
-import com.android.internal.app.LocaleStore;
-import com.android.internal.app.SuggestedLocaleAdapter;
-
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Utility class that supports the language/locale picker flows.
- */
-public final class LanguagePickerUtils {
-    /**
-     * Creates an instance of {@link SuggestedLocaleAdapter} with a locale
-     * {@link LocaleStore.LocaleInfo} that is scoped to a parent locale if a parent locale is
-     * provided.
-     */
-    public static SuggestedLocaleAdapter createSuggestedLocaleAdapter(
-            Context context,
-            Set<LocaleStore.LocaleInfo> localeInfoSet,
-            @Nullable LocaleStore.LocaleInfo parent) {
-        boolean countryMode = (parent != null);
-        Locale displayLocale = countryMode ? parent.getLocale() : Locale.getDefault();
-        SuggestedLocaleAdapter adapter = new SuggestedLocaleAdapter(localeInfoSet, countryMode);
-        LocaleHelper.LocaleInfoComparator comp =
-                new LocaleHelper.LocaleInfoComparator(displayLocale, countryMode);
-        adapter.sort(comp);
-        adapter.setDisplayLocale(context, displayLocale);
-        return adapter;
-    }
-
-    /**
-     * Returns the locale from current system configuration, or the default locale if no system
-     * locale is available.
-     */
-    public static Locale getConfiguredLocale() {
-        try {
-            Locale configLocale =
-                    ActivityManager.getService().getConfiguration().getLocales().get(0);
-            return configLocale != null ? configLocale : Locale.getDefault();
-        } catch (RemoteException e) {
-            return Locale.getDefault();
-        }
-    }
-
-    private LanguagePickerUtils() {}
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/language/LocaleSelectionListener.java b/car-settings-lib/src/com/android/car/settingslib/language/LocaleSelectionListener.java
deleted file mode 100644
index 2541bf8..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/language/LocaleSelectionListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * 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.car.settingslib.language;
-
-import com.android.internal.app.LocaleStore;
-
-/**
- * Listener interface that facilitates notification of changes is locale selection.
- */
-public interface LocaleSelectionListener {
-    /**
-     * Called when a language choice has been selected.
-     */
-    void onLocaleSelected(LocaleStore.LocaleInfo localeInfo);
-
-    /**
-     * Called when a parent locale that has at least 2 child locales is selected. The
-     * expectation here is what the PagedList in the LanguagePickerFragment will be updated to
-     * display the child locales.
-     */
-    void onParentWithChildrenLocaleSelected(LocaleStore.LocaleInfo localeInfo);
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/loader/AsyncLoader.java b/car-settings-lib/src/com/android/car/settingslib/loader/AsyncLoader.java
deleted file mode 100644
index d706c3a..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/loader/AsyncLoader.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.settingslib.loader;
-
-import android.annotation.Nullable;
-import android.content.Context;
-
-import androidx.loader.content.AsyncTaskLoader;
-
-/**
- * This class fills in some boilerplate for AsyncTaskLoader to actually load things.
- * Classes the extend {@link AsyncLoader} need to properly implement required methods expressed in
- * {@link AsyncTaskLoader}
- *
- * <p>Taken from {@link com.android.settingslib.utils.AsyncLoader}. Only change to extend from
- * support library {@link AsyncTaskLoader}
- *
- * @param <T> the data type to be loaded.
- */
-public abstract class AsyncLoader<T> extends AsyncTaskLoader<T> {
-    @Nullable
-    private T mResult;
-
-    public AsyncLoader(Context context) {
-        super(context);
-    }
-
-    @Override
-    protected void onStartLoading() {
-        if (mResult != null) {
-            deliverResult(mResult);
-        }
-
-        if (takeContentChanged() || mResult == null) {
-            forceLoad();
-        }
-    }
-
-    @Override
-    protected void onStopLoading() {
-        cancelLoad();
-    }
-
-    @Override
-    public void deliverResult(T data) {
-        if (isReset()) {
-            return;
-        }
-        mResult = data;
-        if (isStarted()) {
-            super.deliverResult(data);
-        }
-    }
-
-    @Override
-    protected void onReset() {
-        super.onReset();
-        onStopLoading();
-        mResult = null;
-    }
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/log/LoggerBase.java b/car-settings-lib/src/com/android/car/settingslib/log/LoggerBase.java
deleted file mode 100644
index 2d59899..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/log/LoggerBase.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * 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.car.settingslib.log;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-/**
- * Helper class that wraps {@link Log} to log messages to logcat. The intended use for a Logger is
- * to include one per file, using the class.getSimpleName as the prefix, like this:
- *     <pre> private static final Logger LOG = new Logger(MyClass.class); </pre>
- *
- * <p>
- * The logger will log statements in this format:
- *     mTag: [PREFIX] MESSAGE
- *
- * <p>
- * Where mTag is defined by the subclass. This helps differentiate logs while staying within the
- * 23 character limit of the log mTag.
- *
- * <p>
- * When logging verbose and debug logs, the logs should either be guarded by {@code if (LOG.isV())},
- * or a constant if (DEBUG). That DEBUG constant should be false on any submitted code.
- */
-public abstract class LoggerBase {
-    private final String mTag;
-    private final String mPrefix;
-
-    public LoggerBase(Class<?> cls) {
-        this(cls.getSimpleName());
-    }
-
-    public LoggerBase(String prefix) {
-        mTag = getTag();
-        if (TextUtils.isEmpty(mTag)) {
-            throw new IllegalStateException("Tag must be not null or empty");
-        }
-        if (mTag.length() > 23) {
-            throw new IllegalStateException("Tag must be 23 characters or less");
-        }
-        mPrefix = "[" + prefix + "] ";
-    }
-
-    /**
-     * Gets the tag that will be used in all logging calls.
-     */
-    @NonNull
-    protected abstract String getTag();
-
-    /**
-     * Returns true when it is desired to force log all messages.
-     */
-    protected boolean forceAllLogging() {
-        return false;
-    }
-
-    /**
-     * Logs a {@link Log#VERBOSE} log message. Will only be logged if {@link Log#VERBOSE} is
-     * loggable. This is a wrapper around {@link Log#v(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void v(String message) {
-        if (isV()) {
-            Log.v(mTag, mPrefix.concat(message));
-        }
-    }
-
-    /**
-     * Logs a {@link Log#VERBOSE} log message. Will only be logged if {@link Log#VERBOSE} is
-     * loggable. This is a wrapper around {@link Log#v(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void v(String message, Throwable throwable) {
-        if (isV()) {
-            Log.v(mTag, mPrefix.concat(message), throwable);
-        }
-    }
-
-    /**
-     * Logs a {@link Log#DEBUG} log message. Will only be logged if {@link Log#DEBUG} is
-     * loggable. This is a wrapper around {@link Log#d(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void d(String message) {
-        if (isD()) {
-            Log.d(mTag, mPrefix.concat(message));
-        }
-    }
-
-    /**
-     * Logs a {@link Log#DEBUG} log message. Will only be logged if {@link Log#DEBUG} is
-     * loggable. This is a wrapper around {@link Log#d(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void d(String message, Throwable throwable) {
-        if (isD()) {
-            Log.d(mTag, mPrefix.concat(message), throwable);
-        }
-    }
-
-    /**
-     * Logs a {@link Log#INFO} log message. Will only be logged if {@link Log#INFO} is loggable.
-     * This is a wrapper around {@link Log#i(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void i(String message) {
-        if (isI()) {
-            Log.i(mTag, mPrefix.concat(message));
-        }
-    }
-
-    /**
-     * Logs a {@link Log#INFO} log message. Will only be logged if {@link Log#INFO} is loggable.
-     * This is a wrapper around {@link Log#i(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void i(String message, Throwable throwable) {
-        if (isI()) {
-            Log.i(mTag, mPrefix.concat(message), throwable);
-        }
-    }
-
-    /**
-     * Logs a {@link Log#WARN} log message. This is a wrapper around {@link Log#w(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void w(String message) {
-        Log.w(mTag, mPrefix.concat(message));
-    }
-
-    /**
-     * Logs a {@link Log#WARN} log message. This is a wrapper around
-     * {@link Log#w(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void w(String message, Throwable throwable) {
-        Log.w(mTag, mPrefix.concat(message), throwable);
-    }
-
-    /**
-     * Logs a {@link Log#ERROR} log message. This is a wrapper around {@link Log#e(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void e(String message) {
-        Log.e(mTag, mPrefix.concat(message));
-    }
-
-    /**
-     * Logs a {@link Log#ERROR} log message. This is a wrapper around
-     * {@link Log#e(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void e(String message, Throwable throwable) {
-        Log.e(mTag, mPrefix.concat(message), throwable);
-    }
-
-    /**
-     * Logs a "What a Terrible Failure" as an {@link Log#ASSERT} log message. This is a wrapper
-     * around {@link Log#w(String, String)}.
-     *
-     * @param message The message you would like logged.
-     */
-    public void wtf(String message) {
-        Log.wtf(mTag, mPrefix.concat(message));
-    }
-
-    /**
-     * Logs a "What a Terrible Failure" as an {@link Log#ASSERT} log message. This is a wrapper
-     * around {@link Log#wtf(String, String, Throwable)}.
-     *
-     * @param message The message you would like logged.
-     * @param throwable An exception to log
-     */
-    public void wtf(String message, Throwable throwable) {
-        Log.wtf(mTag, mPrefix.concat(message), throwable);
-    }
-
-    private boolean isV() {
-        return Log.isLoggable(mTag, Log.VERBOSE) || forceAllLogging();
-    }
-
-    private boolean isD() {
-        return Log.isLoggable(mTag, Log.DEBUG) || forceAllLogging();
-    }
-
-    private boolean isI() {
-        return Log.isLoggable(mTag, Log.INFO) || forceAllLogging();
-    }
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/util/ProfileNameSaver.java b/car-settings-lib/src/com/android/car/settingslib/util/ProfileNameSaver.java
deleted file mode 100644
index 8f7067c..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/util/ProfileNameSaver.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.settingslib.util;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * Saves name as GIVEN_NAME on "Me" Profile. If "Me" contact does not exist, it's created.
- */
-public class ProfileNameSaver {
-    private static final String TAG = "ProfileNameSaver";
-    private static final Uri PROFILE_URI = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI;
-    private static final int INVALID_ID = -1;
-
-    /**
-     * The projection into the profiles database that retrieves just the id of a profile.
-     */
-    private static final String[] CONTACTS_PROJECTION =
-            new String[]{ContactsContract.RawContacts._ID};
-
-    /**
-     * A projection into the profile data for one particular contact that includes the
-     * contact's MIME type.
-     */
-    private static final String[] CONTACTS_PROFILE_PROJECTION = new String[]{
-            ContactsContract.Data._ID,
-            ContactsContract.Data.MIMETYPE};
-
-    /**
-     * A selection into the profiles database that queries for a MIME type.
-     */
-    private static final String CONTACT_MIME_QUERY = ContactsContract.Data.MIMETYPE + " = ?";
-
-    /**
-     * Updates the "Me" contact profile card with the given name as the first name of the
-     * contact. If the "Me" contact does not exist, then one will be created.
-     *
-     * @param name The first name for the "Me" contact. If this value is {@code null} or
-     *             empty, then the contact will not be updated.
-     */
-    public static void updateMeContactWith(String name, ContentResolver contentResolver) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "updateMeContactWith name=" + name);
-        }
-
-        if (TextUtils.isEmpty(name)) {
-            return;
-        }
-
-        // Check if there is already an existing "me" contact.
-        Cursor cursor = contentResolver.query(
-                PROFILE_URI,
-                CONTACTS_PROJECTION,
-                /* selection= */ null,
-                /* selectionArgs= */ null,
-                /* sortOrder= */ null);
-
-        if (cursor == null) {
-            // Error in querying the content resolver, skip the update flow
-            Log.e(TAG, "Received null from query to the \"me\" contact at " + PROFILE_URI);
-            return;
-        }
-
-        long meRawContactId = -1;  // no ID can be < 0
-        boolean newContact = true;
-        try {
-            if (cursor.moveToFirst()) {
-                meRawContactId = cursor.getLong(0);
-                newContact = false;  // An entry indicates that the "me" contact exists.
-            }
-        } finally {
-            cursor.close();
-        }
-
-        ContentValues values = new ContentValues();
-
-        if (newContact) {
-            meRawContactId = ContentUris.parseId(contentResolver.insert(PROFILE_URI, values));
-        }
-
-        values.put(ContactsContract.Data.RAW_CONTACT_ID, meRawContactId);
-        values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
-        values.put(ContactsContract.Data.MIMETYPE,
-                ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
-
-        long structuredNameId = getProfileItem(meRawContactId, contentResolver);
-        if (newContact || structuredNameId == INVALID_ID) {
-            contentResolver.insert(ContactsContract.Data.CONTENT_URI, values);
-        } else {
-            contentResolver.update(ContentUris.withAppendedId(
-                    ContactsContract.Data.CONTENT_URI, structuredNameId), values,
-                    /* where= */ null, /* selectionArgs= */ null);
-        }
-    }
-
-    /**
-     * Helper method to search for the first profile item of the type {@link
-     * ContactsContract.CommonDataKinds.StructuredName#CONTENT_ITEM_TYPE}.
-     *
-     * @return The item's ID or {@link #INVALID_ID} if not found.
-     */
-    private static long getProfileItem(long profileContactId, ContentResolver contentResolver) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "getProfileItem profileContactId=" + profileContactId);
-        }
-        Uri dataUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI.buildUpon()
-                .appendPath(String.valueOf(profileContactId))
-                .appendPath(ContactsContract.RawContacts.Data.CONTENT_DIRECTORY)
-                .build();
-
-        Cursor cursor = contentResolver.query(
-                dataUri,
-                CONTACTS_PROFILE_PROJECTION,
-                CONTACT_MIME_QUERY,
-                new String[]{
-                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE},
-                /* sortOrder= */ null);
-
-        // Error in querying the content resolver.
-        if (cursor == null) {
-            Log.e(TAG, "Received null from query to the first profile item at " + dataUri);
-            return INVALID_ID;
-        }
-
-        try {
-            return cursor.moveToFirst() ? cursor.getLong(0) : INVALID_ID;
-        } finally {
-            cursor.close();
-        }
-    }
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/util/ResultCodes.java b/car-settings-lib/src/com/android/car/settingslib/util/ResultCodes.java
deleted file mode 100644
index 2ac5ef2..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/util/ResultCodes.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.settingslib.util;
-
-import static android.app.Activity.RESULT_FIRST_USER;
-
-/**
- * Result code set shared between Settings and other Car components
- */
-public final class ResultCodes {
-    public static final int RESULT_SKIP = RESULT_FIRST_USER;
-    public static final int RESULT_NONE = RESULT_FIRST_USER + 1;
-}
diff --git a/car-settings-lib/src/com/android/car/settingslib/util/SettingsConstants.java b/car-settings-lib/src/com/android/car/settingslib/util/SettingsConstants.java
deleted file mode 100644
index cec6146..0000000
--- a/car-settings-lib/src/com/android/car/settingslib/util/SettingsConstants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2018 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.car.settingslib.util;
-
-/**
- * Contains car specific settings constants.
- */
-public class SettingsConstants {
-
-    public static final String USER_NAME_SET = "user_name_set";
-
-}
diff --git a/car-settings-lib/tests/Android.mk b/car-settings-lib/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-settings-lib/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-settings-lib/tests/robotests/Android.mk b/car-settings-lib/tests/robotests/Android.mk
deleted file mode 100644
index 59e61b2..0000000
--- a/car-settings-lib/tests/robotests/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-##################################################################
-# Car Settings Library app just for Robolectric test target.     #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarSettingsLib
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-settings-lib
-
-include $(BUILD_PACKAGE)
-
-##################################################################
-# Car Settings Library Robolectric test target.                  #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarSettingsLibRoboTests
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-LOCAL_JAVA_LIBRARIES := \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt \
-    android.car
-
-LOCAL_INSTRUMENTATION_FOR := CarSettingsLib
-
-LOCAL_MODULE_TAGS := optional
-
-# Generate test_config.properties
-include external/robolectric-shadows/gen_test_config.mk
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Settings Library runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarSettingsLibRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    CarSettingsLibRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt \
-    android.car
-
-LOCAL_TEST_PACKAGE := CarSettingsLib
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
\ No newline at end of file
diff --git a/car-settings-lib/tests/robotests/AndroidManifest.xml b/car-settings-lib/tests/robotests/AndroidManifest.xml
deleted file mode 100644
index dd1a985..0000000
--- a/car-settings-lib/tests/robotests/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2018 Google Inc.
-
-    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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.settingslib.robotests">
-
-</manifest>
diff --git a/car-settings-lib/tests/robotests/config/robolectric.properties b/car-settings-lib/tests/robotests/config/robolectric.properties
deleted file mode 100644
index 3626c87..0000000
--- a/car-settings-lib/tests/robotests/config/robolectric.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Copyright (C) 2018 Google Inc.
-#
-# 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.
-#
-sdk=NEWEST_SDK
\ No newline at end of file
diff --git a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/log/LoggerBaseTest.java b/car-settings-lib/tests/robotests/src/com/android/car/settingslib/log/LoggerBaseTest.java
deleted file mode 100644
index 468c010..0000000
--- a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/log/LoggerBaseTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * 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.car.settingslib.log;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-/**
- * Tests {@link LoggerBase}
- */
-@RunWith(RobolectricTestRunner.class)
-public class LoggerBaseTest {
-
-    @Rule
-    public ExpectedException mExpectedException = ExpectedException.none();
-
-    @Test
-    public void testNullTag() {
-        mExpectedException.expect(IllegalStateException.class);
-        mExpectedException.expectMessage("Tag must be not null or empty");
-        new NullTagLogger("NullLogger");
-    }
-
-    @Test
-    public void testEmptyTag() {
-        mExpectedException.expect(IllegalStateException.class);
-        mExpectedException.expectMessage("Tag must be not null or empty");
-        new EmptyTagLogger("EmptyTagLogger");
-    }
-
-    @Test
-    public void testTooLongTag() {
-        mExpectedException.expect(IllegalStateException.class);
-        mExpectedException.expectMessage("Tag must be 23 characters or less");
-        new TooLongTagLogger("TooLongTagLogger");
-    }
-
-    private class NullTagLogger extends LoggerBase {
-
-        NullTagLogger(String prefix) {
-            super(prefix);
-        }
-
-        @Override
-        protected String getTag() {
-            return null;
-        }
-    }
-
-    private class EmptyTagLogger extends LoggerBase {
-
-        EmptyTagLogger(String prefix) {
-            super(prefix);
-        }
-
-        @Override
-        protected String getTag() {
-            return "";
-        }
-    }
-
-    /**
-     * A Logger with a tag that is 24 characters long.
-     */
-    private class TooLongTagLogger extends LoggerBase {
-
-        TooLongTagLogger(String prefix) {
-            super(prefix);
-        }
-
-        @Override
-        protected String getTag() {
-            return "LoremIpsumLoremIpsumLore";
-        }
-    }
-}
diff --git a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/robolectric/BaseRobolectricTest.java b/car-settings-lib/tests/robotests/src/com/android/car/settingslib/robolectric/BaseRobolectricTest.java
deleted file mode 100644
index 280faea..0000000
--- a/car-settings-lib/tests/robotests/src/com/android/car/settingslib/robolectric/BaseRobolectricTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2018 Google Inc.
- *
- * 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.car.settingslib.robolectric;
-
-import org.junit.Rule;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-/**
- * Base test for CarSettingsLib Robolectric tests.
- */
-public abstract class BaseRobolectricTest {
-    // This rule automatically initializes any mocks created using the @Mock annotation
-    @Rule
-    public MockitoRule mMockitoRule = MockitoJUnit.rule();
-}
diff --git a/car-telephony-common/Android.bp b/car-telephony-common/Android.bp
new file mode 100644
index 0000000..1e6a9b8
--- /dev/null
+++ b/car-telephony-common/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2018 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.
+//
+
+android_library {
+    name: "car-telephony-common",
+
+    srcs: ["src/**/*.java"],
+
+    resource_dirs: ["res"],
+
+    optimize: {
+        enabled: false,
+    },
+
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+
+    static_libs: [
+        "androidx.legacy_legacy-support-v4",
+        "car-apps-common",
+        "glide-prebuilt",
+        "libphonenumber",
+    ],
+
+    libs: ["android.car"],
+
+}
diff --git a/car-telephony-common/Android.mk b/car-telephony-common/Android.mk
deleted file mode 100644
index 3a592d6..0000000
--- a/car-telephony-common/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-telephony-common
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.legacy_legacy-support-v4 \
-    car-apps-common
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    car-glide \
-    car-glide-disklrucache \
-    car-gifdecoder \
-    libphonenumber
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
\ No newline at end of file
diff --git a/car-telephony-common/res/values-af/strings.xml b/car-telephony-common/res/values-af/strings.xml
index 7e19555..56aebcf 100644
--- a/car-telephony-common/res/values-af/strings.xml
+++ b/car-telephony-common/res/values-af/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Koppel tans …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Bel tans …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Hou aan"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Oproep beëindig"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Hou aan"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Oproep beëindig"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Gekoppel"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Lui tans …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ontkoppel tans …"</string>
diff --git a/car-telephony-common/res/values-am/strings.xml b/car-telephony-common/res/values-am/strings.xml
index 6d0315e..2714928 100644
--- a/car-telephony-common/res/values-am/strings.xml
+++ b/car-telephony-common/res/values-am/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"በመገናኘት ላይ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"በመደወል ላይ"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ያዝናቆይ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ጥሪ አብቅቷል"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ያዝና ቆይ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ጥሪ አብቅቷል"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ተገናኝቷል"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"በመጥራት ላይ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ግንኝነትን በማቋረጥ ላይ…"</string>
diff --git a/car-telephony-common/res/values-ar/strings.xml b/car-telephony-common/res/values-ar/strings.xml
index fcc72fb..aa5ceca 100644
--- a/car-telephony-common/res/values-ar/strings.xml
+++ b/car-telephony-common/res/values-ar/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"جارٍ الاتصال…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"جارٍ طلب الرقم…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"قيد الانتظار"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"انتهت المكالمة"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"قيد الانتظار"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"تم إنهاء المكالمة"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"متّصل"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"جارٍ إطلاق الرنين…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"جارٍ قطع الاتصال…"</string>
diff --git a/car-telephony-common/res/values-as/strings.xml b/car-telephony-common/res/values-as/strings.xml
index a4c90ae..c2d94c4 100644
--- a/car-telephony-common/res/values-as/strings.xml
+++ b/car-telephony-common/res/values-as/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"সংযোগ কৰি থকা হৈছে…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ডায়েল কৰি থকা হৈছে…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"হ’ল্ডত আছে"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"কল শেষ হৈছে"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"হ’ল্ডত আছে"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"কলটো সমাপ্ত হ’ল"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"সংযোগ কৰা হ’ল"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ৰিং কৰি আছে…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"সংযোগ ছেদ হৈ আছে…"</string>
diff --git a/car-telephony-common/res/values-az/strings.xml b/car-telephony-common/res/values-az/strings.xml
index d29aeab..6882db1 100644
--- a/car-telephony-common/res/values-az/strings.xml
+++ b/car-telephony-common/res/values-az/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Qoşulur…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Nömrə yığılır…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Gözləmədə"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Zəng sona çatdı"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Xətdə"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Zəng bitdi"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Qoşuldu"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zəng çalır…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Bağlantı kəsilir…"</string>
diff --git a/car-telephony-common/res/values-b+sr+Latn/strings.xml b/car-telephony-common/res/values-b+sr+Latn/strings.xml
index d05ef72..04dcbbe 100644
--- a/car-telephony-common/res/values-b+sr+Latn/strings.xml
+++ b/car-telephony-common/res/values-b+sr+Latn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezuje se…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Poziva se…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Na čekanju"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Poziv je završen"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čekanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Poziv je završen"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezan"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvoni…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Prekida se veza…"</string>
diff --git a/car-telephony-common/res/values-be/strings.xml b/car-telephony-common/res/values-be/strings.xml
index 1e1bcdf..49e9f44 100644
--- a/car-telephony-common/res/values-be/strings.xml
+++ b/car-telephony-common/res/values-be/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ідзе падключэнне…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Ідзе набор нумара…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На ўтрыманні"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Выклік скончаны"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"На ўтрыманні"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Выклік завершаны"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Падключана"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ідзе празвон…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ідзе адключэнне…"</string>
diff --git a/car-telephony-common/res/values-bg/strings.xml b/car-telephony-common/res/values-bg/strings.xml
index ac7dbf6..99d16bd 100644
--- a/car-telephony-common/res/values-bg/strings.xml
+++ b/car-telephony-common/res/values-bg/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Свързва се…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Набиране…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Задържано"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Обаждането завърши"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Задържане на обаждането"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Обаждането завърши"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Установена е връзка"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Звъни се…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Връзката се прекр…"</string>
diff --git a/car-telephony-common/res/values-bn/strings.xml b/car-telephony-common/res/values-bn/strings.xml
index 4855b6e..65f38ef 100644
--- a/car-telephony-common/res/values-bn/strings.xml
+++ b/car-telephony-common/res/values-bn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"কানেক্ট হচ্ছে…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ডায়াল করা হচ্ছে…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"হোল্ডে আছে"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"কল শেষ হয়েছে"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"হোল্ডে রয়েছে"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"কল শেষ হয়েছে"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"কানেক্ট করা হয়েছে"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"রিং হচ্ছে…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ডিসকানেক্ট করা হচ্ছে…"</string>
diff --git a/car-telephony-common/res/values-bs/strings.xml b/car-telephony-common/res/values-bs/strings.xml
index 1d6a8b8..fbfb012 100644
--- a/car-telephony-common/res/values-bs/strings.xml
+++ b/car-telephony-common/res/values-bs/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezivanje…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Biranje…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Na čekanju"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Poziv je završen"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čekanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Poziv je završen"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezan"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvoni…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Prekidanje veze…"</string>
diff --git a/car-telephony-common/res/values-ca/strings.xml b/car-telephony-common/res/values-ca/strings.xml
index 356f31c..1ff8957 100644
--- a/car-telephony-common/res/values-ca/strings.xml
+++ b/car-telephony-common/res/values-ca/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"S\'està connectant…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"S\'està marcant…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Trucada finalitzada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Trucada finalitzada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connectat"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Està sonant…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"S\'està desconnectant…"</string>
diff --git a/car-telephony-common/res/values-cs/strings.xml b/car-telephony-common/res/values-cs/strings.xml
index 41a29b5..7b6e1d7 100644
--- a/car-telephony-common/res/values-cs/strings.xml
+++ b/car-telephony-common/res/values-cs/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Připojování…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Vytáčení…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Podrženo"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Hovor byl ukončen"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Přidržený hovor"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Hovor byl ukončen"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Připojeno"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Vyzvánění…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Odpojování…"</string>
diff --git a/car-telephony-common/res/values-da/strings.xml b/car-telephony-common/res/values-da/strings.xml
index 6995f5c..c1507fe 100644
--- a/car-telephony-common/res/values-da/strings.xml
+++ b/car-telephony-common/res/values-da/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Tilslutter…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Ringer op…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"På hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Opkaldet er slut"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"På hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Opkaldet er slut"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Der er forbindelse"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringer…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Afbryder…"</string>
diff --git a/car-telephony-common/res/values-de/strings.xml b/car-telephony-common/res/values-de/strings.xml
index a5257d3..131fc08 100644
--- a/car-telephony-common/res/values-de/strings.xml
+++ b/car-telephony-common/res/values-de/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Verbinden…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Rufaufbau…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Warten"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Anruf beendet"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Anruf wird gehalten"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Anruf beendet"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Verbunden"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Klingelt…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Verbindung wird getrennt…"</string>
diff --git a/car-telephony-common/res/values-el/strings.xml b/car-telephony-common/res/values-el/strings.xml
index 40d1716..6392460 100644
--- a/car-telephony-common/res/values-el/strings.xml
+++ b/car-telephony-common/res/values-el/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Σύνδεση…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Κλήση…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Σε αναμονή"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Η κλήση τερματίστηκε"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Σε αναμονή"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Η κλήση τερματίστηκε"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Συνδέθηκε"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Κλήση…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Αποσύνδεση…"</string>
diff --git a/car-telephony-common/res/values-en-rAU/strings.xml b/car-telephony-common/res/values-en-rAU/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rAU/strings.xml
+++ b/car-telephony-common/res/values-en-rAU/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rCA/strings.xml b/car-telephony-common/res/values-en-rCA/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rCA/strings.xml
+++ b/car-telephony-common/res/values-en-rCA/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rGB/strings.xml b/car-telephony-common/res/values-en-rGB/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rGB/strings.xml
+++ b/car-telephony-common/res/values-en-rGB/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rIN/strings.xml b/car-telephony-common/res/values-en-rIN/strings.xml
index 06d1973..cc8a536 100644
--- a/car-telephony-common/res/values-en-rIN/strings.xml
+++ b/car-telephony-common/res/values-en-rIN/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connecting…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dialling…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"On Hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Call Ended"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"On hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Call ended"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connected"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringing…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnecting…"</string>
diff --git a/car-telephony-common/res/values-en-rXC/strings.xml b/car-telephony-common/res/values-en-rXC/strings.xml
index b80f8fa..43e60e9 100644
--- a/car-telephony-common/res/values-en-rXC/strings.xml
+++ b/car-telephony-common/res/values-en-rXC/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎  ·  ‎‏‎‎‏‏‎<xliff:g id="DURATION">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎Connecting…‎‏‎‎‏‎"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎Dialing…‎‏‎‎‏‎"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎On Hold‎‏‎‎‏‎"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎Call Ended‎‏‎‎‏‎"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎On hold‎‏‎‎‏‎"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎Call ended‎‏‎‎‏‎"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎Connected‎‏‎‎‏‎"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎Ringing…‎‏‎‎‏‎"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‎Disconnecting…‎‏‎‎‏‎"</string>
diff --git a/car-telephony-common/res/values-es-rUS/strings.xml b/car-telephony-common/res/values-es-rUS/strings.xml
index 2e71140..12fb629 100644
--- a/car-telephony-common/res/values-es-rUS/strings.xml
+++ b/car-telephony-common/res/values-es-rUS/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Marcando…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Llamada finalizada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Llamada finalizada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-es/strings.xml b/car-telephony-common/res/values-es/strings.xml
index 390354f..6cff2e2 100644
--- a/car-telephony-common/res/values-es/strings.xml
+++ b/car-telephony-common/res/values-es/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Marcando…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Llamada finalizada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Llamada finalizada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-et/strings.xml b/car-telephony-common/res/values-et/strings.xml
index e74cb8a..9926364 100644
--- a/car-telephony-common/res/values-et/strings.xml
+++ b/car-telephony-common/res/values-et/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ühendamine …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Valimine …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Ootel"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Kõne lõpetati"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ootel"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Kõne lõpetati"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ühendatud"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Heliseb …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ühenduse katkestamine…"</string>
diff --git a/car-telephony-common/res/values-eu/strings.xml b/car-telephony-common/res/values-eu/strings.xml
index ddaec85..ff34106 100644
--- a/car-telephony-common/res/values-eu/strings.xml
+++ b/car-telephony-common/res/values-eu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Konektatzen…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Markatzen…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Zain"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Deia amaituta"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Zain"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Amaitu da deia"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Konektatuta"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Deitzen…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Deskonektatzen…"</string>
diff --git a/car-telephony-common/res/values-fa/strings.xml b/car-telephony-common/res/values-fa/strings.xml
index 092b944..0418d6e 100644
--- a/car-telephony-common/res/values-fa/strings.xml
+++ b/car-telephony-common/res/values-fa/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"درحال اتصال…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"درحال شماره‌گیری"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"در انتظار"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"تماس پایان یافت"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"درانتظار"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"تماس پایان یافت"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"متصل"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"درحال زنگ زدن…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"درحال قطع اتصال…"</string>
diff --git a/car-telephony-common/res/values-fi/strings.xml b/car-telephony-common/res/values-fi/strings.xml
index ce6ff53..bf46e0b 100644
--- a/car-telephony-common/res/values-fi/strings.xml
+++ b/car-telephony-common/res/values-fi/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Yhdistetään…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Soitetaan…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Pidossa"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Puhelu päättyi"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Pidossa"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Puhelu lopetettu"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Yhdistetty"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Soi…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Katkaistaan…"</string>
diff --git a/car-telephony-common/res/values-fr-rCA/strings.xml b/car-telephony-common/res/values-fr-rCA/strings.xml
index cef9278..bed5d9d 100644
--- a/car-telephony-common/res/values-fr-rCA/strings.xml
+++ b/car-telephony-common/res/values-fr-rCA/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g> : <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connexion en cours…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Composition…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En attente"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Appel terminé"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En attente"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Appel terminé"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connecté"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonnerie en cours…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Déconnexion…"</string>
diff --git a/car-telephony-common/res/values-fr/strings.xml b/car-telephony-common/res/values-fr/strings.xml
index 164f23d..35833e0 100644
--- a/car-telephony-common/res/values-fr/strings.xml
+++ b/car-telephony-common/res/values-fr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connexion…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Composition numéro…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En attente"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Appel terminé"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En attente"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Appel terminé"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Appel en cours"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sonnerie…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Déconnexion…"</string>
diff --git a/car-telephony-common/res/values-gl/strings.xml b/car-telephony-common/res/values-gl/strings.xml
index 2251c16..2058cad 100644
--- a/car-telephony-common/res/values-gl/strings.xml
+++ b/car-telephony-common/res/values-gl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Marcando…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"En espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chamada finalizada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"En espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chamada finalizada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Facendo soar…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-gu/strings.xml b/car-telephony-common/res/values-gu/strings.xml
index 04cf443..7040087 100644
--- a/car-telephony-common/res/values-gu/strings.xml
+++ b/car-telephony-common/res/values-gu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"કનેક્ટ થઈ રહ્યું છે…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ડાયલ કરી રહ્યાં છે…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"હોલ્ડ પર"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"કૉલ સમાપ્ત થયો"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"હોલ્ડ પર"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"કૉલ સમાપ્ત થયો"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"કનેક્ટેડ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"રિંગ વાગી રહી છે…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ડિસ્કનેક્ટ થાય છે…"</string>
diff --git a/car-telephony-common/res/values-hi/strings.xml b/car-telephony-common/res/values-hi/strings.xml
index 5fdb213..418e776 100644
--- a/car-telephony-common/res/values-hi/strings.xml
+++ b/car-telephony-common/res/values-hi/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"कनेक्ट हो रहा है…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"डायल किया जा रहा है…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"कॉल होल्ड पर है"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"कॉल खत्म हो गया"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"होल्ड पर है"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"कॉल खत्म हुआ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"जुड़ गया है"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"घंटी बज रही है…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"डिसकनेक्ट हो रहा है…"</string>
diff --git a/car-telephony-common/res/values-hr/strings.xml b/car-telephony-common/res/values-hr/strings.xml
index 5e0f4d7..6a35140 100644
--- a/car-telephony-common/res/values-hr/strings.xml
+++ b/car-telephony-common/res/values-hr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezivanje…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Biranje broja…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Na čekanju"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Poziv je završio"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čekanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Poziv je završio"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezano"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvonjenje…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Isključivanje…"</string>
diff --git a/car-telephony-common/res/values-hu/strings.xml b/car-telephony-common/res/values-hu/strings.xml
index fa95e1a..26e0165 100644
--- a/car-telephony-common/res/values-hu/strings.xml
+++ b/car-telephony-common/res/values-hu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Csatlakozás…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Tárcsázás…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Várakoztatva"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"A hívás befejeződött"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Várakoztatva"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"A hívás befejeződött"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Csatlakozva"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Csörgés…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Kapcsolat bontása…"</string>
diff --git a/car-telephony-common/res/values-hy/strings.xml b/car-telephony-common/res/values-hy/strings.xml
index c8d7ea9..9a0cdeb 100644
--- a/car-telephony-common/res/values-hy/strings.xml
+++ b/car-telephony-common/res/values-hy/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Միացում…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Համարհավաքում…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Սպասում"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Զանգն ավարտվեց"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Զանգը սպասման մեջ է"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Զանգն ավարտվեց"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Միացած է"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Զանգ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Անջատվում է…"</string>
diff --git a/car-telephony-common/res/values-in/strings.xml b/car-telephony-common/res/values-in/strings.xml
index 9ef213c..7450656 100644
--- a/car-telephony-common/res/values-in/strings.xml
+++ b/car-telephony-common/res/values-in/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Menghubungkan…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Memanggil…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Harap Tunggu"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Panggilan Diakhiri"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ditangguhkan"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Panggilan diakhiri"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Terhubung"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Berdering…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Memutus sambungan..."</string>
diff --git a/car-telephony-common/res/values-is/strings.xml b/car-telephony-common/res/values-is/strings.xml
index b91a805..e330acb 100644
--- a/car-telephony-common/res/values-is/strings.xml
+++ b/car-telephony-common/res/values-is/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Tengist…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Hringir…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Í bið"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Símtali lokið"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Í bið"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Lagt á"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Tengt"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Hringir…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Aftengist…"</string>
diff --git a/car-telephony-common/res/values-it/strings.xml b/car-telephony-common/res/values-it/strings.xml
index cb4bc61..47b659c 100644
--- a/car-telephony-common/res/values-it/strings.xml
+++ b/car-telephony-common/res/values-it/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Connessione…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Chiamata…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"In attesa"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chiamata terminata"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"In attesa"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chiamata terminata"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Connesso"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sta squillando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Disconnessione…"</string>
diff --git a/car-telephony-common/res/values-iw/strings.xml b/car-telephony-common/res/values-iw/strings.xml
index 8e0fe49..67620e7 100644
--- a/car-telephony-common/res/values-iw/strings.xml
+++ b/car-telephony-common/res/values-iw/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"מתחבר…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"החיוג מתבצע…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"בהמתנה"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"השיחה הסתיימה"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"בהמתנה"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"השיחה הסתיימה"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"מתבצעת שיחה"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"מצלצל…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"מתנתק…"</string>
diff --git a/car-telephony-common/res/values-ja/strings.xml b/car-telephony-common/res/values-ja/strings.xml
index 4c0a6c1..a231047 100644
--- a/car-telephony-common/res/values-ja/strings.xml
+++ b/car-telephony-common/res/values-ja/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"接続中…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"発信中…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"保留中"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通話終了"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保留中"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通話終了"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"接続済み"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"着信中…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"切断中…"</string>
diff --git a/car-telephony-common/res/values-ka/strings.xml b/car-telephony-common/res/values-ka/strings.xml
index 858ffa3..6db5a44 100644
--- a/car-telephony-common/res/values-ka/strings.xml
+++ b/car-telephony-common/res/values-ka/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"დაკავშირება…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"მიმდინარეობს აკრეფა…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"შეყოვნების რეჟიმში"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ზარი დასრულდა"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"შეყოვნების რეჟიმში"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ზარი დასრულდა"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"დაკავშირებულია"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ირეკება…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"კავშირი წყდება…"</string>
diff --git a/car-telephony-common/res/values-kk/strings.xml b/car-telephony-common/res/values-kk/strings.xml
index 48eba3d..0e767dd 100644
--- a/car-telephony-common/res/values-kk/strings.xml
+++ b/car-telephony-common/res/values-kk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Жалғануда…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Терілуде…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Күтуде"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Қоңырау аяқталды"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Күтуде"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Қоңырау аяқталды"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Жалғанды"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Шылдырлату…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ажыратылуда…"</string>
diff --git a/car-telephony-common/res/values-km/strings.xml b/car-telephony-common/res/values-km/strings.xml
index a483de3..44b7870 100644
--- a/car-telephony-common/res/values-km/strings.xml
+++ b/car-telephony-common/res/values-km/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"កំពុងភ្ជាប់…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"កំពុងហៅ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"រង់ចាំ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"បាន​បញ្ចប់​ការ​ហៅ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"កំពុងរង់ចាំ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"បានបញ្ចប់​ការហៅទូរសព្ទ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"បានភ្ជាប់"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"កំពុង​រោទ៍…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"កំពុង​ផ្ដាច់…"</string>
diff --git a/car-telephony-common/res/values-kn/strings.xml b/car-telephony-common/res/values-kn/strings.xml
index 7b57804..2f04e28 100644
--- a/car-telephony-common/res/values-kn/strings.xml
+++ b/car-telephony-common/res/values-kn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ಡಯಲ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ಹೋಲ್ಡ್‌ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ಕರೆ ಅಂತ್ಯಗೊಂಡಿದೆ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ಹೋಲ್ಡ್‌ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ಕರೆ ಅಂತ್ಯಗೊಂಡಿದೆ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ರಿಂಗ್‍ ಆಗುತ್ತಿದೆ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾ…"</string>
diff --git a/car-telephony-common/res/values-ko/strings.xml b/car-telephony-common/res/values-ko/strings.xml
index 1171186..b210c69 100644
--- a/car-telephony-common/res/values-ko/strings.xml
+++ b/car-telephony-common/res/values-ko/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"연결 중…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"전화 거는 중..."</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"대기 중"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"통화 종료됨"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"대기 중"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"통화 종료됨"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"연결됨"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"벨소리 울리는 중…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"연결 해제 중..."</string>
diff --git a/car-telephony-common/res/values-ky/strings.xml b/car-telephony-common/res/values-ky/strings.xml
index b76e748..599ca63 100644
--- a/car-telephony-common/res/values-ky/strings.xml
+++ b/car-telephony-common/res/values-ky/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Туташууда…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Терилүүдө…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Күтүү режиминде"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Чалуу аяктады"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Күтүү режиминде"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Чалуу аяктады"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Туташты"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Шыңгырап жатат…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Ажыратылууда…"</string>
diff --git a/car-telephony-common/res/values-lo/strings.xml b/car-telephony-common/res/values-lo/strings.xml
index b6cc9df..ec95f01 100644
--- a/car-telephony-common/res/values-lo/strings.xml
+++ b/car-telephony-common/res/values-lo/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ກຳລັງເຊື່ອມຕໍ່…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ກຳລັງໂທ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ຖືສາຍລໍຖ້າ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ວາງສາຍແລ້ວ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ພັກສາຍ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ວາງສາຍແລ້ວ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ກຳລັງດັງ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ກຳລັງຕັດການເຊື່ອມຕໍ່…"</string>
diff --git a/car-telephony-common/res/values-lt/strings.xml b/car-telephony-common/res/values-lt/strings.xml
index ea0508a..550d875 100644
--- a/car-telephony-common/res/values-lt/strings.xml
+++ b/car-telephony-common/res/values-lt/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Prisijungiama…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Renkamas numeris…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Sulaikyta"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Skambutis baigtas"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Sulaikyta"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Skambutis baigtas"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Sujungta"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Skambinama…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Atsijungiama…"</string>
diff --git a/car-telephony-common/res/values-lv/strings.xml b/car-telephony-common/res/values-lv/strings.xml
index 28e49f5..184c937 100644
--- a/car-telephony-common/res/values-lv/strings.xml
+++ b/car-telephony-common/res/values-lv/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Veido savienojumu…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Sastāda numuru…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Aizturēts"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Zvans ir pabeigts"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Aizturēts"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Zvans pabeigts"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Savienots"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvana…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Notiek atvienošana…"</string>
diff --git a/car-telephony-common/res/values-mk/strings.xml b/car-telephony-common/res/values-mk/strings.xml
index b6053e3..c3ef6eb 100644
--- a/car-telephony-common/res/values-mk/strings.xml
+++ b/car-telephony-common/res/values-mk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Се поврзува…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Бирање…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На чекање"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Повикот заврши"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"На чекање"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Повикот заврши"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Поврзан"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ѕвони…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Се исклучува…"</string>
diff --git a/car-telephony-common/res/values-ml/strings.xml b/car-telephony-common/res/values-ml/strings.xml
index e940e9b..85d886c 100644
--- a/car-telephony-common/res/values-ml/strings.xml
+++ b/car-telephony-common/res/values-ml/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"കണക്റ്റ് ചെയ്യുന്നു…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ഡയൽ ചെയ്യുന്നു…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ഹോള്‍ഡിലാണ്"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"കോൾ അവസാനിച്ചു"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ഹോൾഡിലാണ്"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"കോൾ അവസാനിച്ചു"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"കണക്‌റ്റ് ചെയ്‌തു"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"റിംഗ് ചെയ്യുന്നു…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"വിച്ഛേദിക്കുന്നു…"</string>
diff --git a/car-telephony-common/res/values-mn/strings.xml b/car-telephony-common/res/values-mn/strings.xml
index 5fdc776..74956f3 100644
--- a/car-telephony-common/res/values-mn/strings.xml
+++ b/car-telephony-common/res/values-mn/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Холбогдож байна…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Залгаж байна…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Хүлээлгэнд байна"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Дуудлагыг тасалсан"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Хүлээлгэд байгаа"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Дуудлага дууссан"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Холбогдсон"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Дуугарч байна…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Салгаж байна…"</string>
diff --git a/car-telephony-common/res/values-mr/strings.xml b/car-telephony-common/res/values-mr/strings.xml
index 9c7f085..d3036e1 100644
--- a/car-telephony-common/res/values-mr/strings.xml
+++ b/car-telephony-common/res/values-mr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"कनेक्ट करत आहे…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"डायल करत आहे…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"होल्ड वर"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"कॉल संपला"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"होल्डवर आहे"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"कॉल संपला आहे"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"कनेक्ट केले"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"रिंग होत आहे…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"डिस्कनेक्ट करत आहे…"</string>
diff --git a/car-telephony-common/res/values-ms/strings.xml b/car-telephony-common/res/values-ms/strings.xml
index fcde473..038ac0c 100644
--- a/car-telephony-common/res/values-ms/strings.xml
+++ b/car-telephony-common/res/values-ms/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Menyambung…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Mendail…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Ditunda"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Panggilan Tamat"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ditunda"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Panggilan tamat"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Disambungkan"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Berdering…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Memutuskan sambungan…"</string>
diff --git a/car-telephony-common/res/values-my/strings.xml b/car-telephony-common/res/values-my/strings.xml
index 130935a..e2d5565 100644
--- a/car-telephony-common/res/values-my/strings.xml
+++ b/car-telephony-common/res/values-my/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ချိတ်ဆက်နေသည်…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ခေါ်ဆိုနေသည်…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ဖုန်းကိုင်ထားသည်"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ခေါ်ဆိုမှု ပြီးပါပြီ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ဖုန်းကိုင်ထားသည်"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ခေါ်ဆိုမှု ပြီးသွားပါပြီ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ချိတ်ဆက်ထားသည်"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"အသံမြည်နေသည်…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"အဆက်အသွယ် ဖြတ်နေသည်…"</string>
diff --git a/car-telephony-common/res/values-nb/strings.xml b/car-telephony-common/res/values-nb/strings.xml
index 119f352..e6e90b3 100644
--- a/car-telephony-common/res/values-nb/strings.xml
+++ b/car-telephony-common/res/values-nb/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Kobler til …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Slår nummeret …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"På vent"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Anropet er avsluttet"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"På vent"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Anropet er avsluttet"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Tilkoblet"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringer …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Kobler fra …"</string>
diff --git a/car-telephony-common/res/values-ne/strings.xml b/car-telephony-common/res/values-ne/strings.xml
index 331c544..2283a98 100644
--- a/car-telephony-common/res/values-ne/strings.xml
+++ b/car-telephony-common/res/values-ne/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"जोड्दै…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"डायल गर्दै…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"होल्डमा छ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"कल समाप्त भयो"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"होल्डमा छ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"कल समाप्त भयो"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"कनेक्ट गरिएको छ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"घन्टी बज्दै छ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"विच्छेद गर्दै…"</string>
diff --git a/car-telephony-common/res/values-nl/strings.xml b/car-telephony-common/res/values-nl/strings.xml
index 53543e8..c1f4c00 100644
--- a/car-telephony-common/res/values-nl/strings.xml
+++ b/car-telephony-common/res/values-nl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Verbinden…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Kiezen…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"In de wacht"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Gesprek beëindigd"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"In de wacht"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Gesprek beëindigd"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Verbonden"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Gaat over…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Verbreken…"</string>
diff --git a/car-telephony-common/res/values-or/strings.xml b/car-telephony-common/res/values-or/strings.xml
index 775e33c..c95fa40 100644
--- a/car-telephony-common/res/values-or/strings.xml
+++ b/car-telephony-common/res/values-or/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ସଂଯୋଗ ହେଉଛି…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ଡାଏଲ୍ କରାଯାଉଛି…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ହୋଲ୍ଡରେ ଅଛି"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"କଲ୍ ସମାପ୍ତ ହେଲା"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ହୋଲ୍ଡରେ ଅଛି"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"କଲ୍ ଶେଷ ହୋଇଛି"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ସଂଯୋଗ ହୋଇଛି"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ରିଙ୍ଗ ହେଉଛି…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ବିଚ୍ଛିନ୍ନ ହେଉଛି…"</string>
diff --git a/car-telephony-common/res/values-pa/strings.xml b/car-telephony-common/res/values-pa/strings.xml
index 129276b..dcad72f 100644
--- a/car-telephony-common/res/values-pa/strings.xml
+++ b/car-telephony-common/res/values-pa/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"ਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ਡਾਇਲ ਹੋ ਰਿਹਾ ਹੈ…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ਰੋਕ ਕੇ ਰੱਖੀ ਗਈ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ਕਾਲ ਸਮਾਪਤ ਹੋਈ"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ਰੋਕ ਕੇ ਰੱਖੀ ਗਈ"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ਕਾਲ ਸਮਾਪਤ ਹੋਈ"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"ਕਨੈਕਟ ਹੈ"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"ਘੰਟੀ ਵੱਜ ਰਹੀ ਹੈ…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ਡਿਸਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
diff --git a/car-telephony-common/res/values-pl/strings.xml b/car-telephony-common/res/values-pl/strings.xml
index 1212857..7b87eef 100644
--- a/car-telephony-common/res/values-pl/strings.xml
+++ b/car-telephony-common/res/values-pl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Łączę…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Wybieram numer…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Oczekujące"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Koniec połączenia"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Oczekujące"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Połączenie zakończone"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Połączono"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Dzwonię…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Rozłączam…"</string>
diff --git a/car-telephony-common/res/values-pt-rPT/strings.xml b/car-telephony-common/res/values-pt-rPT/strings.xml
index 3b518e6..b0577d0 100644
--- a/car-telephony-common/res/values-pt-rPT/strings.xml
+++ b/car-telephony-common/res/values-pt-rPT/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"A ligar…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"A marcar…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Em espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chamada terminada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Em espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chamada terminada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ligado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"A tocar…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"A desligar…"</string>
diff --git a/car-telephony-common/res/values-pt/strings.xml b/car-telephony-common/res/values-pt/strings.xml
index 1bf5282..f56f6ad 100644
--- a/car-telephony-common/res/values-pt/strings.xml
+++ b/car-telephony-common/res/values-pt/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Conectando…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Chamando...…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Em espera"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chamada encerrada"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Em espera"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chamada encerrada"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectado"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Tocando…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Desconectando…"</string>
diff --git a/car-telephony-common/res/values-ro/strings.xml b/car-telephony-common/res/values-ro/strings.xml
index a9883de..7d78d46 100644
--- a/car-telephony-common/res/values-ro/strings.xml
+++ b/car-telephony-common/res/values-ro/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Se conectează…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Se apelează…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"În așteptare"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Apel încheiat"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"În așteptare"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Apel încheiat"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Conectat"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Sună…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Se deconectează…"</string>
diff --git a/car-telephony-common/res/values-ru/strings.xml b/car-telephony-common/res/values-ru/strings.xml
index 2e37211..6731414 100644
--- a/car-telephony-common/res/values-ru/strings.xml
+++ b/car-telephony-common/res/values-ru/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Подключение…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Набор номера…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На удержании"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Вызов завершен"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Вызов на удержании"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Вызов завершен"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Подключено"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Вызов…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Отключение…"</string>
diff --git a/car-telephony-common/res/values-si/strings.xml b/car-telephony-common/res/values-si/strings.xml
index 399c8d8..b0ac2e8 100644
--- a/car-telephony-common/res/values-si/strings.xml
+++ b/car-telephony-common/res/values-si/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"සබැඳෙමින්…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"අමතමින්…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"රඳවා ඇත"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"ඇමතුම නිමා විය"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"රඳවා ගනිමින්"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"ඇමතුම අවසන් විය"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"සම්බන්ධයි"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"නාද වෙමින්…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"විසන්ධි වෙමින්…"</string>
diff --git a/car-telephony-common/res/values-sk/strings.xml b/car-telephony-common/res/values-sk/strings.xml
index 83721d3..0aeef23 100644
--- a/car-telephony-common/res/values-sk/strings.xml
+++ b/car-telephony-common/res/values-sk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Pripája sa…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Vytáča sa…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Podržané"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Hovor bol ukončený"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Podržaný hovor"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Hovor bol ukončený"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Pripojené"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Prezváňa sa…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Odpája sa…"</string>
diff --git a/car-telephony-common/res/values-sl/strings.xml b/car-telephony-common/res/values-sl/strings.xml
index 03a7063..ce84056 100644
--- a/car-telephony-common/res/values-sl/strings.xml
+++ b/car-telephony-common/res/values-sl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Povezovanje …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Klicanje …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Zadržan"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Klic je bil končan"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Na čakanju"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Klic je končan"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Povezano"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zvonjenje …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Prekin. povezave …"</string>
diff --git a/car-telephony-common/res/values-sq/strings.xml b/car-telephony-common/res/values-sq/strings.xml
index f6439eb..87af7f4 100644
--- a/car-telephony-common/res/values-sq/strings.xml
+++ b/car-telephony-common/res/values-sq/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Po lidhet…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Po formon numrin…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Në pritje"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Telefonata përfundoi"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Në pritje"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Telefonata përfundoi"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Lidhur"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Po bie zilja…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Po shkëputet…"</string>
diff --git a/car-telephony-common/res/values-sr/strings.xml b/car-telephony-common/res/values-sr/strings.xml
index 1f3837f..4b48d1a 100644
--- a/car-telephony-common/res/values-sr/strings.xml
+++ b/car-telephony-common/res/values-sr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Повезује се…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Позива се…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"На чекању"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Позив је завршен"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"На чекању"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Позив је завршен"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Повезан"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Звони…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Прекида се веза…"</string>
diff --git a/car-telephony-common/res/values-sv/strings.xml b/car-telephony-common/res/values-sv/strings.xml
index f4b9b1a..2aff4e7 100644
--- a/car-telephony-common/res/values-sv/strings.xml
+++ b/car-telephony-common/res/values-sv/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ansluter …"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Ringer upp …"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Parkerat"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Samtal avslutat"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Parkerat"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Samtal avslutat"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ansluten"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Ringer …"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Kopplar från …"</string>
diff --git a/car-telephony-common/res/values-sw/strings.xml b/car-telephony-common/res/values-sw/strings.xml
index 18a33e0..28a496b 100644
--- a/car-telephony-common/res/values-sw/strings.xml
+++ b/car-telephony-common/res/values-sw/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Inaunganisha…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Inapiga…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Imesitishwa"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Simu Imekamilika"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Imesitishwa"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Simu imekamilika"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Imeunganisha"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Inalia…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Inakata…"</string>
diff --git a/car-telephony-common/res/values-ta/strings.xml b/car-telephony-common/res/values-ta/strings.xml
index d835fab..d6bb4c9 100644
--- a/car-telephony-common/res/values-ta/strings.xml
+++ b/car-telephony-common/res/values-ta/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"இணைக்கிறது…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"டயல் செய்கிறது…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"காத்திருப்பில்"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"அழைப்பு முடிந்தது"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ஹோல்டில் உள்ளது"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"அழைப்பு முடிந்தது"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"இணைக்கப்பட்டது"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"அழைக்கிறது…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"துண்டிக்கிறது…"</string>
diff --git a/car-telephony-common/res/values-te/strings.xml b/car-telephony-common/res/values-te/strings.xml
index 2ebcb08..39975e4 100644
--- a/car-telephony-common/res/values-te/strings.xml
+++ b/car-telephony-common/res/values-te/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"కనెక్ట్ అవుతోంది…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"డయల్ చేస్తోంది…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"హోల్డ్‌లో ఉంది"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"కాల్ ముగిసింది"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"హోల్డ్‌లో ఉంది"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"కాల్ ముగిసింది"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"కనెక్ట్ చేయబడింది"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"రింగ్ అవుతోంది…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"డిస్కనెక్టవుతోంది…"</string>
diff --git a/car-telephony-common/res/values-th/strings.xml b/car-telephony-common/res/values-th/strings.xml
index e627b44..6b5a368 100644
--- a/car-telephony-common/res/values-th/strings.xml
+++ b/car-telephony-common/res/values-th/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"กำลังเชื่อมต่อ…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"กำลังโทรออก…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"พักสาย"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"วางสายแล้ว"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"พักสาย"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"วางสายแล้ว"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"เชื่อมต่อแล้ว"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"กำลังส่งเสียง…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"ยกเลิกการโทรออก…"</string>
diff --git a/car-telephony-common/res/values-tl/strings.xml b/car-telephony-common/res/values-tl/strings.xml
index f5f02ef..2bdda5c 100644
--- a/car-telephony-common/res/values-tl/strings.xml
+++ b/car-telephony-common/res/values-tl/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Kumokonekta…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Dina-dial…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Naka-hold"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Natapos ang Tawag"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Naka-hold"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Tinapos ang tawag"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Nakakonekta"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Nagri-ring…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Dinidiskonekta…"</string>
diff --git a/car-telephony-common/res/values-tr/strings.xml b/car-telephony-common/res/values-tr/strings.xml
index 8da8d62..dc05ebf 100644
--- a/car-telephony-common/res/values-tr/strings.xml
+++ b/car-telephony-common/res/values-tr/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Bağlanıyor…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Numara çevriliyor…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Beklemede"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Çağrı Sonlandırıldı"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Beklemede"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Çağrı sonlandırıldı"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Bağlandı"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Zil çaldırılıyor…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Bağlantı kesiliyor…"</string>
diff --git a/car-telephony-common/res/values-uk/strings.xml b/car-telephony-common/res/values-uk/strings.xml
index 6c05db2..f72fa83 100644
--- a/car-telephony-common/res/values-uk/strings.xml
+++ b/car-telephony-common/res/values-uk/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"З’єднання…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Набір номера…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Утримується"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Виклик завершено"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Утримується"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Виклик завершено"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Під’єднано"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Дзвінок…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Від’єднання…"</string>
diff --git a/car-telephony-common/res/values-ur/strings.xml b/car-telephony-common/res/values-ur/strings.xml
index 92dfe09..3deac0b 100644
--- a/car-telephony-common/res/values-ur/strings.xml
+++ b/car-telephony-common/res/values-ur/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"منسلک ہو رہا ہے…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"ڈائل کر رہا ہے…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"ہولڈ پر ہے"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"کال ختم ہوگئی"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"ہولڈ پر ہے"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"کال ختم ہو گئی"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"منسلک ہے"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"گھنٹی بج رہی ہے…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"غیر منسلک ہو رہا ہے…"</string>
diff --git a/car-telephony-common/res/values-uz/strings.xml b/car-telephony-common/res/values-uz/strings.xml
index 2683304..a818836 100644
--- a/car-telephony-common/res/values-uz/strings.xml
+++ b/car-telephony-common/res/values-uz/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Ulanmoqda…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Raqam terilmoqda…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Kutish holatida"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Chaqiruv yakunlandi"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Pauzada"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Chaqiruv tugadi"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ulandi"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Jiringlamoqda…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Uzilmoqda…"</string>
diff --git a/car-telephony-common/res/values-vi/strings.xml b/car-telephony-common/res/values-vi/strings.xml
index e52194a..d0dc77b 100644
--- a/car-telephony-common/res/values-vi/strings.xml
+++ b/car-telephony-common/res/values-vi/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Đang kết nối…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Đang quay số..."</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Đang chờ"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Cuộc gọi đã kết thúc"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Đang giữ máy"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Cuộc gọi đã kết thúc"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Đã kết nối"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Đang đổ chuông..."</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Đang ngắt kết nối…"</string>
diff --git a/car-telephony-common/res/values-zh-rCN/strings.xml b/car-telephony-common/res/values-zh-rCN/strings.xml
index 04631c8..0c2fc09 100644
--- a/car-telephony-common/res/values-zh-rCN/strings.xml
+++ b/car-telephony-common/res/values-zh-rCN/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"正在连接…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"正在拨号…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"呼叫等待"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通话已结束"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保持"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通话已结束"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"已连接"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"正在响铃…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"正在断开连接…"</string>
diff --git a/car-telephony-common/res/values-zh-rHK/strings.xml b/car-telephony-common/res/values-zh-rHK/strings.xml
index c92766e..6872577 100644
--- a/car-telephony-common/res/values-zh-rHK/strings.xml
+++ b/car-telephony-common/res/values-zh-rHK/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"正在連接…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"正在撥號…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"保留通話"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通話已結束"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保留通話"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通話已結束"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"已連接"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"正在發出鈴聲…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"正在解除連接…"</string>
diff --git a/car-telephony-common/res/values-zh-rTW/strings.xml b/car-telephony-common/res/values-zh-rTW/strings.xml
index decc1db..41928bb 100644
--- a/car-telephony-common/res/values-zh-rTW/strings.xml
+++ b/car-telephony-common/res/values-zh-rTW/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"連線中…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"撥號中…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"保留中"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"通話結束"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"保留中"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"通話已結束"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"已連線"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"鈴響中…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"正在中斷連線…"</string>
diff --git a/car-telephony-common/res/values-zu/strings.xml b/car-telephony-common/res/values-zu/strings.xml
index 0978e00..fa90708 100644
--- a/car-telephony-common/res/values-zu/strings.xml
+++ b/car-telephony-common/res/values-zu/strings.xml
@@ -21,8 +21,8 @@
     <string name="phone_label_with_info" msgid="4652109530699808645">"<xliff:g id="LABEL">%1$s</xliff:g>  ·  <xliff:g id="DURATION">%2$s</xliff:g>"</string>
     <string name="call_state_connecting" msgid="5930724746375294866">"Iyaxhuma…"</string>
     <string name="call_state_dialing" msgid="1534599871716648114">"Iyadayela…"</string>
-    <string name="call_state_hold" msgid="6834028102796624100">"Ibanjiwe"</string>
-    <string name="call_state_call_ended" msgid="4159349597599886429">"Ikholi iqediwe"</string>
+    <string name="call_state_hold" msgid="8063542005458186874">"Ibambile"</string>
+    <string name="call_state_call_ended" msgid="1432127342949555464">"Ikholi iqediwe"</string>
     <string name="call_state_call_active" msgid="2769644783657864202">"Ixhunyiwe"</string>
     <string name="call_state_call_ringing" msgid="4618803402954375017">"Iyakhala…"</string>
     <string name="call_state_call_ending" msgid="5037498349965472247">"Iyanqamula…"</string>
diff --git a/car-telephony-common/res/values/strings.xml b/car-telephony-common/res/values/strings.xml
index 9bb8811..89ec0f1 100644
--- a/car-telephony-common/res/values/strings.xml
+++ b/car-telephony-common/res/values/strings.xml
@@ -32,9 +32,9 @@
     <!-- Status label for phone state. &#8230; is an ellipsis. [CHAR LIMIT=25] -->
     <string name="call_state_dialing">Dialing&#8230;</string>
     <!-- Status label for phone state [CHAR LIMIT=25] -->
-    <string name="call_state_hold">On Hold</string>
+    <string name="call_state_hold">On hold</string>
     <!-- Status label for phone state [CHAR LIMIT=25] -->
-    <string name="call_state_call_ended">Call Ended</string>
+    <string name="call_state_call_ended">Call ended</string>
     <!-- Status label for phone state [CHAR LIMIT=25] -->
     <string name="call_state_call_active">Connected</string>
     <!-- Status label for phone state. &#8230; is an ellipsis. [CHAR LIMIT=25] -->
diff --git a/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java b/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java
index 83f3291..04fc4bd 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/CallDetail.java
@@ -32,13 +32,16 @@
     private final CharSequence mDisconnectCause;
     private final Uri mGatewayInfoOriginalAddress;
     private final long mConnectTimeMillis;
+    private final boolean mIsConference;
 
     private CallDetail(String number, CharSequence disconnectCause,
-                       Uri gatewayInfoOriginalAddress, long connectTimeMillis) {
+                       Uri gatewayInfoOriginalAddress, long connectTimeMillis,
+                       boolean isConference) {
         mNumber = number;
         mDisconnectCause = disconnectCause;
         mGatewayInfoOriginalAddress = gatewayInfoOriginalAddress;
         this.mConnectTimeMillis = connectTimeMillis;
+        mIsConference = isConference;
     }
 
     /**
@@ -46,7 +49,8 @@
      */
     public static CallDetail fromTelecomCallDetail(@Nullable Call.Details callDetail) {
         return new CallDetail(getNumber(callDetail), getDisconnectCause(callDetail),
-                getGatewayInfoOriginalAddress(callDetail), getConnectTimeMillis(callDetail));
+                getGatewayInfoOriginalAddress(callDetail), getConnectTimeMillis(callDetail),
+                isConferenceCall(callDetail));
     }
 
     /**
@@ -80,6 +84,13 @@
         return mConnectTimeMillis;
     }
 
+    /**
+     * Returns whether the call is a conference.
+     */
+    public boolean isConference() {
+        return mIsConference;
+    }
+
     private static String getNumber(Call.Details callDetail) {
         String number = "";
         if (callDetail == null) {
@@ -115,4 +126,8 @@
             return 0;
         }
     }
+
+    private static boolean isConferenceCall(Call.Details callDetail) {
+        return callDetail != null && callDetail.hasProperty(Call.Details.PROPERTY_CONFERENCE);
+    }
 }
diff --git a/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java b/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java
index 6ef5f21..8ed7e73 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/InMemoryPhoneBook.java
@@ -20,7 +20,6 @@
 import android.database.Cursor;
 import android.provider.ContactsContract;
 import android.text.TextUtils;
-
 import android.util.ArrayMap;
 
 import androidx.annotation.NonNull;
@@ -170,7 +169,7 @@
      */
     @Nullable
     public Contact lookupContactEntry(String phoneNumber) {
-        L.v(TAG, String.format("lookupContactEntry: %s", phoneNumber));
+        L.v(TAG, String.format("lookupContactEntry: %s", TelecomUtils.piiLog(phoneNumber)));
         if (!isLoaded()) {
             L.w(TAG, "looking up a contact while loading.");
         }
diff --git a/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java b/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java
index 02c0808..a1e25f2 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/PhoneCallLog.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.provider.CallLog;
-import android.telecom.Log;
 import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
@@ -172,7 +171,7 @@
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("PhoneNumber: ");
-        sb.append(Log.pii(mPhoneNumberString));
+        sb.append(TelecomUtils.piiLog(mPhoneNumberString));
         sb.append(" CallLog: ");
         sb.append(mCallRecords.size());
         sb.append(" Account: ");
diff --git a/car-telephony-common/src/com/android/car/telephony/common/PhoneNumber.java b/car-telephony-common/src/com/android/car/telephony/common/PhoneNumber.java
index 4e3eff6..255def0 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/PhoneNumber.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/PhoneNumber.java
@@ -23,7 +23,6 @@
 import android.os.Parcelable;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -107,8 +106,8 @@
         mLabel = label;
         mIsPrimary = isPrimary;
         mId = id;
-        mAccountName = TextUtils.emptyIfNull(accountName);
-        mAccountType = TextUtils.emptyIfNull(accountType);
+        mAccountName = accountName == null ? "" : accountName;
+        mAccountType = accountType == null ? "" : accountType;
         mDataVersion = dataVersion;
     }
 
diff --git a/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java b/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java
index 7de3be6..a3d4862 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/PostalAddress.java
@@ -24,10 +24,10 @@
 import android.provider.ContactsContract;
 
 import androidx.annotation.Nullable;
+
 import com.android.car.apps.common.NavigationUtils;
 import com.android.car.apps.common.log.L;
 
-
 /**
  * Encapsulates data about an address entry. Typically loaded from the local Address store.
  */
@@ -106,19 +106,18 @@
     }
 
     /**
-     * Returns the address Intent for {@link #mFormattedAddress}.
+     * Returns the address Uri for {@link #mFormattedAddress}.
      */
     public Intent getAddressIntent(Resources res) {
-        L.d(TAG, "Get address intent");
+        L.d(TAG, "The address is: " + TelecomUtils.piiLog(mFormattedAddress));
         return NavigationUtils.getViewAddressIntent(res, mFormattedAddress);
     }
 
     /**
-     * Returns the navigation Intent for {@link #mFormattedAddress}.
+     * Returns the navigation Uri for {@link #mFormattedAddress}.
      */
-
     public Intent getNavigationIntent(Resources res) {
-        L.d(TAG, "Get navigation intent");
+        L.d(TAG, "The address is: " + TelecomUtils.piiLog(mFormattedAddress));
         return NavigationUtils.getNavigationIntent(res, mFormattedAddress);
     }
 
diff --git a/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java b/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java
index 1d934ec..40d93a7 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/TelecomUtils.java
@@ -27,8 +27,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Icon;
-import android.location.Country;
-import android.location.CountryDetector;
 import android.net.Uri;
 import android.provider.CallLog;
 import android.provider.ContactsContract;
@@ -67,6 +65,8 @@
  */
 public class TelecomUtils {
     private static final String TAG = "CD.TelecomUtils";
+    private static final int PII_STRING_LENGTH = 4;
+    private static final String COUNTRY_US = "US";
     /**
      * A reference to keep track of the soring method of sorting by the contact's first name.
      */
@@ -123,18 +123,18 @@
      * Format a number as a phone number.
      */
     public static String getFormattedNumber(Context context, String number) {
-        L.d(TAG, "getFormattedNumber: " + number);
+        L.d(TAG, "getFormattedNumber: " + piiLog(number));
         if (number == null) {
             return "";
         }
 
-        String countryIso = getCurrentCountryIso(context);
-        L.d(TAG, "PhoneNumberUtils.formatNumber, number: " + number
-                    + ", country: " + countryIso);
+        String countryIso = getCurrentCountryIsoFromLocale(context);
+        L.d(TAG, "PhoneNumberUtils.formatNumber, number: " + piiLog(number)
+                + ", country: " + countryIso);
 
         String formattedNumber = PhoneNumberUtils.formatNumber(number, countryIso);
         formattedNumber = TextUtils.isEmpty(formattedNumber) ? number : formattedNumber;
-        L.d(TAG, "getFormattedNumber, result: " + formattedNumber);
+        L.d(TAG, "getFormattedNumber, result: " + piiLog(formattedNumber));
 
         return formattedNumber;
     }
@@ -143,25 +143,10 @@
      * @return The ISO 3166-1 two letters country code of the country the user is in.
      */
     private static String getCurrentCountryIso(Context context, Locale locale) {
-        String countryIso = null;
-        CountryDetector detector = (CountryDetector) context.getSystemService(
-                Context.COUNTRY_DETECTOR);
-        if (detector != null) {
-            Country country = detector.detectCountry();
-            if (country != null) {
-                countryIso = country.getCountryIso();
-            } else {
-                L.e(TAG, "CountryDetector.detectCountry() returned null.");
-            }
-        }
-        if (countryIso == null) {
-            countryIso = locale.getCountry();
-            L.w(TAG, "No CountryDetector; falling back to countryIso based on locale: "
-                    + countryIso);
-        }
+        String countryIso = locale.getCountry();
         if (countryIso == null || countryIso.length() != 2) {
             L.w(TAG, "Invalid locale, falling back to US");
-            countryIso = "US";
+            countryIso = COUNTRY_US;
         }
         return countryIso;
     }
@@ -170,6 +155,18 @@
         return getCurrentCountryIso(context, Locale.getDefault());
     }
 
+    private static String getCurrentCountryIsoFromLocale(Context context) {
+        String countryIso;
+        countryIso = context.getResources().getConfiguration().getLocales().get(0).getCountry();
+
+        if (countryIso == null) {
+            L.w(TAG, "Invalid locale, falling back to US");
+            countryIso = COUNTRY_US;
+        }
+
+        return countryIso;
+    }
+
     /**
      * Creates a new instance of {@link Phonenumber.PhoneNumber} base on the given number and sim
      * card country code. Returns {@code null} if the number in an invalid number.
@@ -511,6 +508,24 @@
      * valid, it will mark all new missed call log as read.
      */
     public static void markCallLogAsRead(Context context, String phoneNumberString) {
+        markCallLogAsRead(context, CallLog.Calls.NUMBER, phoneNumberString);
+    }
+
+    /**
+     * Mark missed call log matching given call log id as read. If phone number string is not
+     * valid, it will mark all new missed call log as read.
+     */
+    public static void markCallLogAsRead(Context context, long callLogId) {
+        markCallLogAsRead(context, CallLog.Calls._ID,
+                callLogId < 0 ? null : String.valueOf(callLogId));
+    }
+
+    /**
+     * Mark missed call log matching given column name and selection argument as read. If the column
+     * name or the selection argument is not valid, mark all new missed call log as read.
+     */
+    private static void markCallLogAsRead(Context context, String columnName,
+            String selectionArg) {
         if (context.checkSelfPermission(Manifest.permission.WRITE_CALL_LOG)
                 != PackageManager.PERMISSION_GRANTED) {
             L.w(TAG, "Missing WRITE_CALL_LOG permission; not marking missed calls as read.");
@@ -527,21 +542,22 @@
         where.append(CallLog.Calls.TYPE);
         where.append(" = ?");
         selectionArgs.add(Integer.toString(CallLog.Calls.MISSED_TYPE));
-        if (!TextUtils.isEmpty(phoneNumberString)) {
+        if (!TextUtils.isEmpty(columnName) && !TextUtils.isEmpty(selectionArg)) {
             where.append(" AND ");
-            where.append(CallLog.Calls.NUMBER);
+            where.append(columnName);
             where.append(" = ?");
-            selectionArgs.add(phoneNumberString);
+            selectionArgs.add(selectionArg);
         }
         String[] selectionArgsArray = new String[0];
         try {
-            context
-                    .getContentResolver()
-                    .update(
-                            CallLog.Calls.CONTENT_URI,
-                            contentValues,
-                            where.toString(),
-                            selectionArgs.toArray(selectionArgsArray));
+            ContentResolver contentResolver = context.getContentResolver();
+            contentResolver.update(
+                    CallLog.Calls.CONTENT_URI,
+                    contentValues,
+                    where.toString(),
+                    selectionArgs.toArray(selectionArgsArray));
+            // #update doesn't notify change any more. Notify change to rerun query from database.
+            contentResolver.notifyChange(CallLog.Calls.CONTENT_URI, null);
         } catch (IllegalArgumentException e) {
             L.e(TAG, "markCallLogAsRead failed", e);
         }
@@ -604,12 +620,22 @@
     private static Uri makeResourceUri(Context context, int resourceId) {
         return new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                .encodedAuthority(context.getBasePackageName())
+                .encodedAuthority(context.getPackageName())
                 .appendEncodedPath(String.valueOf(resourceId))
                 .build();
     }
 
     /**
+     * This is a workaround for Log.Pii(). It will only show the last {@link #PII_STRING_LENGTH}
+     * characters.
+     */
+    public static String piiLog(Object pii) {
+        String piiString = String.valueOf(pii);
+        return piiString.length() >= PII_STRING_LENGTH ? "*" + piiString.substring(
+                piiString.length() - PII_STRING_LENGTH) : piiString;
+    }
+
+    /**
      * Returns true if contacts are sorted by their first names. Returns false if they are sorted by
      * last names.
      */
diff --git a/car-telephony-common/tests/Android.mk b/car-telephony-common/tests/Android.mk
deleted file mode 100644
index 0903c90..0000000
--- a/car-telephony-common/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-telephony-common/tests/robotests/Android.bp b/car-telephony-common/tests/robotests/Android.bp
new file mode 100644
index 0000000..57bf759
--- /dev/null
+++ b/car-telephony-common/tests/robotests/Android.bp
@@ -0,0 +1,27 @@
+//###########################################################
+// car-telephony-common just for Robolectric test target.   #
+//###########################################################
+android_app {
+    name: "CarTelephonyCommonForTesting",
+
+    platform_apis: true,
+
+    libs: ["android.car"],
+
+    privileged: true,
+
+    static_libs: ["car-telephony-common"],
+}
+
+//############################################################
+// car-telephony-common Robolectric test target.             #
+//############################################################
+android_robolectric_test {
+    name: "CarTelephonyCommonRoboTests",
+
+    srcs: ["src/**/*.java"],
+
+    java_resource_dirs: ["config"],
+
+    instrumentation_for: "CarTelephonyCommonForTesting",
+}
diff --git a/car-telephony-common/tests/robotests/Android.mk b/car-telephony-common/tests/robotests/Android.mk
deleted file mode 100644
index e67530d..0000000
--- a/car-telephony-common/tests/robotests/Android.mk
+++ /dev/null
@@ -1,68 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-
-############################################################
-# car-telephony-common just for Robolectric test target.   #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := CarTelephonyCommonForTesting
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := car-telephony-common
-
-include $(BUILD_PACKAGE)
-
-#############################################################
-# car-telephony-common Robolectric test target.             #
-#############################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarTelephonyCommonRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-LOCAL_INSTRUMENTATION_FOR := CarTelephonyCommonForTesting
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# car-telephony-common runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarTelephonyCommonRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    CarTelephonyCommonRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    truth-prebuilt
-
-
-LOCAL_TEST_PACKAGE := CarTelephonyCommonForTesting
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-telephony-common/tests/robotests/config/robolectric.properties b/car-telephony-common/tests/robotests/config/robolectric.properties
index 9228597..fc4f8ca 100644
--- a/car-telephony-common/tests/robotests/config/robolectric.properties
+++ b/car-telephony-common/tests/robotests/config/robolectric.properties
@@ -11,5 +11,4 @@
 # 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.
-manifest=packages/apps/Car/libs/car-telephony-common/tests/robotests/AndroidManifest.xml
 sdk=NEWEST_SDK
diff --git a/car-theme-lib/Android.bp b/car-theme-lib/Android.bp
index 990148c..30c780c 100644
--- a/car-theme-lib/Android.bp
+++ b/car-theme-lib/Android.bp
@@ -15,7 +15,7 @@
 //
 
 android_library {
-    name: "car-theme-lib-bp",
+    name: "car-theme-lib",
 
     srcs: ["src/**/*.java"],
 
@@ -26,5 +26,4 @@
     optimize: {
         enabled: false,
     },
-
 }
diff --git a/car-theme-lib/Android.mk b/car-theme-lib/Android.mk
deleted file mode 100644
index c22048c..0000000
--- a/car-theme-lib/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-theme-lib
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/car-ui-lib/.gitignore b/car-ui-lib/.gitignore
index cedb234..a6be7ed 100644
--- a/car-ui-lib/.gitignore
+++ b/car-ui-lib/.gitignore
@@ -13,3 +13,6 @@
 
 # Python
 *.pyc
+
+# Android studio's layout inspector captures
+captures/
diff --git a/car-ui-lib/Android.bp b/car-ui-lib/Android.bp
index ac82b7b..4e59773 100644
--- a/car-ui-lib/Android.bp
+++ b/car-ui-lib/Android.bp
@@ -1,5 +1,4 @@
 
-//
 // Copyright (C) 2019 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,40 +14,140 @@
 // limitations under the License.
 
 android_library {
-
-    name: "car-ui-lib-bp",
-
-    srcs: ["src/**/*.java"],
-
-    resource_dirs: ["res"],
-
+    name: "car-ui-lib",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    srcs: ["car-ui-lib/src/main/java/**/*.java"],
+    manifest: "car-ui-lib/AndroidManifest.xml",
+    resource_dirs: ["car-ui-lib/src/main/res"],
     optimize: {
         enabled: false,
     },
-
-    libs: ["android.car"],
-
+    libs: ["android.car-stubs"],
     static_libs: [
         "androidx.annotation_annotation",
         "androidx.appcompat_appcompat",
-        "androidx.asynclayoutinflater_asynclayoutinflater",
         "androidx-constraintlayout_constraintlayout",
         "androidx.preference_preference",
         "androidx.recyclerview_recyclerview",
         "androidx-constraintlayout_constraintlayout-solver",
+        "androidx.asynclayoutinflater_asynclayoutinflater",
     ],
 }
 
 // User this if your project includes overlayable.xml
 android_library {
-
-    name: "car-ui-lib-bp-overlayable",
-
+    name: "car-ui-lib-overlayable",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    manifest: "car-ui-lib/AndroidManifest.xml",
     resource_dirs: [
-        "res-overlayable"
+        "car-ui-lib/src/main/res-overlayable"
+    ],
+    static_libs: [
+        "car-ui-lib",
+    ],
+    // This is also needed for `car-ui-lib` build target.
+    // But it's not in explicitly added to the build rule,
+    // Because it's hardcoded in apex.go file under Soong.
+    apex_available: [
+        "com.android.permission"
+    ],
+}
+
+android_app {
+    name: "car-ui-lib-sharedlibrary",
+    srcs: ["sharedlibrary/src/main/java/**/*.java"],
+    manifest: "sharedlibrary/AndroidManifest.xml",
+    resource_dirs: ["sharedlibrary/src/main/res"],
+    visibility: [
+        "//visibility:private",
+    ],
+    platform_apis: true,
+    aaptflags: ["--shared-lib"],
+    optimize: {
+        enabled: false,
+    },
+}
+
+android_library {
+    name: "car-ui-lib-testing-support",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    manifest: "car-ui-lib/AndroidManifest.xml",
+    srcs: [
+        "tests/baselayouttests/src/**/*.java",
+    ],
+    optimize: {
+        enabled: false,
+    },
+    libs: ["android.car-stubs"],
+    static_libs: [
+        "car-ui-lib",
+        "Robolectric_all-target",
+    ],
+}
+
+android_test {
+    name: "CarUILibUnitTests",
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.car"
+    ],
+    manifest: "car-ui-lib/src/androidTest/AndroidManifest.xml",
+    resource_dirs: ["car-ui-lib/src/androidTest/res"],
+    // Include all test java files.
+    srcs: ["car-ui-lib/src/androidTest/java/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.espresso.core",
+        "androidx.test.espresso.contrib",
+        "androidx.test.ext.junit",
+        "car-ui-lib",
+        "platform-test-annotations",
+        "mockito-target-inline-minus-junit4",
+        "truth-prebuilt",
+    ],
+    jni_libs: [
+        // For mockito extended
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
     ],
 
-    static_libs: [
-        "car-ui-lib-bp",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+}
+
+android_app {
+    name: "PaintBooth",
+    srcs: [
+    	"paintbooth/src/**/*.java",
+    	"paintbooth/src/**/*.kt",
     ],
+    required: ["privapp_whitelist_com.android.car.ui.paintbooth"],
+    manifest: "paintbooth/AndroidManifest.xml",
+    resource_dirs: ["paintbooth/src/main/res", "paintbooth/src/main/res-public"],
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
+    static_libs: [
+        "car-ui-lib",
+        "android.car.userlib",
+	"guava",
+	"gson-prebuilt-jar",
+    ],
+    optimize: {
+        enabled: false,
+    },
+    dex_preopt: {
+        enabled: false,
+    },
+    product_variables: {
+        pdk: {
+            enabled: false,
+        },
+    },
+    export_package_resources: true,
 }
diff --git a/car-ui-lib/Android.mk b/car-ui-lib/Android.mk
index c67ea5c..1df872c 100644
--- a/car-ui-lib/Android.mk
+++ b/car-ui-lib/Android.mk
@@ -30,45 +30,9 @@
 #
 # Your AndroidManifest must use {{TARGET_PACKAGE_NAME}} and {{RRO_PACKAGE_NAME}}
 # tags, which will be replaced accordingly during build.
-
-CAR_UI_GENERATE_RRO_SET := $(call my-dir)/generate_rros.mk
-
-# Build car-ui library
-
 LOCAL_PATH:= $(call my-dir)
 
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_MODULE := car-ui-lib
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_JAVA_LIBRARIES += android.car
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_ANDROID_LIBRARIES += \
-    androidx.annotation_annotation \
-    androidx.appcompat_appcompat \
-    androidx-constraintlayout_constraintlayout \
-    androidx.preference_preference \
-    androidx.recyclerview_recyclerview \
-    androidx.asynclayoutinflater_asynclayoutinflater \
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    androidx-constraintlayout_constraintlayout-solver \
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
+CAR_UI_GENERATE_RRO_SET := $(call my-dir)/generate_rros.mk
 
 ifeq (,$(ONE_SHOT_MAKEFILE))
     include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/car-ui-lib/AndroidManifest-gradle.xml b/car-ui-lib/AndroidManifest-gradle.xml
deleted file mode 100644
index b6e8ee6..0000000
--- a/car-ui-lib/AndroidManifest-gradle.xml
+++ /dev/null
@@ -1,20 +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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.ui">
-</manifest>
diff --git a/car-ui-lib/AndroidManifest.xml b/car-ui-lib/AndroidManifest.xml
deleted file mode 100644
index 038ee67..0000000
--- a/car-ui-lib/AndroidManifest.xml
+++ /dev/null
@@ -1,23 +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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.ui">
-  <uses-sdk
-      android:minSdkVersion="14"
-      android:targetSdkVersion="28" />
-</manifest>
diff --git a/car-ui-lib/README.md b/car-ui-lib/README.md
index 282f8e1..3be5f68 100644
--- a/car-ui-lib/README.md
+++ b/car-ui-lib/README.md
@@ -2,14 +2,48 @@
 Components and resources designed to increase Automotive UI consistency between
 GAS (Google Automotive Services) apps, system-apps and OEM developed apps.
 
-See: go/aae-carui
+See: go/aae-chassis-site
 
 ## Content
 
 Components and resources designed to be configured by means of RRO (Runtime
 Resource Overlays) by OEMs.
 
-## Updating
+## Developing
+
+Project layout:
+* __car-ui-lib__: The main library that is statically linked into applications
+* __paintbooth__: A test application that contains demos of all the car-ui components
+* __referencedesign__: An RRO applied to internal google targets that does some minor car-ui customizations. It's used to make changes to car-ui that would cause backwards compatability issues if we were to create them directly in the library. It can also serve as an example RRO for OEMs, and should be kept reasonably functional and up-to-date because we use it actively.
+
+### Building and running PaintBooth
+
+While car-ui-lib can be developed by using aidegen, it's probably easier to use Android Studio with the gradle build files. To do this, select "Open an existing Android Studio project", then navigating to the (outer) car-ui-lib folder:
+
+![Open an existing Android Studio project](documentation/images/open_existing_android_studio_project.png)
+![Navigating to car-ui-lib](documentation/images/navigating_to_car_ui_lib.png)
+
+If this is your first time using Android Studio, it may ask you to install an SDK. Go ahead and do that.
+
+It may ask if you want to generate the gradle wrapper files, select "Yes". Wait for it to finish indexing, and then you should see car-ui-lib and PaintBooth projects in the project pane on the left. Make sure your project view is set to "Android" mode, as opposed to the regular "Project" mode:
+
+![Android project view](documentation/images/android_project_view.png)
+
+To launch paintbooth, start a car emulator or connect a device, make sure the PaintBooth module and "Virtual Device" is selected in your Android Studio toolbar, then click the green arrow:
+
+![Launching Paintbooth](documentation/images/launch_paintbooth.png)
+
+If it launches a LeakCanary activity instead of PaintBooth, either exit LeakCanary and launch PaintBooth as normal through the car's launcher, or click on the PaintBooth module > Edit configurations > Change "Launch: Default Activity" to "Specified Activity", and enter `com.android.car.ui.paintbooth.MainActivity`.
+
+### Running tests
+
+Once you've set up paintbooth as described above, just open one of the test classes in car-ui-lib > java > com.android.car.ui (androidTest) and click the green arrow next to one of the tests to run it:
+
+![Running tests](documentation/images/running_tests.png)
+
+The tests can also be run from the command line via `atest CarUILibUnitTests`, but that's much slower than running them through Android Studio.
+
+## Updating Google3
 
 This library is developed in Gerrit and copied as source to Google3 using
 Copybara (go/copybara).
@@ -20,9 +54,13 @@
 Here is the process for updating this library:
 
 1. Develop, test and upload changes to Gerrit
-2. On Google3, run './update.sh review <cl>' (with <cl> being your Gerrit CL #) and test your changes
+2. On Google3, run `./update.sh review <cl>` (with <cl> being your Gerrit CL #) and test your changes
 3. Repeat #1 and #2 until your changes look okay on both places.
 4. Back on Gerrit, submit your CL.
-5. Back on Google3, run './update.sh manual' submit
+5. Back on Google3, run `./update.sh manual` submit
 
 TODO: Automate this process using CaaS (in progress)
+
+If you're just updating the current state of car-ui-lib, and not testing a review that has yet to be submitted, the process can be simplified to:
+
+`/google/data/ro/teams/copybara/copybara /google/src/head/depot/google3/third_party/java_src/android_libs/car_chassis_lib/copy.bara.sky default`
diff --git a/car-ui-lib/build.gradle b/car-ui-lib/build.gradle
index edbed36..9744622 100644
--- a/car-ui-lib/build.gradle
+++ b/car-ui-lib/build.gradle
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -23,7 +23,7 @@
 
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.5.1'
+        classpath 'com.android.tools.build:gradle:3.6.1'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
@@ -35,47 +35,8 @@
         google()
         jcenter()
     }
-    buildDir = "/tmp/car-ui-build/${rootProject.name}/${project.name}"
     tasks.withType(JavaCompile) {
         options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
     }
 }
 
-// Library-level build file
-
-apply plugin: 'com.android.library'
-
-android {
-    compileSdkVersion 29
-
-    defaultConfig {
-        minSdkVersion 28
-        targetSdkVersion 29
-        versionCode 1
-        versionName "1.0"
-    }
-
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-
-    sourceSets {
-        main {
-            manifest.srcFile 'AndroidManifest-gradle.xml'
-            java.srcDirs = ['src']
-            res.srcDirs = ['res']
-        }
-    }
-}
-
-dependencies {
-    api 'androidx.annotation:annotation:1.1.0'
-    api 'androidx.appcompat:appcompat:1.1.0'
-    api 'androidx.constraintlayout:constraintlayout:1.1.3'
-    api 'androidx.preference:preference:1.1.0'
-    api 'androidx.recyclerview:recyclerview:1.0.0'
-
-    // This is the gradle equivalent of the libs: ["android.car"] in our Android.bp
-    implementation files('../../../../../out/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/classes.jar')
-}
diff --git a/car-ui-lib/car-ui-lib/AndroidManifest-gradle.xml b/car-ui-lib/car-ui-lib/AndroidManifest-gradle.xml
new file mode 100644
index 0000000..36ffbb8
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/AndroidManifest-gradle.xml
@@ -0,0 +1,26 @@
+<?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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui">
+    <application>
+        <provider
+            android:name="com.android.car.ui.core.CarUiInstaller"
+            android:authorities="${applicationId}.CarUiInstaller"
+            android:exported="false"/>
+    </application>
+</manifest>
diff --git a/car-ui-lib/car-ui-lib/AndroidManifest.xml b/car-ui-lib/car-ui-lib/AndroidManifest.xml
new file mode 100644
index 0000000..5136dc2
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui">
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="28" />
+
+    <application>
+        <provider
+            android:name="com.android.car.ui.core.CarUiInstaller"
+            android:authorities="${applicationId}.CarUiInstaller"
+            android:directBootAware="true"
+            android:exported="false"
+            android:process="@string/car_ui_installer_process_name"/>
+    </application>
+</manifest>
diff --git a/car-ui-lib/car-ui-lib/build.gradle b/car-ui-lib/car-ui-lib/build.gradle
new file mode 100644
index 0000000..5c6ce32
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/build.gradle
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+// Library-level build file
+
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 30
+
+    defaultConfig {
+        minSdkVersion 28
+        targetSdkVersion 30
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest-gradle.xml'
+        }
+    }
+
+    testOptions {
+        unitTests {
+            includeAndroidResources = true
+        }
+    }
+
+    // This is the gradle equivalent of the libs: ["android.car"] in the Android.bp
+    // Which will be in the SDK 30 R3+
+    useLibrary 'android.car'
+}
+
+dependencies {
+    api 'androidx.annotation:annotation:1.1.0'
+    api 'androidx.appcompat:appcompat:1.1.0'
+    api 'androidx.constraintlayout:constraintlayout:2.0.1'
+    api 'androidx.preference:preference:1.1.0'
+    api 'androidx.recyclerview:recyclerview:1.0.0'
+    api 'androidx.core:core:1.2.0'
+    implementation 'com.android.support:support-annotations:28.0.0'
+
+    testImplementation "androidx.test.ext:junit:1.1.1"
+    testImplementation 'org.robolectric:robolectric:4.4'
+    testImplementation "org.mockito:mockito-core:2.19.0"
+    testImplementation "com.google.truth:truth:0.29"
+    testImplementation "org.testng:testng:6.9.9"
+
+    androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+    androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
+    androidTestImplementation "com.google.truth:truth:0.29"
+    androidTestImplementation "androidx.test.ext:junit:1.1.1"
+    androidTestImplementation "org.mockito:mockito-core:2.19.0"
+    androidTestImplementation 'androidx.test:runner:1.1.0'
+    androidTestImplementation 'androidx.test:rules:1.1.0'
+    // This is needed to be able to spy certain classes with Mockito
+    // It's major/minor version must match Mockito's.
+    androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito-inline:2.19.0'
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml b/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..73041a4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2020 Google Inc.
+
+    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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui.test">
+    <application android:debuggable="true" android:theme="@style/Theme.CarUi.NoToolbar">
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="com.android.car.ui.TestActivity" />
+        <activity android:name="com.android.car.ui.recyclerview.CarUiRecyclerViewTestActivity" />
+        <activity android:name="com.android.car.ui.FocusAreaTestActivity" />
+        <activity android:name="com.android.car.ui.FocusParkingViewTestActivity" />
+        <activity android:name="com.android.car.ui.preference.PreferenceTestActivity" />
+        <activity
+            android:name="com.android.car.ui.preference.NonFullscreenPreferenceFragmentTest$MyActivity"
+            android:theme="@style/Theme.CarUi.WithToolbar"/>
+        <activity android:name="com.android.car.ui.utils.ViewUtilsTestActivity" />
+        <activity
+            android:name="com.android.car.ui.toolbar.ToolbarTestActivity"
+            android:theme="@style/Theme.CarUi.WithToolbar"/>
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.car.ui.test"
+        android:label="Chassis Test Cases">
+    </instrumentation>
+</manifest>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/AlertDialogBuilderTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/AlertDialogBuilderTest.java
new file mode 100644
index 0000000..0aaa250
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/AlertDialogBuilderTest.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import android.app.AlertDialog;
+import android.database.Cursor;
+import android.view.View;
+
+import androidx.test.espresso.Root;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
+import com.android.car.ui.recyclerview.CarUiRadioButtonListItem;
+import com.android.car.ui.recyclerview.CarUiRadioButtonListItemAdapter;
+import com.android.car.ui.test.R;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class AlertDialogBuilderTest {
+
+    @Rule
+    public ActivityTestRule<TestActivity> mActivityRule =
+            new ActivityTestRule<>(TestActivity.class);
+
+    @Test
+    public void test_AlertDialogBuilder_works() throws Throwable {
+        String title = "Test message from AlertDialogBuilder";
+        String subtitle = "Subtitle from AlertDialogBuilder";
+        mActivityRule.runOnUiThread(() ->
+                new AlertDialogBuilder(mActivityRule.getActivity())
+                        .setMessage(title)
+                        .setSubtitle(subtitle)
+                        .show());
+
+        AlertDialog dialog = checkDefaultButtonExists(true,
+                new AlertDialogBuilder(mActivityRule.getActivity())
+                        .setMessage(title)
+                        .setSubtitle(subtitle));
+        onView(withText(title))
+                .inRoot(new RootWithDecorMatcher(dialog.getWindow().getDecorView()))
+                .check(matches(isDisplayed()));
+        onView(withText(subtitle))
+                .inRoot(new RootWithDecorMatcher(dialog.getWindow().getDecorView()))
+                .check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void test_showSingleListChoiceItem_StringArray_hidesDefaultButton() throws Throwable {
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setSingleChoiceItems(new CharSequence[]{"Item 1", "Item 2"}, 0,
+                        ((dialog, which) -> {
+                        }));
+
+        checkDefaultButtonExists(false, builder);
+    }
+
+    @Test
+    public void test_showSingleListChoiceItem_StringArrayResource_hidesDefaultButton()
+            throws Throwable {
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setSingleChoiceItems(R.array.test_string_array, 0, ((dialog, which) -> {
+                }));
+
+        checkDefaultButtonExists(false, builder);
+    }
+
+    @Test
+    public void test_showSingleListChoiceItem_CarUiRadioButtonListItemAdapter_forcesDefaultButton()
+            throws Throwable {
+        CarUiRadioButtonListItem item1 = new CarUiRadioButtonListItem();
+        item1.setTitle("Item 1");
+        CarUiRadioButtonListItem item2 = new CarUiRadioButtonListItem();
+        item2.setTitle("Item 2");
+        CarUiRadioButtonListItem item3 = new CarUiRadioButtonListItem();
+        item3.setTitle("Item 3");
+
+        CarUiRadioButtonListItemAdapter adapter = new CarUiRadioButtonListItemAdapter(
+                Arrays.asList(item1, item2, item3));
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setSingleChoiceItems(adapter);
+
+        checkDefaultButtonExists(true, builder);
+    }
+
+    @Test
+    public void test_showSingleListChoiceItem_cursor_hidesDefaultButton() throws Throwable {
+        Cursor cursor = new FakeCursor(Arrays.asList("Item 1", "Item 2"), "ColumnName");
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setTitle("Title")
+                .setAllowDismissButton(false)
+                .setSingleChoiceItems(cursor, 0, "ColumnName", ((dialog, which) -> {
+                }));
+
+        checkDefaultButtonExists(false, builder);
+    }
+
+    @Test
+    public void test_setItems_StringArrayResource_hidesDefaultButton() throws Throwable {
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setItems(R.array.test_string_array, ((dialog, which) -> {
+                }));
+
+        checkDefaultButtonExists(false, builder);
+    }
+
+    @Test
+    public void test_setItems_StringArray_hidesDefaultButton() throws Throwable {
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setItems(new CharSequence[]{"Item 1", "Item 2"}, ((dialog, which) -> {
+                }));
+
+        checkDefaultButtonExists(false, builder);
+    }
+
+    @Test
+    public void test_setAdapter_hidesDefaultButton()
+            throws Throwable {
+        CarUiContentListItem item1 = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item1.setTitle("Item 1");
+        CarUiContentListItem item2 = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item2.setTitle("Item 2");
+        CarUiContentListItem item3 = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item3.setTitle("Item 3");
+
+        CarUiListItemAdapter adapter = new CarUiListItemAdapter(
+                Arrays.asList(item1, item2, item3));
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setAdapter(adapter);
+
+        checkDefaultButtonExists(false, builder);
+    }
+
+    @Test
+    public void test_multichoiceItems_StringArrayResource_forcesDefaultButton()
+            throws Throwable {
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setMultiChoiceItems(R.array.test_string_array, null,
+                        ((dialog, which, isChecked) -> {
+                        }));
+
+        checkDefaultButtonExists(true, builder);
+    }
+
+    @Test
+    public void test_multichoiceItems_StringArray_forcesDefaultButton()
+            throws Throwable {
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setMultiChoiceItems(new CharSequence[]{"Test 1", "Test 2"}, null,
+                        ((dialog, which, isChecked) -> {
+                        }));
+
+        checkDefaultButtonExists(true, builder);
+    }
+
+    @Test
+    public void test_multichoiceItems_Cursor_forcesDefaultButton()
+            throws Throwable {
+        Cursor cursor = new FakeCursor(Arrays.asList("Item 1", "Item 2"), "Label");
+        AlertDialogBuilder builder = new AlertDialogBuilder(mActivityRule.getActivity())
+                .setAllowDismissButton(false)
+                .setMultiChoiceItems(cursor, "isChecked", "Label",
+                        ((dialog, which, isChecked) -> {
+                        }));
+
+        checkDefaultButtonExists(true, builder);
+    }
+
+    private AlertDialog checkDefaultButtonExists(boolean shouldExist, AlertDialogBuilder builder)
+            throws Throwable {
+        AtomicBoolean done = new AtomicBoolean(false);
+        AlertDialog[] result = new AlertDialog[1];
+        mActivityRule.runOnUiThread(() -> {
+            try {
+                result[0] = builder.create();
+                result[0].show();
+            } catch (RuntimeException e) {
+                assert e.getMessage() != null;
+                assert e.getMessage().contains(
+                        "must have at least one button to disable the dismiss button");
+
+                assert shouldExist;
+                done.set(true);
+            }
+        });
+
+        if (done.get()) {
+            return result[0];
+        }
+
+        if (shouldExist) {
+            onView(withText(R.string.car_ui_alert_dialog_default_button))
+                    .inRoot(new RootWithDecorMatcher(result[0].getWindow().getDecorView()))
+                    .check(matches(isDisplayed()));
+        } else {
+            onView(withText(R.string.car_ui_alert_dialog_default_button))
+                    .inRoot(new RootWithDecorMatcher(result[0].getWindow().getDecorView()))
+                    .check(doesNotExist());
+        }
+
+        return result[0];
+    }
+
+    private static class RootWithDecorMatcher extends TypeSafeMatcher<Root> {
+
+        private View mView;
+
+        RootWithDecorMatcher(View view) {
+            mView = view;
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("is a root with a certain decor");
+        }
+
+        @Override
+        protected boolean matchesSafely(Root item) {
+            return item.getDecorView() == mView;
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FakeCursor.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FakeCursor.java
new file mode 100644
index 0000000..d6bc4e1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FakeCursor.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import android.database.AbstractCursor;
+
+import java.util.List;
+
+public class FakeCursor extends AbstractCursor {
+
+    private List<String> mRows;
+    private String mColumnName;
+
+    public FakeCursor(List<String> rows, String columnName) {
+        mRows = rows;
+        mColumnName = columnName;
+    }
+
+    @Override
+    public int getCount() {
+        return mRows.size();
+    }
+
+    @Override
+    public String[] getColumnNames() {
+        return new String[] { mColumnName };
+    }
+
+    @Override
+    public String getString(int column) {
+        return mRows.get(getPosition());
+    }
+
+    @Override
+    public short getShort(int column) {
+        return 0;
+    }
+
+    @Override
+    public int getInt(int column) {
+        return 0;
+    }
+
+    @Override
+    public long getLong(int column) {
+        return 0;
+    }
+
+    @Override
+    public float getFloat(int column) {
+        return 0;
+    }
+
+    @Override
+    public double getDouble(int column) {
+        return 0;
+    }
+
+    @Override
+    public boolean isNull(int column) {
+        return mRows.get(getPosition()) == null;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTest.java
new file mode 100644
index 0000000..b0e7c88
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTest.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static android.view.View.FOCUS_DOWN;
+import static android.view.View.FOCUS_LEFT;
+import static android.view.View.FOCUS_RIGHT;
+import static android.view.View.FOCUS_UP;
+import static android.view.View.LAYOUT_DIRECTION_LTR;
+import static android.view.View.LAYOUT_DIRECTION_RTL;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+
+import static com.android.car.ui.RotaryCache.CACHE_TYPE_DISABLED;
+import static com.android.car.ui.RotaryCache.CACHE_TYPE_NEVER_EXPIRE;
+import static com.android.car.ui.utils.RotaryConstants.ACTION_NUDGE_SHORTCUT;
+import static com.android.car.ui.utils.RotaryConstants.ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_BOTTOM_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_LEFT_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_RIGHT_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_TOP_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.NUDGE_DIRECTION;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.Button;
+
+import androidx.annotation.NonNull;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.test.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/** Unit tests for {@link FocusArea} not in touch mode. */
+public class FocusAreaTest {
+    private static final long WAIT_TIME_MS = 3000;
+
+    @Rule
+    public ActivityTestRule<FocusAreaTestActivity> mActivityRule =
+            new ActivityTestRule<>(FocusAreaTestActivity.class);
+
+    private FocusAreaTestActivity mActivity;
+    private TestFocusArea mFocusArea1;
+    private TestFocusArea mFocusArea2;
+    private TestFocusArea mFocusArea3;
+    private TestFocusArea mFocusArea4;
+    private FocusParkingView mFpv;
+    private View mView1;
+    private Button mButton1;
+    private View mView2;
+    private View mDefaultFocus2;
+    private View mView3;
+    private View mNudgeShortcut3;
+    private View mView4;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mFocusArea1 = mActivity.findViewById(R.id.focus_area1);
+        mFocusArea2 = mActivity.findViewById(R.id.focus_area2);
+        mFocusArea3 = mActivity.findViewById(R.id.focus_area3);
+        mFocusArea4 = mActivity.findViewById(R.id.focus_area4);
+        mFpv = mActivity.findViewById(R.id.fpv);
+        mView1 = mActivity.findViewById(R.id.view1);
+        mButton1 = mActivity.findViewById(R.id.button1);
+        mView2 = mActivity.findViewById(R.id.view2);
+        mDefaultFocus2 = mActivity.findViewById(R.id.default_focus2);
+        mView3 = mActivity.findViewById(R.id.view3);
+        mNudgeShortcut3 = mActivity.findViewById(R.id.nudge_shortcut3);
+        mView4 = mActivity.findViewById(R.id.view4);
+    }
+
+    @Test
+    public void testDrawMethodsCalled() throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+        mView1.post(() -> {
+            mView1.requestFocus();
+            mFocusArea1.enableForegroundHighlight();
+            mFocusArea2.enableForegroundHighlight();
+            mFocusArea1.setOnDrawCalled(false);
+            mFocusArea1.setDrawCalled(false);
+            mFocusArea2.setOnDrawCalled(false);
+            mFocusArea2.setDrawCalled(false);
+
+            mView2.requestFocus();
+            mView2.post(() -> latch.countDown());
+        });
+
+        // The methods should be called when a FocusArea gains or loses focus.
+        assertDrawMethodsCalled(mFocusArea1, latch);
+        assertDrawMethodsCalled(mFocusArea2, latch);
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionNudgeShortcut() {
+        mFocusArea1.post(() -> {
+            // Nudge to the nudgeShortcut view.
+            mView3.requestFocus();
+            assertThat(mView3.isFocused()).isTrue();
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_RIGHT);
+            mFocusArea3.performAccessibilityAction(ACTION_NUDGE_SHORTCUT, arguments);
+            assertThat(mNudgeShortcut3.isFocused()).isTrue();
+
+            // nudgeShortcutDirection doesn't match. The focus should stay the same.
+            mView3.requestFocus();
+            assertThat(mView3.isFocused()).isTrue();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea3.performAccessibilityAction(ACTION_NUDGE_SHORTCUT, arguments);
+            assertThat(mView3.isFocused()).isTrue();
+
+            // No nudgeShortcut view in the current FocusArea. The focus should stay the same.
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_RIGHT);
+            mFocusArea1.performAccessibilityAction(ACTION_NUDGE_SHORTCUT, arguments);
+            assertThat(mView1.isFocused()).isTrue();
+        });
+    }
+
+
+    @Test
+    public void testPerformAccessibilityAction_actionFocus() {
+        mFocusArea1.post(() -> {
+            mFocusArea1.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mView1.isFocused()).isTrue();
+
+            // It should focus on the default or the first view in the FocusArea.
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionFocus_enabledFocusCache() {
+        mFocusArea1.post(() -> {
+            RotaryCache cache =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea1.setRotaryCache(cache);
+
+            mButton1.requestFocus();
+            assertThat(mButton1.isFocused()).isTrue();
+            mView2.requestFocus();
+            assertThat(mView2.isFocused()).isTrue();
+
+            // With cache, it should focus on the lastly focused view in the FocusArea.
+            mFocusArea1.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mButton1.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionFocus_disabledFocusCache() {
+        mFocusArea1.post(() -> {
+            RotaryCache cache = new RotaryCache(CACHE_TYPE_DISABLED, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea1.setRotaryCache(cache);
+
+            mButton1.requestFocus();
+            assertThat(mButton1.isFocused()).isTrue();
+            mView2.requestFocus();
+            assertThat(mView2.isFocused()).isTrue();
+
+            // Without cache, it should focus on the default or the first view in the FocusArea.
+            mFocusArea1.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mView1.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionFocus_lastFocusedViewRemoved() {
+        mFocusArea1.post(() -> {
+            // Focus on mDefaultFocus2 in mFocusArea2, then mView1 in mFocusArea21.
+            mDefaultFocus2.requestFocus();
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            // Remove mDefaultFocus2, then Perform ACTION_FOCUS on mFocusArea2.
+            mFocusArea2.removeView(mDefaultFocus2);
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, null);
+
+            // mView2 in mFocusArea2 should get focused.
+            assertThat(mView2.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionNudgeToAnotherFocusArea_enabledCache() {
+        mFocusArea1.post(() -> {
+            RotaryCache cache1 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea1.setRotaryCache(cache1);
+            RotaryCache cache2 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea2.setRotaryCache(cache2);
+
+            // Focus on the second view in mFocusArea1, then nudge to mFocusArea2.
+            mButton1.requestFocus();
+            assertThat(mButton1.isFocused()).isTrue();
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+
+            // Nudge back. It should focus on the cached view (mButton1) in the cached
+            // FocusArea (mFocusArea1).
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea2.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mButton1.isFocused()).isTrue();
+
+            // Nudge back. It should fail and the focus should stay the same because of one-way
+            // nudge history.
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea1.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mButton1.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionNudgeToAnotherFocusArea_mixedCache() {
+        mFocusArea1.post(() -> {
+            // Disabled FocusCache but enabled FocusAreaCache.
+            RotaryCache cache1 =
+                    new RotaryCache(CACHE_TYPE_DISABLED, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea1.setRotaryCache(cache1);
+            RotaryCache cache2 =
+                    new RotaryCache(CACHE_TYPE_DISABLED, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea2.setRotaryCache(cache2);
+
+            // Focus on the second view in mFocusArea1, then nudge to mFocusArea2.
+            mButton1.requestFocus();
+            assertThat(mButton1.isFocused()).isTrue();
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+
+            // Nudge back. Since FocusCache is disabled, it should focus on the default or the first
+            // view (mView1) in the cached FocusArea (mFocusArea1).
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea2.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mView1.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionNudgeToAnotherFocusArea_mixedCache2() {
+        mFocusArea1.post(() -> {
+            // Enabled FocusCache but disabled FocusAreaCache.
+            RotaryCache cache1 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_DISABLED, 0);
+            mFocusArea1.setRotaryCache(cache1);
+            RotaryCache cache2 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_DISABLED, 0);
+            mFocusArea2.setRotaryCache(cache2);
+
+            // Focus on the second view in mFocusArea1, then nudge to mFocusArea2.
+            mButton1.requestFocus();
+            assertThat(mButton1.isFocused()).isTrue();
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+
+            // Nudge back. Since FocusAreaCache is disabled, nudge should fail and the focus should
+            // stay the same.
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea2.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionNudgeToAnotherFocusArea_specifiedTarget() {
+        mFocusArea1.post(() -> {
+            // Nudge to specified FocusArea.
+            mView4.requestFocus();
+            assertThat(mView4.isFocused()).isTrue();
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_LEFT);
+            mFocusArea4.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+
+            // Direction doesn't match specified FocusArea. The focus should stay the same.
+            mView4.requestFocus();
+            assertThat(mView4.isFocused()).isTrue();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea4.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mView4.isFocused()).isTrue();
+
+            // The FocusArea doesn't specify a target FocusArea. The focus should stay the same.
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_LEFT);
+            mFocusArea1.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mView1.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testDefaultFocusOverridesHistory_override() {
+        mFocusArea1.post(() -> {
+            RotaryCache cache =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea2.setRotaryCache(cache);
+            mFocusArea2.setDefaultFocusOverridesHistory(true);
+
+            mView2.requestFocus();
+            assertThat(mView2.isFocused()).isTrue();
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            // The focused view should be the default focus view rather than the cached view.
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testDefaultFocusOverridesHistory_notOverride() {
+        mFocusArea1.post(() -> {
+            RotaryCache cache =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea2.setRotaryCache(cache);
+            mFocusArea2.setDefaultFocusOverridesHistory(false);
+
+            mView2.requestFocus();
+            assertThat(mView2.isFocused()).isTrue();
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            // The focused view should be the cached view rather than the default focus view.
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mView2.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testClearFocusAreaHistoryWhenRotating_clear() {
+        mFocusArea1.post(() -> {
+            RotaryCache cache1 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea1.setRotaryCache(cache1);
+            mFocusArea1.setClearFocusAreaHistoryWhenRotating(true);
+            RotaryCache cache2 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea2.setRotaryCache(cache2);
+            mFocusArea2.setClearFocusAreaHistoryWhenRotating(true);
+
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            // Nudging down from mFocusArea1 to mFocusArea2.
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+            // Rotate.
+            mView2.requestFocus();
+            assertThat(mView2.isFocused()).isTrue();
+            // Since nudge history is cleared, nudging up should fail and the focus should stay
+            // the same.
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea2.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mView2.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testClearFocusAreaHistoryWhenRotating_notClear() {
+        mFocusArea1.post(() -> {
+            RotaryCache cache1 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea1.setRotaryCache(cache1);
+            mFocusArea1.setClearFocusAreaHistoryWhenRotating(false);
+            RotaryCache cache2 =
+                    new RotaryCache(CACHE_TYPE_NEVER_EXPIRE, 0, CACHE_TYPE_NEVER_EXPIRE, 0);
+            mFocusArea2.setRotaryCache(cache2);
+            mFocusArea2.setClearFocusAreaHistoryWhenRotating(false);
+
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            // Nudging down from mFocusArea1 to mFocusArea2.
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+            // Rotate.
+            mView2.requestFocus();
+            assertThat(mView2.isFocused()).isTrue();
+            // Nudging up should move focus to mFocusArea1 according to nudge history.
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea2.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mView1.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testBoundsOffset() {
+        assertThat(mFocusArea1.getLayoutDirection()).isEqualTo(LAYOUT_DIRECTION_LTR);
+
+        // FocusArea's bounds offset specified in layout file:
+        // 10dp(start), 20dp(end), 30dp(top), 40dp(bottom).
+        int left = dp2Px(10);
+        int right = dp2Px(20);
+        int top = dp2Px(30);
+        int bottom = dp2Px(40);
+        AccessibilityNodeInfo node = mFocusArea1.createAccessibilityNodeInfo();
+        assertBoundsOffset(node, left, top, right, bottom);
+        node.recycle();
+    }
+
+    @Test
+    public void testBoundsOffsetWithRtl() {
+        mFocusArea1.post(() -> {
+            mFocusArea1.setLayoutDirection(LAYOUT_DIRECTION_RTL);
+            assertThat(mFocusArea1.getLayoutDirection()).isEqualTo(LAYOUT_DIRECTION_RTL);
+
+            // FocusArea highlight padding specified in layout file:
+            // 10dp(start), 20dp(end), 30dp(top), 40dp(bottom).
+            int left = dp2Px(20);
+            int right = dp2Px(10);
+            int top = dp2Px(30);
+            int bottom = dp2Px(40);
+            AccessibilityNodeInfo node = mFocusArea1.createAccessibilityNodeInfo();
+            assertBoundsOffset(node, left, top, right, bottom);
+            node.recycle();
+        });
+    }
+
+    @Test
+    public void testSetBoundsOffset() {
+        mFocusArea1.setBoundsOffset(50, 60, 70, 80);
+        AccessibilityNodeInfo node = mFocusArea1.createAccessibilityNodeInfo();
+        assertBoundsOffset(node, 50, 60, 70, 80);
+        node.recycle();
+    }
+
+    @Test
+    public void testHighlightPadding() {
+        assertThat(mFocusArea2.getLayoutDirection()).isEqualTo(LAYOUT_DIRECTION_LTR);
+
+        int left = dp2Px(50);
+        int right = dp2Px(10);
+        int top = dp2Px(40);
+        int bottom = dp2Px(20);
+        AccessibilityNodeInfo node = mFocusArea2.createAccessibilityNodeInfo();
+        assertBoundsOffset(node, left, top, right, bottom);
+        node.recycle();
+    }
+
+    @Test
+    public void testBug170423337() {
+        mFocusArea1.post(() -> {
+            // Focus on app bar (assume mFocusArea1 is app bar).
+            mView1.requestFocus();
+
+            // Nudge down to browse list (assume mFocusArea2 is browse list).
+            Bundle arguments = new Bundle();
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_DOWN);
+            mFocusArea2.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+
+            // Nudge down to playback control bar (assume mFocusArea3 is playback control bar).
+            mFocusArea3.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mView3.isFocused()).isTrue();
+
+            // Nudge down to navigation bar (navigation bar is in system window without FocusAreas).
+            mFpv.performAccessibilityAction(ACTION_FOCUS, null);
+
+            // Nudge up to playback control bar.
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea3.performAccessibilityAction(ACTION_FOCUS, arguments);
+            assertThat(mView3.isFocused()).isTrue();
+
+            // Nudge up to browse list.
+            arguments.putInt(NUDGE_DIRECTION, FOCUS_UP);
+            mFocusArea3.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mDefaultFocus2.isFocused()).isTrue();
+
+            // Nudge up, and it should focus on app bar.
+            mFocusArea2.performAccessibilityAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments);
+            assertThat(mView1.isFocused()).isTrue();
+        });
+    }
+
+    private void assertBoundsOffset(
+            @NonNull AccessibilityNodeInfo node, int leftPx, int topPx, int rightPx, int bottomPx) {
+        Bundle extras = node.getExtras();
+        assertThat(extras.getInt(FOCUS_AREA_LEFT_BOUND_OFFSET)).isEqualTo(leftPx);
+        assertThat(extras.getInt(FOCUS_AREA_RIGHT_BOUND_OFFSET)).isEqualTo(rightPx);
+        assertThat(extras.getInt(FOCUS_AREA_TOP_BOUND_OFFSET)).isEqualTo(topPx);
+        assertThat(extras.getInt(FOCUS_AREA_BOTTOM_BOUND_OFFSET)).isEqualTo(bottomPx);
+    }
+
+    /** Converts dp unit to equivalent pixels. */
+    private int dp2Px(int dp) {
+        return (int) (dp * mActivity.getResources().getDisplayMetrics().density + 0.5f);
+    }
+
+    private void assertDrawMethodsCalled(@NonNull TestFocusArea focusArea, CountDownLatch latch)
+            throws Exception {
+        latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+        assertThat(focusArea.onDrawCalled()).isTrue();
+        assertThat(focusArea.drawCalled()).isTrue();
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTestActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTestActivity.java
new file mode 100644
index 0000000..bd9716c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.test.R;
+
+/** An activity used for testing {@link FocusArea}. */
+public class FocusAreaTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.focus_area_test_activity);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTouchModeTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTouchModeTest.java
new file mode 100644
index 0000000..5c06f84
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTouchModeTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static android.view.View.FOCUS_RIGHT;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.graphics.Rect;
+import android.view.View;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.test.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/** Unit tests for {@link FocusArea} in touch mode. */
+public class FocusAreaTouchModeTest {
+    @Rule
+    public ActivityTestRule<FocusAreaTestActivity> mActivityRule =
+            new ActivityTestRule<>(FocusAreaTestActivity.class, /* initialTouchMode= */ true);
+
+    private FocusAreaTestActivity mActivity;
+    private TestFocusArea mFocusArea2;
+    private View mView1;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mFocusArea2 = mActivity.findViewById(R.id.focus_area2);
+        mView1 = mActivity.findViewById(R.id.view1);
+    }
+
+    @Test
+    public void testOnRequestFocusInDescendants_doesNothing() {
+        mFocusArea2.post(() -> {
+            Rect previouslyFocusedRect = new Rect();
+            previouslyFocusedRect.left = mView1.getLeft();
+            previouslyFocusedRect.top = mView1.getTop();
+            previouslyFocusedRect.right = previouslyFocusedRect.left + mView1.getWidth();
+            previouslyFocusedRect.bottom = previouslyFocusedRect.top + mView1.getHeight();
+            boolean focusTaken =
+                    mFocusArea2.onRequestFocusInDescendants(FOCUS_RIGHT, previouslyFocusedRect);
+
+            assertWithMessage("onRequestFocusInDescendants returned").that(focusTaken).isFalse();
+            assertWithMessage("No view should be focused")
+                    .that(mFocusArea2.getRootView().findFocus()).isNull();
+        });
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTest.java
new file mode 100644
index 0000000..e706ae1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTest.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+
+import static com.android.car.ui.utils.RotaryConstants.ACTION_RESTORE_DEFAULT_FOCUS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.recyclerview.TestContentLimitingAdapter;
+import com.android.car.ui.test.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/** Unit test for {@link FocusParkingView} not in touch mode. */
+public class FocusParkingViewTest {
+
+    private static final int NUM_ITEMS = 40;
+
+    @Rule
+    public ActivityTestRule<FocusParkingViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(FocusParkingViewTestActivity.class);
+
+    private FocusParkingViewTestActivity mActivity;
+    private FocusParkingView mFpv;
+    private ViewGroup mParent1;
+    private View mView1;
+    private View mFocusedByDefault;
+    private RecyclerView mList;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mFpv = mActivity.findViewById(R.id.fpv);
+        mParent1 = mActivity.findViewById(R.id.parent1);
+        mView1 = mActivity.findViewById(R.id.view1);
+        mFocusedByDefault = mActivity.findViewById(R.id.focused_by_default);
+        mList = mActivity.findViewById(R.id.list);
+
+        mList.post(() -> {
+            mList.setLayoutManager(new LinearLayoutManager(mActivity));
+            mList.setAdapter(new TestContentLimitingAdapter(NUM_ITEMS));
+            CarUiUtils.setRotaryScrollEnabled(mList, /* isVertical= */ true);
+        });
+    }
+
+    @Test
+    public void testGetWidthAndHeight() {
+        assertThat(mFpv.getWidth()).isEqualTo(1);
+        assertThat(mFpv.getHeight()).isEqualTo(1);
+    }
+
+    @Test
+    public void testRequestFocus_focusOnDefaultFocus() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mFpv.requestFocus();
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testRestoreDefaultFocus_focusOnDefaultFocus() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mFpv.restoreDefaultFocus();
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testOnWindowFocusChanged_loseFocus() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mFpv.onWindowFocusChanged(false);
+            assertThat(mFpv.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testOnWindowFocusChanged_focusOnDefaultFocus() {
+        mFpv.post(() -> {
+            mFpv.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mFpv.isFocused()).isTrue();
+
+            mFpv.onWindowFocusChanged(true);
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionRestoreDefaultFocus() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mFpv.performAccessibilityAction(ACTION_RESTORE_DEFAULT_FOCUS, null);
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testPerformAccessibilityAction_actionFocus() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mFpv.performAccessibilityAction(ACTION_FOCUS, null);
+            assertThat(mFpv.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testRestoreFocusInRoot_recyclerViewItemRemoved() {
+        mList.post(() -> mList.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        View firstItem = mList.getLayoutManager().findViewByPosition(0);
+                        firstItem.requestFocus();
+                        assertThat(firstItem.isFocused()).isTrue();
+
+                        ViewGroup parent = (ViewGroup) firstItem.getParent();
+                        parent.removeView(firstItem);
+                        assertThat(mFocusedByDefault.isFocused()).isTrue();
+                    }
+                })
+        );
+    }
+
+    @Test
+    public void testRestoreFocusInRoot_recyclerViewItemScrolledOffScreen() {
+        mList.post(() -> mList.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        View firstItem = mList.getLayoutManager().findViewByPosition(0);
+                        firstItem.requestFocus();
+                        assertThat(firstItem.isFocused()).isTrue();
+
+                        mList.scrollToPosition(NUM_ITEMS - 1);
+                        mList.getViewTreeObserver().addOnGlobalLayoutListener(
+                                new ViewTreeObserver.OnGlobalLayoutListener() {
+                                    @Override
+                                    public void onGlobalLayout() {
+                                        mList.getViewTreeObserver()
+                                                .removeOnGlobalLayoutListener(this);
+                                        assertThat(mList.isFocused()).isTrue();
+                                    }
+                                });
+                    }
+                }));
+    }
+
+    @Test
+    public void testRestoreFocusInRoot_focusedViewRemoved() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            ViewGroup parent = (ViewGroup) mView1.getParent();
+            parent.removeView(mView1);
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testRestoreFocusInRoot_focusedViewDisabled() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mView1.setEnabled(false);
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testRestoreFocusInRoot_focusedViewBecomesInvisible() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mView1.setVisibility(View.INVISIBLE);
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testRestoreFocusInRoot_focusedViewParentBecomesInvisible() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+
+            mParent1.setVisibility(View.INVISIBLE);
+            assertThat(mFocusedByDefault.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testRequestFocus_focusesFpvWhenShouldRestoreFocusIsFalse() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+            mFpv.setShouldRestoreFocus(false);
+
+            mFpv.requestFocus();
+            assertThat(mFpv.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testRestoreDefaultFocus_focusesFpvWhenShouldRestoreFocusIsFalse() {
+        mFpv.post(() -> {
+            mView1.requestFocus();
+            assertThat(mView1.isFocused()).isTrue();
+            mFpv.setShouldRestoreFocus(false);
+
+            mFpv.restoreDefaultFocus();
+            assertThat(mFpv.isFocused()).isTrue();
+        });
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTestActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTestActivity.java
new file mode 100644
index 0000000..9ce37cc
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.test.R;
+
+/** An Activity used for testing {@link FocusParkingView}. */
+public class FocusParkingViewTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.focus_parking_view_test_activity);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTouchModeTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTouchModeTest.java
new file mode 100644
index 0000000..d872bb6
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusParkingViewTouchModeTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static com.android.car.ui.utils.RotaryConstants.ACTION_RESTORE_DEFAULT_FOCUS;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.view.View;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.test.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/** Unit test for {@link FocusParkingView} in touch mode. */
+public class FocusParkingViewTouchModeTest {
+
+    @Rule
+    public ActivityTestRule<FocusParkingViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(FocusParkingViewTestActivity.class,
+                    /* initialTouchMode= */ true);
+
+    private FocusParkingView mFpv;
+
+    @Before
+    public void setUp() {
+        FocusParkingViewTestActivity activity = mActivityRule.getActivity();
+        mFpv = activity.findViewById(R.id.fpv);
+    }
+
+    @Test
+    public void testRestoreDefaultFocus_doesNothing() {
+        mFpv.post(() -> {
+            assertThat(mFpv.getRootView().findFocus()).isNull();
+
+            boolean result = mFpv.restoreDefaultFocus();
+
+            assertWithMessage("restoreDefaultFocus returned").that(result).isFalse();
+            assertWithMessage("No view should be focused")
+                    .that(mFpv.getRootView().findFocus()).isNull();
+        });
+    }
+
+    @Test
+    public void testRequestFocus_doesNothing() {
+        mFpv.post(() -> {
+            assertThat(mFpv.getRootView().findFocus()).isNull();
+
+            boolean result = mFpv.requestFocus(View.FOCUS_DOWN, /* previouslyFocusedRect= */ null);
+
+            assertWithMessage("requestFocus returned").that(result).isFalse();
+            assertWithMessage("No view should be focused")
+                    .that(mFpv.getRootView().findFocus()).isNull();
+        });
+    }
+
+    @Test
+    public void testPerformActionRestoreDefaultFocus_exitsTouchMode() {
+        mFpv.post(() -> {
+            assertThat(mFpv.getRootView().findFocus()).isNull();
+
+            boolean result = mFpv.performAccessibilityAction(
+                    ACTION_RESTORE_DEFAULT_FOCUS, /* arguments= */ null);
+
+            assertWithMessage("performAccessibilityAction returned").that(result).isTrue();
+            assertWithMessage("A view should be focused")
+                    .that(mFpv.getRootView().findFocus()).isNotNull();
+        });
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/RotaryCacheTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/RotaryCacheTest.java
new file mode 100644
index 0000000..b1b9b59
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/RotaryCacheTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static com.android.car.ui.RotaryCache.CACHE_TYPE_EXPIRED_AFTER_SOME_TIME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.view.View;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link RotaryCache}. */
+@RunWith(AndroidJUnit4.class)
+public class RotaryCacheTest {
+    private static final int CACHE_TIME_OUT_MS = 10000;
+
+    private RotaryCache mRotaryCache;
+    private long mValidTime;
+    private long mExpiredTime;
+    private Context mContext;
+    private FocusArea mFocusArea;
+    private View mFocusedView;
+
+    @Before
+    public void setUp() {
+        mRotaryCache = new RotaryCache(CACHE_TYPE_EXPIRED_AFTER_SOME_TIME, CACHE_TIME_OUT_MS,
+                CACHE_TYPE_EXPIRED_AFTER_SOME_TIME, CACHE_TIME_OUT_MS);
+        mValidTime = CACHE_TIME_OUT_MS - 1;
+        mExpiredTime = CACHE_TIME_OUT_MS + 1;
+        mContext = ApplicationProvider.getApplicationContext();
+        mFocusArea = new FocusArea(mContext);
+        mFocusedView = new View(mContext);
+    }
+
+    @Test
+    public void testGetFocusedView_inTheCache() {
+        mRotaryCache.saveFocusedView(mFocusedView, 0);
+        View view = mRotaryCache.getFocusedView(mValidTime);
+        assertThat(view).isEqualTo(mFocusedView);
+    }
+
+    @Test
+    public void testGetFocusedView_notInTheCache() {
+        View view = mRotaryCache.getFocusedView(mValidTime);
+        assertThat(view).isNull();
+    }
+
+    @Test
+    public void testGetFocusedView_expiredCache() {
+        mRotaryCache.saveFocusedView(mFocusedView, 0);
+        View view = mRotaryCache.getFocusedView(mExpiredTime);
+        assertThat(view).isNull();
+    }
+
+    @Test
+    public void testGetCachedFocusArea_inTheCache() {
+        int direction = View.FOCUS_LEFT;
+        mRotaryCache.saveFocusArea(direction, mFocusArea, 0);
+        FocusArea focusArea = mRotaryCache.getCachedFocusArea(direction, mValidTime);
+        assertThat(focusArea).isEqualTo(mFocusArea);
+    }
+
+    @Test
+    public void testGetCachedFocusArea_notInTheCache() {
+        int direction = View.FOCUS_LEFT;
+        mRotaryCache.saveFocusArea(direction, mFocusArea, 0);
+
+        FocusArea focusArea = mRotaryCache.getCachedFocusArea(View.FOCUS_RIGHT, mValidTime);
+        assertThat(focusArea).isNull();
+        focusArea = mRotaryCache.getCachedFocusArea(View.FOCUS_UP, mValidTime);
+        assertThat(focusArea).isNull();
+    }
+
+    @Test
+    public void testGetCachedFocusArea_expiredCache() {
+        int direction = View.FOCUS_LEFT;
+        mRotaryCache.saveFocusArea(direction, mFocusArea, 0);
+        FocusArea focusArea = mRotaryCache.getCachedFocusArea(direction, mExpiredTime);
+        assertThat(focusArea).isNull();
+    }
+
+    @Test
+    public void testClearFocusAreaHistory() {
+        mRotaryCache.saveFocusArea(View.FOCUS_UP, mFocusArea, 0);
+        assertThat(mRotaryCache.getCachedFocusArea(View.FOCUS_UP, mValidTime)).isEqualTo(
+                mFocusArea);
+
+        mRotaryCache.clearFocusAreaHistory();
+        assertThat(mRotaryCache.getCachedFocusArea(View.FOCUS_UP, mValidTime)).isNull();
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TestActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TestActivity.java
new file mode 100644
index 0000000..a5f20d5
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TestActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.test.R;
+
+/**
+ * An empty activity to be used for testing.
+ */
+public class TestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.empty_test_activity);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TestFocusArea.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TestFocusArea.java
new file mode 100644
index 0000000..444cbc5
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TestFocusArea.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+
+import androidx.annotation.Nullable;
+
+/** A {@link FocusArea} used for testing. */
+public class TestFocusArea extends FocusArea {
+
+    /** Whether {@link #onDraw(Canvas)} was called. */
+    private boolean mOnDrawCalled;
+
+    /** Whether {@link #draw(Canvas)} was called. */
+    private boolean mDrawCalled;
+
+    private int mLayoutDirection = LAYOUT_DIRECTION_LTR;
+
+    public TestFocusArea(Context context) {
+        super(context);
+    }
+
+    public TestFocusArea(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public TestFocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public TestFocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        mOnDrawCalled = true;
+        super.onDraw(canvas);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        mDrawCalled = true;
+        super.draw(canvas);
+    }
+
+    public boolean onDrawCalled() {
+        return mOnDrawCalled;
+    }
+
+    public void setOnDrawCalled(boolean onDrawCalled) {
+        mOnDrawCalled = onDrawCalled;
+    }
+
+    public boolean drawCalled() {
+        return mDrawCalled;
+    }
+
+    public void setDrawCalled(boolean drawCalled) {
+        mDrawCalled = drawCalled;
+    }
+
+    @Override
+    public void setLayoutDirection(int layoutDirection) {
+        // The real setLayoutDirection doesn't work in the test, so let's mock it.
+        if (mLayoutDirection != layoutDirection) {
+            mLayoutDirection = layoutDirection;
+            // To trigger the highlight padding update, we need to call onLayout. Note: the
+            // parameters don't matter.
+            onLayout(false, 0, 0, 0, 0);
+        }
+    }
+
+    @Override
+    public int getLayoutDirection() {
+        return mLayoutDirection;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/LowLevelActions.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/LowLevelActions.java
new file mode 100644
index 0000000..ea8e681
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/LowLevelActions.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2020 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.car.ui.actions;
+
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
+
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.test.espresso.UiController;
+import androidx.test.espresso.ViewAction;
+import androidx.test.espresso.action.GeneralLocation;
+import androidx.test.espresso.action.MotionEvents;
+import androidx.test.espresso.action.Press;
+
+import org.hamcrest.Matcher;
+
+public class LowLevelActions {
+    static MotionEvent sMotionEventDownHeldView = null;
+
+    public static PressAndHoldAction pressAndHold() {
+        return new PressAndHoldAction();
+    }
+
+    public static ReleaseAction release() {
+        return new ReleaseAction();
+    }
+
+    public static void tearDown() {
+        sMotionEventDownHeldView = null;
+    }
+
+    static class PressAndHoldAction implements ViewAction {
+        @Override
+        public Matcher<View> getConstraints() {
+            return isDisplayingAtLeast(90);
+        }
+
+        @Override
+        public String getDescription() {
+            return "Press and hold action";
+        }
+
+        @Override
+        public void perform(final UiController uiController, final View view) {
+            if (sMotionEventDownHeldView != null) {
+                throw new AssertionError("Only one view can be held at a time");
+            }
+
+            float[] precision = Press.FINGER.describePrecision();
+            float[] coords = GeneralLocation.CENTER.calculateCoordinates(view);
+            sMotionEventDownHeldView = MotionEvents.sendDown(uiController, coords, precision).down;
+        }
+    }
+
+    static class ReleaseAction implements ViewAction {
+        @Override
+        public Matcher<View> getConstraints() {
+            return isDisplayingAtLeast(90);
+        }
+
+        @Override
+        public String getDescription() {
+            return "Release action";
+        }
+
+        @Override
+        public void perform(final UiController uiController, final View view) {
+            if (sMotionEventDownHeldView == null) {
+                throw new AssertionError(
+                        "Before calling release(), you must call pressAndHold() on a view");
+            }
+
+            float[] coords = GeneralLocation.CENTER.calculateCoordinates(view);
+            MotionEvents.sendUp(uiController, sMotionEventDownHeldView, coords);
+        }
+    }
+
+    public static ViewAction touchDownAndUp(final float x, final float y) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Send touch events.";
+            }
+
+            @Override
+            public void perform(UiController uiController, final View view) {
+                // Get view absolute position
+                int[] location = new int[2];
+                view.getLocationOnScreen(location);
+
+                // Offset coordinates by view position
+                float[] coordinates = new float[]{x + location[0], y + location[1]};
+                float[] precision = new float[]{1f, 1f};
+
+                // Send down event, pause, and send up
+                MotionEvent down = MotionEvents.sendDown(uiController, coordinates, precision).down;
+                uiController.loopMainThreadForAtLeast(200);
+                MotionEvents.sendUp(uiController, down, coordinates);
+            }
+        };
+    }
+
+    /**
+     * Performs the down, move and up touch actions for the given coordinates. deltaX and deltaY
+     * coordinates are used for moving the view from the downX and downY position. The interval
+     * defines the number of time the value should be increased via delta. Also, limitY or limitX
+     * can be provided to stop the movement if that value is reached.
+     */
+    public static ViewAction performDrag(final float downX, final float downY,
+            final float deltaX, final float deltaY, final float interval, final float limitX,
+            final float limitY) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Send touch events.";
+            }
+
+            @Override
+            public void perform(UiController uiController, final View view) {
+                // Get view absolute position
+                int[] location = new int[2];
+                view.getLocationOnScreen(location);
+
+                // Offset coordinates by view position
+                float[] coordinatesDown = new float[]{downX + location[0], downY + location[1]};
+                float[] coordinatesMove = new float[]{downX + location[0], downY + location[1]};
+                float[] precision = new float[]{1f, 1f};
+                // Send down event, pause, and send up
+                MotionEvent down = MotionEvents.sendDown(uiController, coordinatesDown,
+                        precision).down;
+                uiController.loopMainThreadForAtLeast(200);
+                for (int i = 0; i < interval; i++) {
+                    MotionEvents.sendMovement(uiController, down, coordinatesMove);
+                    uiController.loopMainThreadForAtLeast(100);
+
+                    coordinatesMove[0] = coordinatesMove[0] + deltaX;
+                    coordinatesMove[1] = coordinatesMove[1] + deltaY;
+                    if (coordinatesMove[1] > limitY + location[1]
+                            || coordinatesMove[0] > limitX + location[0]) {
+                        break;
+                    }
+                }
+                MotionEvents.sendUp(uiController, down, coordinatesMove);
+            }
+        };
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/ViewActions.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/ViewActions.java
new file mode 100644
index 0000000..8640a02
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/ViewActions.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 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.car.ui.actions;
+
+import android.view.View;
+
+import androidx.test.espresso.ViewAction;
+
+import org.hamcrest.Matcher;
+
+public class ViewActions {
+
+    public static ViewAction waitForView(Matcher<View> matcher, long waitTimeMillis) {
+        return new WaitForViewAction(matcher, waitTimeMillis);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/WaitForViewAction.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/WaitForViewAction.java
new file mode 100644
index 0000000..7ce2bf6
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/actions/WaitForViewAction.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 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.car.ui.actions;
+
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+
+import android.view.View;
+
+import androidx.test.espresso.PerformException;
+import androidx.test.espresso.UiController;
+import androidx.test.espresso.ViewAction;
+import androidx.test.espresso.util.HumanReadables;
+import androidx.test.espresso.util.TreeIterables;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+
+import java.util.concurrent.TimeoutException;
+
+public class WaitForViewAction implements ViewAction {
+
+    private Matcher<View> mMatcher;
+    private long mWaitTimeMillis;
+
+    public WaitForViewAction(Matcher<View> matcher, long waitTimeMillis) {
+        mMatcher = matcher;
+        mWaitTimeMillis = waitTimeMillis;
+    }
+
+    @Override
+    public Matcher<View> getConstraints() {
+        return isRoot();
+    }
+
+    @Override
+    public String getDescription() {
+        Description description = new StringDescription();
+        mMatcher.describeTo(description);
+        return "wait at most " + mWaitTimeMillis + " milliseconds for view "
+                + description.toString();
+    }
+
+    @Override
+    public void perform(UiController uiController, View view) {
+        uiController.loopMainThreadUntilIdle();
+        final long startTime = System.currentTimeMillis();
+        final long endTime = startTime + mWaitTimeMillis;
+
+        do {
+            for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
+                if (mMatcher.matches(child)) {
+                    return;
+                }
+            }
+
+            uiController.loopMainThreadForAtLeast(50);
+        }
+        while (System.currentTimeMillis() < endTime);
+
+        throw new PerformException.Builder()
+                .withActionDescription(this.getDescription())
+                .withViewDescription(HumanReadables.describe(view))
+                .withCause(new TimeoutException())
+                .build();
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/DrawableMatcher.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/DrawableMatcher.java
new file mode 100644
index 0000000..4c0d9bb
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/DrawableMatcher.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.car.ui.matchers;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.ImageView;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+
+/* package */ class DrawableMatcher extends TypeSafeMatcher<View> {
+
+    private final int mDrawableId;
+
+    DrawableMatcher(int drawableId) {
+        mDrawableId = drawableId;
+    }
+
+    @Override
+    protected boolean matchesSafely(View item) {
+        if (!(item instanceof ImageView) || !item.isShown()) {
+            return false;
+        }
+
+        ImageView imageView = (ImageView) item;
+
+        Bitmap bitmap = drawableToBitmap(imageView.getDrawable());
+        Bitmap otherBitmap = drawableToBitmap(imageView.getContext().getDrawable(mDrawableId));
+
+        if (bitmap == null && otherBitmap == null) {
+            return true;
+        } else if ((bitmap == null) != (otherBitmap == null)) {
+            return false;
+        }
+
+        return bitmap.sameAs(otherBitmap);
+    }
+
+    private Bitmap drawableToBitmap(Drawable drawable) {
+        if (drawable == null) {
+            return null;
+        }
+
+        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+        drawable.draw(canvas);
+        return bitmap;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("has drawable with id " + mDrawableId);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/IndexMatcher.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/IndexMatcher.java
new file mode 100644
index 0000000..8902b7d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/IndexMatcher.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 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.car.ui.matchers;
+
+import android.view.View;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * A custom matcher that allows for the specification of an index when multiple views meet the
+ * criteria of a matcher.
+ */
+public class IndexMatcher extends TypeSafeMatcher<View> {
+
+    private final Matcher<View> mMatcher;
+    private final int mIndex;
+    int mCurrentIndex = 0;
+
+    public IndexMatcher(Matcher<View> matcher, int index) {
+        mMatcher = matcher;
+        mIndex = index;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("with index: ");
+        description.appendValue(mIndex);
+        mMatcher.describeTo(description);
+    }
+
+    @Override
+    public boolean matchesSafely(View view) {
+        return mMatcher.matches(view) && mCurrentIndex++ == mIndex;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/NthChildMatcher.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/NthChildMatcher.java
new file mode 100644
index 0000000..996cf63
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/NthChildMatcher.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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.car.ui.matchers;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+public class NthChildMatcher extends TypeSafeMatcher<View> {
+
+    private Matcher<View> mParentMatcher;
+    private int mPosition;
+
+    public NthChildMatcher(Matcher<View> parentMatcher, int position) {
+        mParentMatcher = parentMatcher;
+        mPosition = position;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("position " + mPosition + " of parent ");
+        mParentMatcher.describeTo(description);
+    }
+
+    @Override
+    public boolean matchesSafely(View view) {
+        if (!(view.getParent() instanceof ViewGroup)) {
+            return false;
+        }
+
+        ViewGroup parent = (ViewGroup) view.getParent();
+
+        return mParentMatcher.matches(parent)
+                && parent.getChildCount() > mPosition
+                && view.equals(parent.getChildAt(mPosition));
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/PaddingMatcher.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/PaddingMatcher.java
new file mode 100644
index 0000000..5ab1a86
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/PaddingMatcher.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 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.car.ui.matchers;
+
+import android.view.View;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+
+public class PaddingMatcher extends TypeSafeMatcher<View> {
+
+    public enum Side {
+        TOP,
+        BOTTOM,
+        LEFT,
+        RIGHT,
+        START,
+        END
+    }
+
+    private Side mSide;
+    private int mMin;
+    private int mMax;
+
+    public PaddingMatcher(Side side, int min, int max) {
+        mSide = side;
+        mMin = min;
+        mMax = max;
+    }
+
+    @Override
+    protected boolean matchesSafely(View item) {
+        int padding = 0;
+        switch (mSide) {
+            case TOP:
+                padding = item.getPaddingTop();
+                break;
+            case BOTTOM:
+                padding = item.getPaddingBottom();
+                break;
+            case LEFT:
+                padding = item.getPaddingLeft();
+                break;
+            case RIGHT:
+                padding = item.getPaddingRight();
+                break;
+            case START:
+                padding = item.getPaddingStart();
+                break;
+            case END:
+                padding = item.getPaddingEnd();
+                break;
+        }
+
+        if (mMin >= 0 && padding < mMin) {
+            return false;
+        }
+
+        return mMax < 0 || padding <= mMax;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description
+            .appendText("with " + mSide.toString() + " padding between " + mMin + " and " + mMax);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/ViewMatchers.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/ViewMatchers.java
new file mode 100644
index 0000000..cdef653
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/ViewMatchers.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.car.ui.matchers;
+
+import android.view.View;
+
+import com.android.car.ui.matchers.PaddingMatcher.Side;
+
+import org.hamcrest.Matcher;
+
+public class ViewMatchers {
+    public static Matcher<View> withDrawable(int drawableId) {
+        return new DrawableMatcher(drawableId);
+    }
+
+    public static Matcher<View> nthChildOfView(Matcher<View> parentMatcher, int n) {
+        return new NthChildMatcher(parentMatcher, n);
+    }
+
+    public static Matcher<View> withIndex(Matcher<View> matcher, int index) {
+        return new IndexMatcher(matcher, index);
+    }
+
+    public static Matcher<View> withPadding(Side side, int exactly) {
+        return new PaddingMatcher(side, exactly, exactly);
+    }
+
+    public static Matcher<View> withPaddingAtLeast(Side side, int min) {
+        return new PaddingMatcher(side, min, -1);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/NonFullscreenPreferenceFragmentTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/NonFullscreenPreferenceFragmentTest.java
new file mode 100644
index 0000000..33aaa18
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/NonFullscreenPreferenceFragmentTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2020 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.car.ui.preference;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.Espresso.pressBack;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.ui.matchers.ViewMatchers.withPadding;
+import static com.android.car.ui.matchers.ViewMatchers.withPaddingAtLeast;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.preference.ListPreference;
+import androidx.preference.MultiSelectListPreference;
+import androidx.preference.PreferenceScreen;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.matchers.PaddingMatcher.Side;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+public class NonFullscreenPreferenceFragmentTest {
+
+    private static final String EXTRA_FULLSCREEN = "fullscreen";
+    private static final String TOOLBAR_DEFAULT_TEXT = "Test!";
+    private static final String PREFERENCE_SCREEN_TITLE = "PreferenceScreen Title";
+    private static final String LIST_PREFERENCE_TITLE = "List Preference";
+    private static final String MULTI_SELECT_LIST_PREFERENCE_TITLE = "MultiSelect List Preference";
+    private static final String BACK_CONTENT_DESCRIPTION = "Back";
+    private static final String[] ITEMS = { "Item 1", "Item 2", "Item 3" };
+
+    @Rule
+    public ActivityScenarioRule<PreferenceTestActivity> mActivityRule =
+            new ActivityScenarioRule<>(PreferenceTestActivity.class);
+
+    @Test
+    public void test_fullscreen_changesTitle() {
+        try (ActivityScenario<MyActivity> scenario =
+                     ActivityScenario.launch(MyActivity.newIntent(true))) {
+
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(doesNotExist());
+            onView(withText(PREFERENCE_SCREEN_TITLE)).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(
+                    matches(withPaddingAtLeast(Side.TOP, 1)));
+
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(
+                    matches(withPaddingAtLeast(Side.TOP, 1)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).perform(click());
+
+            onView(withText(LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(LIST_PREFERENCE_TITLE)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(
+                    matches(withPaddingAtLeast(Side.TOP, 1)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).perform(click());
+        }
+    }
+
+    @Test
+    public void test_nonFullscreen_doesntChangeTitle() {
+        try (ActivityScenario<MyActivity> scenario =
+                     ActivityScenario.launch(MyActivity.newIntent(false))) {
+
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(matches(isDisplayed()));
+            onView(withText(PREFERENCE_SCREEN_TITLE)).check(doesNotExist());
+            onView(isAssignableFrom(RecyclerView.class)).check(matches(withPadding(Side.TOP, 0)));
+
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).check(doesNotExist());
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(matches(withPadding(Side.TOP, 0)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).check(doesNotExist());
+            pressBack();
+
+            onView(withText(LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(LIST_PREFERENCE_TITLE)).check(doesNotExist());
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(matches(withPadding(Side.TOP, 0)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).check(doesNotExist());
+            pressBack();
+        }
+    }
+
+
+    public static class MyActivity extends AppCompatActivity implements InsetsChangedListener {
+
+        private boolean mIsFullScreen = false;
+
+        public static Intent newIntent(boolean isFullScreen) {
+            Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+            Intent intent = new Intent(context, MyActivity.class);
+            intent.putExtra(EXTRA_FULLSCREEN, isFullScreen);
+            return intent;
+        }
+
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            ToolbarController toolbar = CarUi.requireToolbar(this);
+            toolbar.setTitle(TOOLBAR_DEFAULT_TEXT);
+
+            mIsFullScreen = getIntent().getBooleanExtra(EXTRA_FULLSCREEN, true);
+            if (savedInstanceState == null) {
+                getSupportFragmentManager()
+                        .beginTransaction()
+                        .replace(android.R.id.content, new MyPreferenceFragment(mIsFullScreen))
+                        .commitNow();
+            }
+        }
+
+        @Override
+        public void onCarUiInsetsChanged(@NonNull Insets insets) {
+            if (!mIsFullScreen) {
+                requireViewById(android.R.id.content).setPadding(insets.getLeft(), insets.getTop(),
+                        insets.getRight(), insets.getBottom());
+            } else {
+                // No-op marker for the preference fragment to handle it
+            }
+        }
+    }
+
+    public static class MyPreferenceFragment extends PreferenceFragment {
+
+        private final boolean mIsFullScreen;
+
+        public MyPreferenceFragment(boolean isFullScreen) {
+            mIsFullScreen = isFullScreen;
+        }
+
+        @Override
+        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+            PreferenceScreen screen = getPreferenceManager()
+                    .createPreferenceScreen(requireContext());
+
+            ListPreference listPreference = new CarUiListPreference(getContext());
+            listPreference.setTitle(LIST_PREFERENCE_TITLE);
+            listPreference.setKey(LIST_PREFERENCE_TITLE);
+            listPreference.setEntries(ITEMS);
+            listPreference.setEntryValues(new CharSequence[]{"1", "2", "3"});
+
+            MultiSelectListPreference multiSelectListPreference =
+                    new CarUiMultiSelectListPreference(getContext());
+            multiSelectListPreference.setTitle(MULTI_SELECT_LIST_PREFERENCE_TITLE);
+            multiSelectListPreference.setKey(MULTI_SELECT_LIST_PREFERENCE_TITLE);
+            multiSelectListPreference.setEntries(ITEMS);
+            multiSelectListPreference.setEntryValues(new CharSequence[]{"1", "2", "3"});
+
+            screen.addPreference(listPreference);
+            screen.addPreference(multiSelectListPreference);
+
+            screen.setTitle(PREFERENCE_SCREEN_TITLE);
+            setPreferenceScreen(screen);
+        }
+
+        @Override
+        protected boolean isFullScreenFragment() {
+            return mIsFullScreen;
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTest.java
new file mode 100644
index 0000000..a955cfd
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTest.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2020 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.car.ui.preference;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.ui.matchers.ViewMatchers.withIndex;
+
+import static org.hamcrest.Matchers.not;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.res.Resources;
+
+import androidx.preference.CheckBoxPreference;
+import androidx.preference.DropDownPreference;
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.test.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/** Unit tests for {@link CarUiPreference}. */
+public class PreferenceTest {
+
+    private PreferenceTestActivity mActivity;
+    private String[] mEntries;
+    private String[] mEntriesValues;
+
+    @Rule
+    public ActivityTestRule<PreferenceTestActivity> mActivityRule =
+            new ActivityTestRule<>(PreferenceTestActivity.class);
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        Resources resources = mActivity.getResources();
+        mEntries = resources.getStringArray(R.array.entries);
+        mEntriesValues = resources.getStringArray(R.array.entry_values);
+    }
+
+    @Test
+    public void testListPreference() {
+        // Scroll until list preference is visible
+        mActivity.runOnUiThread(() -> mActivity.scrollToPreference("list"));
+
+        // Display full screen list preference.
+        onView(withText(R.string.title_list_preference)).perform(click());
+
+        Preference.OnPreferenceChangeListener mockListener = mock(
+                Preference.OnPreferenceChangeListener.class);
+        when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+        mActivity.setOnPreferenceChangeListener("list", mockListener);
+
+        // Check that no option is initially selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
+
+        // Select first option.
+        onView(withText(mEntries[0])).perform(click());
+        // Check that first option is selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
+
+        // Press back to save selection.
+        onView(withId(R.id.car_ui_toolbar_nav_icon)).perform(click());
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(mEntriesValues[0]));
+
+        onView(withText(R.string.title_list_preference)).perform(click());
+
+        // Check that first option is selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
+
+        // Select second option.
+        onView(withText(mEntries[1])).perform(click());
+        // Check that second option is selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
+
+        // Press back to save selection.
+        onView(withId(R.id.car_ui_toolbar_nav_icon)).perform(click());
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(mEntriesValues[1]));
+        // Return to list preference screen.
+        onView(withText(R.string.title_list_preference)).perform(click());
+
+        // Check that second option is selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
+    }
+
+    @Test
+    public void testMultiSelectListPreference() {
+        // Scroll until multi-select preference is visible
+        mActivity.runOnUiThread(() -> mActivity.scrollToPreference("multi_select_list"));
+
+        // Display full screen list preference.
+        onView(withText(R.string.title_multi_list_preference)).perform(click());
+
+        Preference.OnPreferenceChangeListener mockListener = mock(
+                Preference.OnPreferenceChangeListener.class);
+        when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+        mActivity.setOnPreferenceChangeListener("multi_select_list", mockListener);
+
+        // Check that no option is initially selected.
+        onView(withIndex(withId(R.id.checkbox_widget), 0)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.checkbox_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.checkbox_widget), 2)).check(matches(isNotChecked()));
+
+        // Select options 1 and 3.
+        onView(withText(mEntries[0])).perform(click());
+        onView(withText(mEntries[2])).perform(click());
+
+        // Check that selections are correctly reflected.
+        onView(withIndex(withId(R.id.checkbox_widget), 0)).check(matches(isChecked()));
+        onView(withIndex(withId(R.id.checkbox_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.checkbox_widget), 2)).check(matches(isChecked()));
+
+        // Press back to save selection.
+        onView(withId(R.id.car_ui_toolbar_nav_icon)).perform(click());
+        Set<String> expectedUpdate = new HashSet<>();
+        expectedUpdate.add(mEntriesValues[0]);
+        expectedUpdate.add(mEntriesValues[2]);
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(expectedUpdate));
+
+        // Return to multi-select list preference screen.
+        onView(withText(R.string.title_multi_list_preference)).perform(click());
+
+        // Check that selections are correctly reflected.
+        onView(withIndex(withId(R.id.checkbox_widget), 0)).check(matches(isChecked()));
+        onView(withIndex(withId(R.id.checkbox_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.checkbox_widget), 2)).check(matches(isChecked()));
+    }
+
+    @Test
+    public void testCheckboxPreference() {
+        // Create checkbox preference and add it to screen.
+        CheckBoxPreference preference = new CheckBoxPreference(mActivity);
+        preference.setOrder(0);
+        preference.setKey("checkbox");
+        preference.setTitle(R.string.title_checkbox_preference);
+        preference.setSummary(R.string.summary_checkbox_preference);
+        mActivity.addPreference(preference);
+
+        // Check title and summary are displayed as expected.
+        onView(withIndex(withId(android.R.id.title), 0)).check(matches(
+                withText(mActivity.getString(R.string.title_checkbox_preference))));
+        onView(withIndex(withId(android.R.id.summary), 0)).check(matches(
+                withText(mActivity.getString(R.string.summary_checkbox_preference))));
+
+        // Ensure checkbox preference is initially not selected.
+        onView(withId(android.R.id.checkbox)).check(matches(isNotChecked()));
+
+        Preference.OnPreferenceChangeListener mockListener = mock(
+                Preference.OnPreferenceChangeListener.class);
+        when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+        mActivity.setOnPreferenceChangeListener("checkbox", mockListener);
+
+        // Select checkbox preference.
+        onView(withText(R.string.title_checkbox_preference)).perform(click());
+
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(true));
+
+        // Verify checkbox preference correctly indicates preference is selected.
+        onView(withId(android.R.id.checkbox)).check(matches(isChecked()));
+
+        // Un-select checkbox preference.
+        onView(withText(R.string.title_checkbox_preference)).perform(click());
+
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(false));
+
+        // Verify checkbox preference correctly indicates preference is selected.
+        onView(withId(android.R.id.checkbox)).check(matches(isNotChecked()));
+    }
+
+    @Test
+    public void testSwitchPreference() {
+        // Create switch preference and add it to screen.
+        SwitchPreference preference = new SwitchPreference(mActivity);
+        preference.setOrder(0);
+        preference.setKey("switch");
+        preference.setTitle(R.string.title_switch_preference);
+        preference.setSummary(R.string.summary_switch_preference);
+        mActivity.addPreference(preference);
+
+        // Check title and summary are displayed as expected.
+        onView(withIndex(withId(android.R.id.title), 0)).check(matches(
+                withText(mActivity.getString(R.string.title_switch_preference))));
+        onView(withIndex(withId(android.R.id.summary), 0)).check(matches(
+                withText(mActivity.getString(R.string.summary_switch_preference))));
+
+        // Ensure switch preference is initially not selected.
+        onView(withId(android.R.id.switch_widget)).check(matches(isNotChecked()));
+
+        Preference.OnPreferenceChangeListener mockListener = mock(
+                Preference.OnPreferenceChangeListener.class);
+        when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+        mActivity.setOnPreferenceChangeListener("switch", mockListener);
+
+        // Select switch preference.
+        onView(withText(R.string.title_switch_preference)).perform(click());
+
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(true));
+
+        // Verify switch preference correctly indicates preference is selected.
+        onView(withId(android.R.id.switch_widget)).check(matches(isChecked()));
+
+        // Un-select switch preference.
+        onView(withText(R.string.title_switch_preference)).perform(click());
+
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(false));
+
+        // Verify switch preference correctly indicates preference is selected.
+        onView(withId(android.R.id.switch_widget)).check(matches(isNotChecked()));
+    }
+
+    @Test
+    public void testDropDownPreference() {
+        // Create drop-down preference and add it to screen.
+        DropDownPreference preference = new CarUiDropDownPreference(mActivity);
+        preference.setKey("dropdown");
+        preference.setTitle(R.string.title_dropdown_preference);
+        preference.setEntries(mEntries);
+        preference.setEntryValues(mEntriesValues);
+        preference.setOrder(0);
+        mActivity.addPreference(preference);
+
+        // Display full screen list preference.
+        onView(withText(R.string.title_dropdown_preference)).perform(click());
+
+        Preference.OnPreferenceChangeListener mockListener = mock(
+                Preference.OnPreferenceChangeListener.class);
+        when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+        mActivity.setOnPreferenceChangeListener("dropdown", mockListener);
+
+        // Check that first option is initially selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
+
+        // Select third option.
+        onView(withText(mEntries[2])).perform(click());
+        // Check that first option is selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isChecked()));
+
+        // Press back to save selection.
+        onView(withId(R.id.car_ui_toolbar_nav_icon)).perform(click());
+        // Verify preference value was updated.
+        verify(mockListener, times(1)).onPreferenceChange(any(), eq(mEntriesValues[2]));
+
+        onView(withText(R.string.title_dropdown_preference)).perform(click());
+
+        // Check that first option is selected.
+        onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+        onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isChecked()));
+    }
+
+    @Test
+    public void testTwoActionPreference() {
+        // Create drop-down preference and add it to screen.
+        CarUiTwoActionPreference preference = new CarUiTwoActionPreference(mActivity);
+        preference.setKey("twoaction");
+        preference.setTitle(R.string.title_twoaction_preference);
+        preference.setSummary(R.string.summary_twoaction_preference);
+        preference.setOrder(0);
+        preference.setWidgetLayoutResource(R.layout.details_preference_widget);
+        mActivity.addPreference(preference);
+
+        // Check that widget is displayed
+        onView(withIndex(withId(com.android.car.ui.R.id.action_widget_container), 0)).check(
+                matches(isDisplayed()));
+
+        // Hide second action.
+        mActivity.runOnUiThread(() -> preference.showAction(false));
+
+        // Ensure second action isn't displayed.
+        onView(withIndex(withId(com.android.car.ui.R.id.action_widget_container), 0)).check(
+                matches(not(isDisplayed())));
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestActivity.java
new file mode 100644
index 0000000..0916f4b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 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.car.ui.preference;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.preference.Preference;
+
+public class PreferenceTestActivity extends AppCompatActivity {
+
+    private PreferenceTestFragment mPreferenceFragment;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Display the fragment as the main content.
+        if (savedInstanceState == null) {
+            mPreferenceFragment = new PreferenceTestFragment();
+
+            getSupportFragmentManager()
+                    .beginTransaction()
+                    .replace(android.R.id.content, mPreferenceFragment)
+                    .commitNow();
+        }
+    }
+
+    public void setOnPreferenceChangeListener(
+            String key, Preference.OnPreferenceChangeListener listener) {
+        mPreferenceFragment.setOnPreferenceChangeListener(key, listener);
+    }
+
+    public void scrollToPreference(String key) {
+        mPreferenceFragment.scrollToPreference(key);
+    }
+
+    public void addPreference(Preference preference) {
+        mPreferenceFragment.addPreference(preference);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestFragment.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestFragment.java
new file mode 100644
index 0000000..cc3897b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestFragment.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2020 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.car.ui.preference;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceDataStore;
+
+import com.android.car.ui.test.R;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Test Fragment to load test preferences.
+ */
+public class PreferenceTestFragment extends PreferenceFragment {
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        getPreferenceManager().setPreferenceDataStore(new TestDataStore());
+        // Load the preferences from an XML resource
+        setPreferencesFromResource(R.xml.test_preferences, rootKey);
+    }
+
+    public void setOnPreferenceChangeListener(
+            String key, Preference.OnPreferenceChangeListener listener) {
+        findPreference(key).setOnPreferenceChangeListener(listener);
+    }
+
+    public void addPreference(Preference preference) {
+        getPreferenceManager().getPreferenceScreen().addPreference(preference);
+    }
+
+    /**
+     * Custom data store to be used for testing as SharedPreferences for instrumentation tests
+     * are not initialized as expected.
+     */
+    public static class TestDataStore extends PreferenceDataStore {
+
+        private Map<String, String> mStringStore = new HashMap<>();
+        private Map<String, Boolean> mBooleanStore = new HashMap<>();
+        private Map<String, Set<String>> mStringSetStore = new HashMap<>();
+
+        @Override
+        public void putString(String key, @Nullable String value) {
+            mStringStore.put(key, value);
+        }
+
+        @Override
+        public void putStringSet(String key, @Nullable Set<String> values) {
+            mStringSetStore.put(key, values);
+        }
+
+        @Override
+        @Nullable
+        public String getString(String key, @Nullable String defValue) {
+            return mStringStore.getOrDefault(key, defValue);
+        }
+
+        @Override
+        @Nullable
+        public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
+            // Workaround for NullPointerException caused by null string set from custom data store.
+            if (defValues == null) {
+                defValues = new HashSet<>();
+            }
+            return mStringSetStore.getOrDefault(key, defValues);
+        }
+
+        @Override
+        public void putBoolean(String key, boolean value) {
+            mBooleanStore.put(key, value);
+        }
+
+        @Override
+        public boolean getBoolean(String key, boolean defValue) {
+            return mBooleanStore.getOrDefault(key, defValue);
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiListItemTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiListItemTest.java
new file mode 100644
index 0000000..bd21173
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiListItemTest.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.view.View;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link CarUiListItem}.
+ */
+public class CarUiListItemTest {
+
+    private CarUiRecyclerView mCarUiRecyclerView;
+
+    @Rule
+    public ActivityTestRule<CarUiRecyclerViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(CarUiRecyclerViewTestActivity.class);
+
+    @Before
+    public void setUp() {
+        mCarUiRecyclerView = mActivityRule.getActivity().requireViewById(R.id.list);
+    }
+
+    @Test
+    public void testItemVisibility_withTitle() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.body)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.icon_container)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.action_container)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testItemVisibility_withBody() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setBody("Test body");
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.body)).check(matches(isDisplayed()));
+        onView(withId(R.id.title)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.icon_container)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.action_container)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testItemVisibility_withTitle_withBodyAndIcon() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        item.setBody("Test body");
+        item.setIcon(mActivityRule.getActivity().getDrawable(R.drawable.car_ui_icon_close));
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.body)).check(matches(isDisplayed()));
+        onView(withId(R.id.icon_container)).check(matches(isDisplayed()));
+        onView(withId(R.id.action_container)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testItem_withCheckbox() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem.OnCheckedChangeListener mockOnCheckedChangeListener = mock(
+                CarUiContentListItem.OnCheckedChangeListener.class);
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
+        item.setTitle("Test item with checkbox");
+        item.setOnCheckedChangeListener(mockOnCheckedChangeListener);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.checkbox_widget)).check(matches(isDisplayed()));
+        onView(withId(R.id.action_divider)).check(matches(not(isDisplayed())));
+
+        // List item with checkbox should be initially unchecked.
+        onView(withId(R.id.checkbox_widget)).check(matches(isNotChecked()));
+        // Clicks anywhere on the item should toggle the checkbox
+        onView(withId(R.id.title)).perform(click());
+        onView(withId(R.id.checkbox_widget)).check(matches(isChecked()));
+        // Check that onCheckChangedListener was invoked.
+        verify(mockOnCheckedChangeListener, times(1)).onCheckedChanged(item, true);
+
+        // Uncheck checkbox with click on the action container
+        onView(withId(R.id.action_container)).perform(click());
+        onView(withId(R.id.checkbox_widget)).check(matches(isNotChecked()));
+        // Check that onCheckChangedListener was invoked.
+        verify(mockOnCheckedChangeListener, times(1)).onCheckedChanged(item, false);
+    }
+
+    @Test
+    public void testItem_withSwitch() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
+        item.setBody("Test item with switch");
+        item.setChecked(true);
+        item.setActionDividerVisible(true);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.body)).check(matches(isDisplayed()));
+        onView(withId(R.id.switch_widget)).check(matches(isDisplayed()));
+        onView(withId(R.id.action_divider)).check(matches(isDisplayed()));
+
+        // List item with checkbox should be initially checked.
+        onView(withId(R.id.switch_widget)).check(matches(isChecked()));
+        // Clicks anywhere on the item should toggle the switch
+        onView(withId(R.id.switch_widget)).perform(click());
+        onView(withId(R.id.switch_widget)).check(matches(isNotChecked()));
+        // Uncheck checkbox with click on the action container
+        onView(withId(R.id.body)).perform(click());
+        onView(withId(R.id.switch_widget)).check(matches(isChecked()));
+    }
+
+    @Test
+    public void testItem_withRadioButton() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(
+                CarUiContentListItem.Action.RADIO_BUTTON);
+        item.setTitle("Test item with radio button");
+        item.setChecked(false);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+        onView(withId(R.id.radio_button_widget)).check(matches(isDisplayed()));
+
+        // List item with checkbox should be initially not checked.
+        onView(withId(R.id.radio_button_widget)).check(matches(isNotChecked()));
+        // Clicks anywhere on the item should toggle the radio button.
+        onView(withId(R.id.radio_button_widget)).perform(click());
+        onView(withId(R.id.radio_button_widget)).check(matches(isChecked()));
+
+        // Repeated clicks on a selected radio button should not toggle the element once checked.
+        onView(withId(R.id.title)).perform(click());
+        onView(withId(R.id.radio_button_widget)).check(matches(isChecked()));
+    }
+
+    @Test
+    public void testItem_withListener() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem.OnClickListener mockOnCheckedChangeListener = mock(
+                CarUiContentListItem.OnClickListener.class);
+
+        CarUiContentListItem item = new CarUiContentListItem(
+                CarUiContentListItem.Action.NONE);
+        item.setIcon(mActivityRule.getActivity().getDrawable(R.drawable.car_ui_icon_close));
+        item.setTitle("Test item with listener");
+        item.setBody("Body text");
+        item.setOnItemClickedListener(mockOnCheckedChangeListener);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+
+        // Clicks anywhere on the item should toggle the listener
+        onView(withId(R.id.title)).perform(click());
+        verify(mockOnCheckedChangeListener, times(1)).onClick(item);
+
+        onView(withId(R.id.body)).perform(click());
+        verify(mockOnCheckedChangeListener, times(2)).onClick(item);
+
+        onView(withId(R.id.icon_container)).perform(click());
+        verify(mockOnCheckedChangeListener, times(3)).onClick(item);
+    }
+
+    @Test
+    public void testItem_withListenerAndSupplementalIconListener() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem.OnClickListener clickListener = mock(
+                CarUiContentListItem.OnClickListener.class);
+        View.OnClickListener supplementalIconClickListener = mock(View.OnClickListener.class);
+
+        CarUiContentListItem item = new CarUiContentListItem(
+                CarUiContentListItem.Action.ICON);
+        item.setTitle("Test item with two listeners");
+        item.setOnItemClickedListener(clickListener);
+        item.setSupplementalIcon(
+                mActivityRule.getActivity().getDrawable(R.drawable.car_ui_icon_close),
+                supplementalIconClickListener);
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+
+        // Clicks anywhere on the item (except supplemental icon) should trigger the item click
+        // listener.
+        onView(withId(R.id.title)).perform(click());
+        verify(clickListener, times(1)).onClick(item);
+        verify(supplementalIconClickListener, times(0)).onClick(any());
+
+        ArgumentCaptor<View> iconCaptor = ArgumentCaptor.forClass(View.class);
+        onView(withId(R.id.supplemental_icon)).perform(click());
+        // Check that icon is argument for single call to click listener.
+        verify(supplementalIconClickListener, times(1)).onClick(iconCaptor.capture());
+
+        // Verify that the standard click listener wasn't also fired.
+        verify(clickListener, times(1)).onClick(item);
+
+        View icon = mCarUiRecyclerView.findViewById(R.id.supplemental_icon);
+        assertEquals(icon, iconCaptor.getValue());
+    }
+
+    @Test
+    public void testItem_withSupplementalIconAndIconOnClickListener() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem.OnClickListener mockedItemOnClickListener = mock(
+                CarUiContentListItem.OnClickListener.class);
+        View.OnClickListener mockedIconListener = mock(View.OnClickListener.class);
+
+        CarUiContentListItem item = new CarUiContentListItem(
+                CarUiContentListItem.Action.ICON);
+        item.setSupplementalIcon(
+                mActivityRule.getActivity().getDrawable(R.drawable.car_ui_icon_close),
+                mockedIconListener);
+        item.setOnItemClickedListener(mockedItemOnClickListener);
+        item.setTitle("Test item with listeners");
+        items.add(item);
+
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(new CarUiListItemAdapter(items)));
+
+        onView(withId(R.id.title)).check(matches(isDisplayed()));
+
+        // Clicks anywhere on the item (outside of the icon) should only invoke the item click
+        // listener.
+        onView(withId(R.id.title)).perform(click());
+        verify(mockedItemOnClickListener, times(1)).onClick(item);
+
+        // Clicks anywhere on the icon should invoke both listeners.
+        onView(withId(R.id.action_container)).perform(click());
+        verify(mockedItemOnClickListener, times(1)).onClick(item);
+        verify(mockedIconListener, times(1)).onClick(any(View.class));
+    }
+
+    @Test
+    public void testRadioButtonListItemAdapter() {
+        List<CarUiRadioButtonListItem> items = new ArrayList<>();
+
+        CarUiRadioButtonListItem itemOne = new CarUiRadioButtonListItem();
+        String itemOneTitle = "Item 1";
+        itemOne.setTitle(itemOneTitle);
+        items.add(itemOne);
+
+        CarUiRadioButtonListItem itemTwo = new CarUiRadioButtonListItem();
+        String itemTwoTitle = "Item 2";
+        itemTwo.setTitle(itemTwoTitle);
+        items.add(itemTwo);
+
+        CarUiRadioButtonListItem itemThree = new CarUiRadioButtonListItem();
+        String itemThreeTitle = "Item 3";
+        itemThree.setTitle(itemThreeTitle);
+        items.add(itemThree);
+
+        CarUiRadioButtonListItemAdapter adapter = new CarUiRadioButtonListItemAdapter(items);
+        mCarUiRecyclerView.post(
+                () -> mCarUiRecyclerView.setAdapter(adapter));
+
+        onView(withText(itemOneTitle)).check(matches(isDisplayed()));
+        onView(withText(itemTwoTitle)).check(matches(isDisplayed()));
+        onView(withText(itemThreeTitle)).check(matches(isDisplayed()));
+
+        // All items are initially unchecked.
+        assertFalse(itemOne.isChecked());
+        assertFalse(itemTwo.isChecked());
+        assertFalse(itemThree.isChecked());
+        assertEquals(adapter.getSelectedItemPosition(), -1);
+
+        // Select first item.
+        onView(withText(itemOneTitle)).perform(click());
+        assertTrue(itemOne.isChecked());
+        assertFalse(itemTwo.isChecked());
+        assertFalse(itemThree.isChecked());
+        assertEquals(adapter.getSelectedItemPosition(), 0);
+
+        // Select second item.
+        onView(withText(itemTwoTitle)).perform(click());
+        assertFalse(itemOne.isChecked());
+        assertTrue(itemTwo.isChecked());
+        assertFalse(itemThree.isChecked());
+        assertEquals(adapter.getSelectedItemPosition(), 1);
+
+        // Select third item.
+        onView(withText(itemThreeTitle)).perform(click());
+        assertFalse(itemOne.isChecked());
+        assertFalse(itemTwo.isChecked());
+        assertTrue(itemThree.isChecked());
+        assertEquals(adapter.getSelectedItemPosition(), 2);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
new file mode 100644
index 0000000..e1ec9e9
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
@@ -0,0 +1,1100 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.PositionAssertions.isBottomAlignedWith;
+import static androidx.test.espresso.assertion.PositionAssertions.isCompletelyAbove;
+import static androidx.test.espresso.assertion.PositionAssertions.isLeftAlignedWith;
+import static androidx.test.espresso.assertion.PositionAssertions.isRightAlignedWith;
+import static androidx.test.espresso.assertion.PositionAssertions.isTopAlignedWith;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition;
+import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.ui.actions.LowLevelActions.performDrag;
+import static com.android.car.ui.actions.LowLevelActions.pressAndHold;
+import static com.android.car.ui.actions.LowLevelActions.release;
+import static com.android.car.ui.actions.LowLevelActions.touchDownAndUp;
+import static com.android.car.ui.actions.ViewActions.waitForView;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.lessThan;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.OrientationHelper;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.espresso.IdlingRegistry;
+import androidx.test.espresso.IdlingResource;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+
+import com.android.car.ui.TestActivity;
+import com.android.car.ui.recyclerview.decorations.grid.GridDividerItemDecoration;
+import com.android.car.ui.test.R;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Unit tests for {@link CarUiRecyclerView}. */
+public class CarUiRecyclerViewTest {
+
+    @Rule
+    public ActivityScenarioRule<TestActivity> mActivityRule =
+            new ActivityScenarioRule<>(TestActivity.class);
+
+    ActivityScenario<TestActivity> mScenario = ActivityScenario.launch(TestActivity.class);
+
+    private TestActivity mActivity;
+    private Context mTestableContext;
+    private Resources mTestableResources;
+
+    @Before
+    public void setUp() {
+        mScenario.onActivity(activity -> {
+            mActivity = activity;
+            mTestableContext = spy(mActivity);
+            mTestableResources = spy(mActivity.getResources());
+        });
+
+        when(mTestableContext.getResources()).thenReturn(mTestableResources);
+    }
+
+    @After
+    public void tearDown() {
+        for (IdlingResource idlingResource : IdlingRegistry.getInstance().getResources()) {
+            IdlingRegistry.getInstance().unregister(idlingResource);
+        }
+    }
+
+    @Test
+    public void testIsScrollbarPresent_scrollbarEnabled() {
+        doReturn(true).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(new TestAdapter(100));
+        });
+
+        onView(withId(R.id.car_ui_scroll_bar)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testIsScrollbarPresent_scrollbarDisabled() {
+        doReturn(false).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(new TestAdapter(100));
+        });
+
+        onView(withId(R.id.car_ui_scroll_bar)).check(doesNotExist());
+    }
+
+    @Test
+    public void testGridLayout() {
+        TypedArray typedArray = spy(mActivity.getBaseContext().obtainStyledAttributes(
+                null, R.styleable.CarUiRecyclerView));
+
+        doReturn(typedArray).when(mTestableContext).obtainStyledAttributes(
+                any(),
+                eq(R.styleable.CarUiRecyclerView),
+                anyInt(),
+                anyInt());
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_layoutStyle), anyInt()))
+                .thenReturn(CarUiRecyclerView.CarUiRecyclerViewLayout.GRID);
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_numOfColumns), anyInt()))
+                .thenReturn(3);
+
+        // Ensure the CarUiRecyclerViewLayout constant matches the styleable attribute enum value
+        assertEquals(CarUiRecyclerView.CarUiRecyclerViewLayout.GRID, 1);
+
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        TestAdapter adapter = new TestAdapter(4);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        assertTrue(carUiRecyclerView.getLayoutManager() instanceof GridLayoutManager);
+
+        // Check that all items in the first row are top-aligned.
+        onView(withText(adapter.getItemText(0))).check(
+                isTopAlignedWith(withText(adapter.getItemText(1))));
+        onView(withText(adapter.getItemText(1))).check(
+                isTopAlignedWith(withText(adapter.getItemText(2))));
+
+        // Check that all items in the first row are bottom-aligned.
+        onView(withText(adapter.getItemText(0))).check(
+                isBottomAlignedWith(withText(adapter.getItemText(1))));
+        onView(withText(adapter.getItemText(1))).check(
+                isBottomAlignedWith(withText(adapter.getItemText(2))));
+
+        // Check that items in second row are rendered correctly below the first row.
+        onView(withText(adapter.getItemText(0))).check(
+                isCompletelyAbove(withText(adapter.getItemText(3))));
+        onView(withText(adapter.getItemText(0))).check(
+                isLeftAlignedWith(withText(adapter.getItemText(3))));
+        onView(withText(adapter.getItemText(0))).check(
+                isRightAlignedWith(withText(adapter.getItemText(3))));
+    }
+
+    @Test
+    public void testLinearLayout() {
+        TypedArray typedArray = spy(mActivity.getBaseContext().obtainStyledAttributes(
+                null, R.styleable.CarUiRecyclerView));
+
+        doReturn(typedArray).when(mTestableContext).obtainStyledAttributes(
+                any(),
+                eq(R.styleable.CarUiRecyclerView),
+                anyInt(),
+                anyInt());
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_layoutStyle), anyInt()))
+                .thenReturn(CarUiRecyclerView.CarUiRecyclerViewLayout.LINEAR);
+
+        // Ensure the CarUiRecyclerViewLayout constant matches the styleable attribute enum value
+        assertEquals(CarUiRecyclerView.CarUiRecyclerViewLayout.LINEAR, 0);
+
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        TestAdapter adapter = new TestAdapter(4);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        assertTrue(carUiRecyclerView.getLayoutManager() instanceof LinearLayoutManager);
+
+        // Check that item views are laid out linearly.
+        onView(withText(adapter.getItemText(0))).check(
+                isCompletelyAbove(withText(adapter.getItemText(1))));
+        onView(withText(adapter.getItemText(1))).check(
+                isCompletelyAbove(withText(adapter.getItemText(2))));
+        onView(withText(adapter.getItemText(2))).check(
+                isCompletelyAbove(withText(adapter.getItemText(3))));
+    }
+
+    @Test
+    public void testSetLayoutManager_shouldUpdateItemDecorations() {
+        TypedArray typedArray = spy(mActivity.getBaseContext().obtainStyledAttributes(
+                null, R.styleable.CarUiRecyclerView));
+
+        doReturn(typedArray).when(mTestableContext).obtainStyledAttributes(
+                any(),
+                eq(R.styleable.CarUiRecyclerView),
+                anyInt(),
+                anyInt());
+        when(typedArray.getBoolean(eq(R.styleable.CarUiRecyclerView_enableDivider), anyBoolean()))
+                .thenReturn(true);
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_layoutStyle), anyInt()))
+                .thenReturn(CarUiRecyclerView.CarUiRecyclerViewLayout.GRID);
+        when(typedArray.getInt(eq(R.styleable.CarUiRecyclerView_numOfColumns), anyInt()))
+                .thenReturn(3);
+
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        TestAdapter adapter = new TestAdapter(4);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        assertTrue(carUiRecyclerView.getLayoutManager() instanceof GridLayoutManager);
+        assertEquals(carUiRecyclerView.getItemDecorationCount(), 3);
+        assertTrue(carUiRecyclerView.getItemDecorationAt(0) instanceof GridDividerItemDecoration);
+
+        carUiRecyclerView.setLayoutManager(new LinearLayoutManager(mTestableContext));
+
+        assertTrue(carUiRecyclerView.getLayoutManager() instanceof LinearLayoutManager);
+        assertEquals(carUiRecyclerView.getItemDecorationCount(), 3);
+        assertFalse(carUiRecyclerView.getItemDecorationAt(0) instanceof GridDividerItemDecoration);
+    }
+
+    @Test
+    public void testVisibility_goneAtInflationWithChangeToVisible() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(
+                        R.layout.car_ui_recycler_view_gone_test_activity));
+
+        onView(withId(R.id.list)).check(matches(not(isDisplayed())));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(3);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+            carUiRecyclerView.setVisibility(View.VISIBLE);
+        });
+
+        // Check that items in are displayed.
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(1))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(2))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testVisibility_invisibleAtInflationWithChangeToVisible() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(
+                        R.layout.car_ui_recycler_view_invisible_test_activity));
+
+        onView(withId(R.id.list)).check(matches(not(isDisplayed())));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(3);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+            carUiRecyclerView.setVisibility(View.VISIBLE);
+        });
+
+        // Check that items in are displayed.
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(1))).check(matches(isDisplayed()));
+        onView(withText(adapter.getItemText(2))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testFirstItemAtTop_onInitialLoad() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(25);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) carUiRecyclerView.getLayoutManager();
+        assertEquals(layoutManager.findFirstVisibleItemPosition(), 0);
+    }
+
+    @Test
+    public void testPageUpAndDownMoveSameDistance() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        FixedSizeTestAdapter adapter = new FixedSizeTestAdapter(50, carUiRecyclerView.getHeight());
+        mActivity.runOnUiThread(() -> carUiRecyclerView.setAdapter(adapter));
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) carUiRecyclerView.getLayoutManager();
+
+        // Move down one page so there will be sufficient pages for up and downs.
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        int topPosition = layoutManager.findFirstVisibleItemPosition();
+
+        for (int i = 0; i < 3; i++) {
+            onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+            onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click());
+        }
+
+        assertEquals(layoutManager.findFirstVisibleItemPosition(), topPosition);
+    }
+
+    @Test
+    public void testContinuousScroll() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        LinearLayoutManager layoutManager =
+                (LinearLayoutManager) carUiRecyclerView.getLayoutManager();
+
+        // Press and hold the down button for 2 seconds to scroll the list to bottom.
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(pressAndHold());
+        onView(isRoot()).perform(waitForView(withText("Sample item #49"), 3000));
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(release());
+
+        assertEquals(layoutManager.findLastCompletelyVisibleItemPosition(), 49);
+    }
+
+    @Test
+    public void testAlphaJumpToMiddleForThumbWhenTrackClicked() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        View trackView = mActivity.requireViewById(R.id.car_ui_scrollbar_track);
+        // scroll to the middle
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                touchDownAndUp(0f, (trackView.getHeight() / 2f)));
+        onView(withText(adapter.getItemText(25))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testAlphaJumpToEndAndStartForThumbWhenTrackClicked() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        View trackView = mActivity.requireViewById(R.id.car_ui_scrollbar_track);
+        View thumbView = mActivity.requireViewById(R.id.car_ui_scrollbar_thumb);
+        // scroll to the end
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                touchDownAndUp(0f, trackView.getHeight() - 1));
+        onView(withText(adapter.getItemText(49))).check(matches(isDisplayed()));
+
+        // scroll to the start
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                touchDownAndUp(0f, 1));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testThumbDragToCenter() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        onView(withText(adapter.getItemText(0))).check(matches(isDisplayed()));
+
+        View trackView = mActivity.requireViewById(R.id.car_ui_scrollbar_track);
+        View thumbView = mActivity.requireViewById(R.id.car_ui_scrollbar_thumb);
+        // if you drag too far in a single step you'll stop selecting the thumb view. Hence, drag
+        // 5 units at a time for 200 intervals and stop at the center of the track by limitY.
+
+        onView(withId(R.id.car_ui_scrollbar_track)).perform(
+                performDrag(0f, (thumbView.getHeight() / 2f), 0,
+                        5, 200, Float.MAX_VALUE,
+                        trackView.getHeight() / 2f));
+        onView(withText(adapter.getItemText(25))).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testPageUpButtonDisabledAtTop() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        //  50, because needs to be big enough to make sure content is scrollable.
+        TestAdapter adapter = new TestAdapter(50);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        // Initially page_up button is disabled.
+        onView(withId(R.id.car_ui_scrollbar_page_up)).check(matches(not(isEnabled())));
+
+        // Moving down, should enable the up bottom.
+        onView(withId(R.id.car_ui_scrollbar_page_down)).check(matches(isEnabled()));
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        onView(withId(R.id.car_ui_scrollbar_page_up)).check(matches(isEnabled()));
+
+        // Move back up; this should disable the up button again.
+        onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click()).check(
+                matches(not(isEnabled())));
+    }
+
+    @Test
+    public void testPageDownScrollsOverLongItem() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item in the middle.
+        int longItemPosition = itemCount / 2;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
+        // Scroll to a position where long item is partially visible.
+        // Scrolling from top, scrollToPosition() aligns the pos-1 item to bottom.
+        onView(withId(R.id.list)).perform(scrollToPosition(longItemPosition - 1));
+        // Scroll by half the height of the screen so the long item is partially visible.
+        mActivity.runOnUiThread(() -> carUiRecyclerView.scrollBy(0, screenHeight / 2));
+
+        onView(withText(adapter.getItemText(longItemPosition))).check(matches(isDisplayed()));
+
+        // Verify long item is partially shown.
+        View longItem = getLongItem(carUiRecyclerView);
+        assertThat(
+                orientationHelper.getDecoratedStart(longItem),
+                is(greaterThan(carUiRecyclerView.getTop())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        // Verify long item is snapped to top.
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(equalTo(0)));
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(greaterThan(carUiRecyclerView.getBottom())));
+
+        // Set a limit to avoid test stuck in non-moving state.
+        while (orientationHelper.getDecoratedEnd(longItem) > carUiRecyclerView.getBottom()) {
+            onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        }
+
+        // Verify long item end is aligned to bottom.
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(equalTo(carUiRecyclerView.getHeight())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        // Verify that the long item is no longer visible; Should be on the next child
+        assertThat(
+                orientationHelper.getDecoratedStart(longItem),
+                is(lessThan(carUiRecyclerView.getTop())));
+    }
+
+    @Test
+    public void testPageDownScrollsOverLongItemAtTheEnd() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item at the end.
+        int longItemPosition = itemCount - 1;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            // Setting top padding to any number greater than 0.
+            // Not having padding will make this test pass all the time.
+            // Also adding bottom padding to make sure the padding
+            // after the last content is considered in calculations.
+            carUiRecyclerView.setPadding(0, 1, 0, 1);
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        // 20 is just an arbitrary number to make sure we reach the end of the recyclerview.
+        for (int i = 0; i < 20; i++) {
+            onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        }
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).check(matches(not(isEnabled())));
+
+        View longItem = getLongItem(carUiRecyclerView);
+        // Making sure we've reached end of the recyclerview, after
+        // adding bottom padding
+        assertThat(orientationHelper.getDecoratedEnd(longItem)
+                        + carUiRecyclerView.getPaddingBottom(),
+                is(equalTo(carUiRecyclerView.getHeight())));
+    }
+
+    @Test
+    public void testPageUpScrollsOverLongItem() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item in the middle.
+        int longItemPosition = itemCount / 2;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        // Scroll to a position just below the long item.
+        onView(withId(R.id.list)).perform(scrollToPosition(longItemPosition + 1));
+
+        // Verify long item is off-screen.
+        View longItem = getLongItem(carUiRecyclerView);
+        assertThat(
+                orientationHelper.getDecoratedEnd(longItem),
+                is(greaterThan(carUiRecyclerView.getTop())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click());
+
+        // Verify long item is snapped to bottom.
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(equalTo(carUiRecyclerView.getHeight())));
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(lessThan(0)));
+
+
+        int decoratedStart = orientationHelper.getDecoratedStart(longItem);
+
+        while (decoratedStart < 0) {
+            onView(withId(R.id.car_ui_scrollbar_page_up)).perform(click());
+            decoratedStart = orientationHelper.getDecoratedStart(longItem);
+        }
+
+        // Verify long item top is aligned to top.
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(equalTo(0)));
+    }
+
+    @Test
+    public void testPageDownScrollsOverVeryLongItem() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item in the middle.
+        int longItemPosition = itemCount / 2;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.EXTRA_TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
+        // Scroll to a position where long item is partially visible.
+        // Scrolling from top, scrollToPosition() aligns the pos-1 item to bottom.
+        onView(withId(R.id.list)).perform(scrollToPosition(longItemPosition - 1));
+        // Scroll by half the height of the screen so the long item is partially visible.
+        mActivity.runOnUiThread(() -> carUiRecyclerView.scrollBy(0, screenHeight / 2));
+
+        onView(withText(adapter.getItemText(longItemPosition))).check(matches(isDisplayed()));
+
+        // Verify long item is partially shown.
+        View longItem = getLongItem(carUiRecyclerView);
+        assertThat(
+                orientationHelper.getDecoratedStart(longItem),
+                is(greaterThan(carUiRecyclerView.getTop())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        // Verify long item is snapped to top.
+        assertThat(orientationHelper.getDecoratedStart(longItem), is(equalTo(0)));
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                is(greaterThan(carUiRecyclerView.getBottom())));
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        // Verify long item does not snap to bottom.
+        assertThat(orientationHelper.getDecoratedEnd(longItem),
+                not(equalTo(carUiRecyclerView.getHeight())));
+    }
+
+    @Test
+    public void testPageDownScrollsOverVeryLongItemAtTheEnd() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 100;
+        // Position the long item at the end.
+        int longItemPosition = itemCount - 1;
+
+        Map<Integer, TestAdapter.ItemHeight> heightOverrides = new HashMap<>();
+        heightOverrides.put(longItemPosition, TestAdapter.ItemHeight.EXTRA_TALL);
+        TestAdapter adapter = new TestAdapter(itemCount, heightOverrides);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            // Setting top padding to any number greater than 0.
+            // Not having padding will make this test pass all the time.
+            // Also adding bottom padding to make sure the padding
+            // after the last content is considered in calculations.
+            carUiRecyclerView.setPadding(0, 1, 0, 1);
+            carUiRecyclerView.setAdapter(adapter);
+        });
+
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+
+        OrientationHelper orientationHelper =
+                OrientationHelper.createVerticalHelper(carUiRecyclerView.getLayoutManager());
+
+        // 20 is just an arbitrary number to make sure we reach the end of the recyclerview.
+        for (int i = 0; i < 20; i++) {
+            onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+        }
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).check(matches(not(isEnabled())));
+
+        View longItem = getLongItem(carUiRecyclerView);
+        // Making sure we've reached end of the recyclerview, after
+        // adding bottom padding
+        assertThat(orientationHelper.getDecoratedEnd(longItem)
+                        + carUiRecyclerView.getPaddingBottom(),
+                is(equalTo(carUiRecyclerView.getHeight())));
+    }
+
+
+    @Test
+    public void testPageDownMaintainsMinimumScrollThumbTrackHeight() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        int itemCount = 25000;
+        TestAdapter adapter = new TestAdapter(itemCount);
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+        mActivity.runOnUiThread(() -> {
+            carUiRecyclerView.setAdapter(adapter);
+        });
+        IdlingRegistry.getInstance().register(new ScrollIdlingResource(carUiRecyclerView));
+        mActivity.runOnUiThread(() -> carUiRecyclerView.requestLayout());
+
+        onView(withId(R.id.car_ui_scrollbar_page_down)).perform(click());
+
+        // Check that thumb track maintains minimum height
+        int minThumbViewHeight = mActivity.getResources()
+                .getDimensionPixelOffset(R.dimen.car_ui_scrollbar_min_thumb_height);
+        View thumbView = mActivity.requireViewById(R.id.car_ui_scrollbar_thumb);
+        assertThat(thumbView.getHeight(), is(equalTo(minThumbViewHeight)));
+    }
+
+    @Test
+    public void testSetPaddingToRecyclerViewContainerWithScrollbar() {
+        doReturn(true).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPadding(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+    }
+
+    @Test
+    public void testSetPaddingToRecyclerViewContainerWithoutScrollbar() {
+        doReturn(false).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPadding(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(10)));
+    }
+
+    @Test
+    public void testSetPaddingRelativeToRecyclerViewContainerWithScrollbar() {
+        doReturn(true).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPaddingRelative(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+    }
+
+    @Test
+    public void testSetPaddingRelativeToRecyclerViewContainerWithoutScrollbar() {
+        doReturn(false).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(0)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(0)));
+
+        mCarUiRecyclerView.setPaddingRelative(10, 10, 10, 10);
+
+        assertThat(mCarUiRecyclerView.getPaddingTop(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingBottom(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingStart(), is(equalTo(10)));
+        assertThat(mCarUiRecyclerView.getPaddingEnd(), is(equalTo(10)));
+    }
+
+    @Test
+    public void testSetAlphaToRecyclerViewWithoutScrollbar() {
+        doReturn(false).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        CarUiRecyclerView mCarUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        assertThat(mCarUiRecyclerView.getAlpha(), is(equalTo(1.0f)));
+
+        mCarUiRecyclerView.setAlpha(0.5f);
+
+        assertThat(mCarUiRecyclerView.getAlpha(), is(equalTo(0.5f)));
+    }
+
+    @Test
+    public void testSetAlphaToRecyclerViewWithScrollbar() {
+        mActivity.runOnUiThread(
+                () -> mActivity.setContentView(
+                        R.layout.car_ui_recycler_view_test_activity));
+
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+
+        ViewGroup container = (ViewGroup) carUiRecyclerView.getParent().getParent();
+
+        assertThat(carUiRecyclerView.getAlpha(), is(equalTo(1.0f)));
+        assertThat(container.getAlpha(), is(equalTo(1.0f)));
+
+        carUiRecyclerView.setAlpha(0.5f);
+
+        assertThat(carUiRecyclerView.getAlpha(), is(equalTo(1.0f)));
+        assertThat(container.getAlpha(), is(equalTo(0.5f)));
+    }
+
+    @Test
+    public void testCallAnimateOnRecyclerViewWithScrollbar() {
+        doReturn(true).when(mTestableResources).getBoolean(R.bool.car_ui_scrollbar_enable);
+        CarUiRecyclerView carUiRecyclerView = new CarUiRecyclerView(mTestableContext);
+
+        ViewGroup container = mActivity.findViewById(R.id.test_container);
+        container.post(() -> {
+            container.addView(carUiRecyclerView);
+            carUiRecyclerView.setAdapter(new TestAdapter(100));
+        });
+
+        onView(withId(R.id.car_ui_scroll_bar)).check(matches(isDisplayed()));
+
+        ViewGroup recyclerViewContainer = (ViewGroup) carUiRecyclerView.getParent().getParent();
+
+        assertThat(carUiRecyclerView.animate(), is(equalTo(recyclerViewContainer.animate())));
+    }
+
+    /**
+     * Returns an item in the current list view whose height is taller than that of
+     * the CarUiRecyclerView. If that item exists, then it is returned; otherwise an {@link
+     * IllegalStateException} is thrown.
+     *
+     * @return An item that is taller than the CarUiRecyclerView.
+     */
+    private View getLongItem(CarUiRecyclerView recyclerView) {
+        for (int i = 0; i < recyclerView.getChildCount(); i++) {
+            View item = recyclerView.getChildAt(i);
+
+            if (item.getHeight() > recyclerView.getHeight()) {
+                return item;
+            }
+        }
+
+        throw new IllegalStateException(
+                "No item found that is longer than the height of the CarUiRecyclerView.");
+    }
+
+    /** A test adapter that handles inflating test views and binding data to it. */
+    private static class TestAdapter extends RecyclerView.Adapter<TestViewHolder> {
+
+        public enum ItemHeight {
+            STANDARD,
+            TALL,
+            EXTRA_TALL
+        }
+
+        private final List<String> mData;
+        private final Map<Integer, ItemHeight> mHeightOverrides;
+
+        TestAdapter(int itemCount, Map<Integer, ItemHeight> overrides) {
+            mHeightOverrides = overrides;
+            mData = new ArrayList<>(itemCount);
+
+            for (int i = 0; i < itemCount; i++) {
+                mData.add(getItemText(i));
+            }
+        }
+
+        TestAdapter(int itemCount) {
+            this(itemCount, new HashMap<>());
+        }
+
+        String getItemText(int position) {
+            if (position > mData.size()) {
+                return null;
+            }
+
+            return String.format("Sample item #%d", position);
+        }
+
+        @NonNull
+        @Override
+        public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            return new TestViewHolder(inflater, parent);
+        }
+
+        @Override
+        public void onBindViewHolder(@NonNull TestViewHolder holder, int position) {
+            ItemHeight height = ItemHeight.STANDARD;
+
+            if (mHeightOverrides.containsKey(position)) {
+                height = mHeightOverrides.get(position);
+            }
+
+            int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
+
+            switch (height) {
+                case STANDARD:
+                    break;
+                case TALL:
+                    holder.itemView.setMinimumHeight(screenHeight);
+                    break;
+                case EXTRA_TALL:
+                    holder.itemView.setMinimumHeight(screenHeight * 2);
+                    break;
+                default:
+                    throw new IllegalStateException("Unexpected value: " + height);
+            }
+
+            holder.bind(mData.get(position));
+        }
+
+        @Override
+        public int getItemCount() {
+            return mData.size();
+        }
+    }
+
+    private static class FixedSizeTestAdapter extends RecyclerView.Adapter<TestViewHolder> {
+
+        private static final int ITEMS_PER_PAGE = 5;
+        private final List<String> mData;
+        private final int mItemHeight;
+
+        FixedSizeTestAdapter(int itemCount, int recyclerViewHeight) {
+            mData = new ArrayList<>(itemCount);
+            mItemHeight = recyclerViewHeight / ITEMS_PER_PAGE;
+
+            for (int i = 0; i < itemCount; i++) {
+                mData.add(getItemText(i));
+            }
+        }
+
+        String getItemText(int position) {
+            return String.format("Sample item #%d", position);
+        }
+
+        @NonNull
+        @Override
+        public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            return new TestViewHolder(inflater, parent);
+        }
+
+        @Override
+        public void onBindViewHolder(@NonNull TestViewHolder holder, int position) {
+            holder.itemView.setMinimumHeight(mItemHeight);
+            holder.bind(mData.get(position));
+        }
+
+        @Override
+        public int getItemCount() {
+            return mData.size();
+        }
+    }
+
+    private static class TestViewHolder extends RecyclerView.ViewHolder {
+        private TextView mTextView;
+
+        TestViewHolder(LayoutInflater inflater, ViewGroup parent) {
+            super(inflater.inflate(R.layout.test_list_item, parent, false));
+            mTextView = itemView.findViewById(R.id.text);
+        }
+
+        void bind(String text) {
+            mTextView.setText(text);
+        }
+    }
+
+    /**
+     * An {@link IdlingResource} that will prevent assertions from running while the {@link
+     * CarUiRecyclerView} is scrolling.
+     */
+    private static class ScrollIdlingResource implements IdlingResource {
+        private boolean mIdle = true;
+        private ResourceCallback mResourceCallback;
+
+        ScrollIdlingResource(CarUiRecyclerView carUiRecyclerView) {
+            carUiRecyclerView
+                    .addOnScrollListener(
+                            new RecyclerView.OnScrollListener() {
+                                @Override
+                                public void onScrollStateChanged(@NonNull RecyclerView recyclerView,
+                                        int newState) {
+                                    super.onScrollStateChanged(recyclerView, newState);
+                                    mIdle = (newState == RecyclerView.SCROLL_STATE_IDLE
+                                            // Treat dragging as idle, or Espresso will
+                                            // block itself when swiping.
+                                            || newState == RecyclerView.SCROLL_STATE_DRAGGING);
+                                    if (mIdle && mResourceCallback != null) {
+                                        mResourceCallback.onTransitionToIdle();
+                                    }
+                                }
+
+                                @Override
+                                public void onScrolled(@NonNull RecyclerView recyclerView, int dx,
+                                        int dy) {
+                                }
+                            });
+        }
+
+        @Override
+        public String getName() {
+            return ScrollIdlingResource.class.getName();
+        }
+
+        @Override
+        public boolean isIdleNow() {
+            return mIdle;
+        }
+
+        @Override
+        public void registerIdleTransitionCallback(ResourceCallback callback) {
+            mResourceCallback = callback;
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTestActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTestActivity.java
new file mode 100644
index 0000000..64dd993
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTestActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.test.R;
+
+/**
+ * An {@link Activity} that contains only an empty {@link CarUiRecyclerView}.
+ */
+public class CarUiRecyclerViewTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.car_ui_recycler_view_test_activity);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/ContentLimitingAdapterTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/ContentLimitingAdapterTest.java
new file mode 100644
index 0000000..288e839
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/ContentLimitingAdapterTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.widget.LinearLayout;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ContentLimitingAdapterTest {
+
+    @Rule
+    public ActivityTestRule<CarUiRecyclerViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(CarUiRecyclerViewTestActivity.class);
+
+    private ContentLimitingAdapter<TestViewHolder> mContentLimitingAdapter;
+
+    @Before
+    public void setUp() {
+        mContentLimitingAdapter = new TestContentLimitingAdapter(50);
+    }
+
+    @Test
+    public void setMaxItem_toLowerThanTotalItems() {
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        RecyclerView.ViewHolder last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+
+        // Switch to limited
+        mContentLimitingAdapter.setMaxItems(20);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(21);
+        RecyclerView.ViewHolder secondToLast = getItemAtPosition(19);
+        isTestViewHolderWithText(secondToLast, "Item 19");
+
+        last = getItemAtPosition(20);
+        assertThat(last).isInstanceOf(ScrollingLimitedViewHolder.class);
+
+        // Switch back to unlimited
+        mContentLimitingAdapter.setMaxItems(-1);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+    }
+
+    @Test
+    public void setMaxItem_toOne() {
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        RecyclerView.ViewHolder last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+
+        mContentLimitingAdapter.setMaxItems(1);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(2);
+        RecyclerView.ViewHolder secondToLast = getItemAtPosition(0);
+        isTestViewHolderWithText(secondToLast, "Item 0");
+
+        last = getItemAtPosition(1);
+        assertThat(last).isInstanceOf(ScrollingLimitedViewHolder.class);
+
+        // Switch back to unlimited
+        mContentLimitingAdapter.setMaxItems(-1);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+    }
+
+    @Test
+    public void setMaxItem_toZero() {
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        RecyclerView.ViewHolder last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+
+        mContentLimitingAdapter.setMaxItems(0);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(1);
+        last = getItemAtPosition(0);
+        assertThat(last).isInstanceOf(ScrollingLimitedViewHolder.class);
+
+        // Switch back to unlimited
+        mContentLimitingAdapter.setMaxItems(-1);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+    }
+
+    @Test
+    public void setMaxItem_toHigherThanTotalItems() {
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        RecyclerView.ViewHolder last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+
+        mContentLimitingAdapter.setMaxItems(70);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        RecyclerView.ViewHolder secondToLast = getItemAtPosition(48);
+        isTestViewHolderWithText(secondToLast, "Item 48");
+
+        last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+
+        // Switch back to unlimited
+        mContentLimitingAdapter.setMaxItems(-1);
+
+        assertThat(mContentLimitingAdapter.getItemCount()).isEqualTo(50);
+        last = getItemAtPosition(49);
+        isTestViewHolderWithText(last, "Item 49");
+    }
+
+    private RecyclerView.ViewHolder getItemAtPosition(int position) {
+        int viewType = mContentLimitingAdapter.getItemViewType(position);
+        RecyclerView.ViewHolder viewHolder =
+                mContentLimitingAdapter.createViewHolder(
+                        new LinearLayout(mActivityRule.getActivity().getApplicationContext()),
+                        viewType);
+        mContentLimitingAdapter.bindViewHolder(viewHolder, position);
+        return viewHolder;
+    }
+
+    private void isTestViewHolderWithText(RecyclerView.ViewHolder secondToLast, String s) {
+        assertThat(secondToLast).isInstanceOf(TestViewHolder.class);
+        TestViewHolder testViewHolder = (TestViewHolder) secondToLast;
+        assertThat(testViewHolder.getText()).isEqualTo(s);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/ContentLimitingAdapterUiTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/ContentLimitingAdapterUiTest.java
new file mode 100644
index 0000000..eae42b8
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/ContentLimitingAdapterUiTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.test.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ContentLimitingAdapterUiTest {
+
+    @Rule
+    public ActivityTestRule<CarUiRecyclerViewTestActivity> mActivityRule =
+            new ActivityTestRule<>(CarUiRecyclerViewTestActivity.class);
+
+    private ContentLimitingAdapter<TestViewHolder> mContentLimitingAdapter;
+    private RecyclerView mCarUiRecyclerView;
+
+    @Before
+    public void setUp() {
+        mContentLimitingAdapter = new TestContentLimitingAdapter(50);
+        mCarUiRecyclerView = mActivityRule.getActivity().requireViewById(R.id.list);
+        mActivityRule.getActivity().runOnUiThread(() -> {
+            mCarUiRecyclerView.setAdapter(mContentLimitingAdapter);
+        });
+    }
+
+    @Test
+    public void setMaxItem_toLowerThanTotalItems() throws Throwable {
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        // Switch to limited
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(20);
+        });
+        Thread.sleep(300);
+        onView(withText("Item 0")).check(matches(isDisplayed()));
+        onView(withId(R.id.list)).perform(scrollToPosition(20));
+        onView(withText("Item 19")).check(matches(isDisplayed()));
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message))
+                .check(matches(isDisplayed()));
+
+        // Switch back to unlimited
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(-1);
+        });
+        Thread.sleep(300);
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message)).check(doesNotExist());
+    }
+
+    @Test
+    public void setMaxItem_toOne() throws Throwable {
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(1);
+        });
+        Thread.sleep(300);
+        onView(withText("Item 0")).check(matches(isDisplayed()));
+        onView(withText("Item 1")).check(doesNotExist());
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message))
+                .check(matches(isDisplayed()));
+
+        // Switch back to unlimited
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(-1);
+        });
+        Thread.sleep(300);
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message)).check(doesNotExist());
+    }
+
+    @Test
+    public void setMaxItem_toZero() throws Throwable {
+        onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(0);
+        });
+        Thread.sleep(300);
+        onView(withText("Item 0")).check(doesNotExist());
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message))
+                .check(matches(isDisplayed()));
+
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(-1);
+        });
+        Thread.sleep(300);
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message)).check(doesNotExist());
+    }
+
+    @Test
+    public void setMaxItem_toHigherThanTotalItems() throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(70);
+        });
+        Thread.sleep(300);
+        onView(withText("Item 0")).check(matches(isDisplayed()));
+        onView(withId(R.id.list)).perform(scrollToPosition(49));
+        onView(withText("Item 49")).check(matches(isDisplayed()));
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message))
+                .check(doesNotExist());
+
+        // Switch back to unlimited
+        mActivityRule.runOnUiThread(() -> {
+            mContentLimitingAdapter.setMaxItems(-1);
+        });
+        Thread.sleep(300);
+        onView(withId(com.android.car.ui.R.id.car_ui_list_limiting_message)).check(doesNotExist());
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/RangeFilterImplTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/RangeFilterImplTest.java
new file mode 100644
index 0000000..ffb5c04
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/RangeFilterImplTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class RangeFilterImplTest {
+    private static final int EVEN_MAX_ITEMS = 10;
+    private static final int ODD_MAX_ITEMS = 9;
+    private static final int UNRESTRICTED_COUNT = 80;
+    private static final int UNRESTRICTED_SMALL_COUNT = 6;
+
+    @Mock
+    RecyclerView.Adapter mMockAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testRecompute_contentSizeSmallerThanRange_noLimit() {
+        RangeFilterImpl rangeFilter = new RangeFilterImpl(mMockAdapter, EVEN_MAX_ITEMS);
+        int pivotPosition = 0;
+        rangeFilter.recompute(UNRESTRICTED_SMALL_COUNT, pivotPosition);
+        verifyNoClamps(rangeFilter, UNRESTRICTED_SMALL_COUNT);
+    }
+
+    @Test
+    public void testRecompute_pivotPointInTheMiddleWithEvenMaxItems_limitContent() {
+        RangeFilterImpl rangeFilter = new RangeFilterImpl(mMockAdapter, EVEN_MAX_ITEMS);
+        int pivotPosition = 30;
+        rangeFilter.recompute(UNRESTRICTED_COUNT, pivotPosition);
+        verifyClampedBothEnds(rangeFilter, pivotPosition, EVEN_MAX_ITEMS);
+        rangeFilter.applyFilter();
+        verifyFilterBothEnds(mMockAdapter, pivotPosition, EVEN_MAX_ITEMS, UNRESTRICTED_COUNT);
+        rangeFilter.removeFilter();
+        verifyRemoveFilterBothEnds(mMockAdapter, pivotPosition, EVEN_MAX_ITEMS, UNRESTRICTED_COUNT);
+    }
+
+    @Test
+    public void testRecompute_pivotPointInTheMiddleWithOddMaxItems_limitContent() {
+        RangeFilterImpl rangeFilter = new RangeFilterImpl(mMockAdapter, ODD_MAX_ITEMS);
+        int pivotPosition = 30;
+        rangeFilter.recompute(UNRESTRICTED_COUNT, pivotPosition);
+        verifyClampedBothEnds(rangeFilter, pivotPosition, ODD_MAX_ITEMS);
+        rangeFilter.applyFilter();
+        verifyFilterBothEnds(mMockAdapter, pivotPosition, ODD_MAX_ITEMS, UNRESTRICTED_COUNT);
+        rangeFilter.removeFilter();
+        verifyRemoveFilterBothEnds(mMockAdapter, pivotPosition, ODD_MAX_ITEMS, UNRESTRICTED_COUNT);
+    }
+
+    private void verifyClampedBothEnds(
+            RangeFilterImpl rangeFilter, int pivotPoint, int maxItemCount) {
+        RangeFilterImpl.ListRange range = rangeFilter.getRange();
+        int firstHalfCount = maxItemCount / 2;
+        int secondHalfCount = maxItemCount - firstHalfCount;
+        assertThat(range.mClampedHead).isEqualTo(1);
+        assertThat(range.mClampedTail).isEqualTo(1);
+        assertThat(range.mStartIndex).isEqualTo(pivotPoint - firstHalfCount);
+        assertThat(range.mEndIndex).isEqualTo(pivotPoint + secondHalfCount);
+        assertThat(range.mEndIndex - range.mStartIndex).isEqualTo(maxItemCount);
+        assertThat(range.mLimitedCount).isEqualTo(maxItemCount + 2 /* two messages*/);
+
+        assertThat(rangeFilter.positionToIndex(0))
+                .isEqualTo(RangeFilter.INVALID_INDEX);
+        assertThat(rangeFilter.positionToIndex(1))
+                .isEqualTo(range.mStartIndex);
+
+        assertThat(rangeFilter.positionToIndex(maxItemCount))
+                .isEqualTo(range.mEndIndex - 1);
+        assertThat(rangeFilter.positionToIndex(maxItemCount + 1))
+                .isEqualTo(RangeFilter.INVALID_INDEX);
+
+        assertThat(rangeFilter.indexToPosition(range.mStartIndex))
+                .isEqualTo(1);
+
+        assertThat(rangeFilter.indexToPosition(range.mEndIndex - 1))
+                .isEqualTo(maxItemCount /* head message takes an additional position */);
+    }
+
+    private void verifyNoClamps(RangeFilterImpl rangeFilter, int unrestrictedCount) {
+        RangeFilterImpl.ListRange range = rangeFilter.getRange();
+        assertThat(range.mClampedHead).isEqualTo(0);
+        assertThat(range.mClampedTail).isEqualTo(0);
+        assertThat(range.mStartIndex).isEqualTo(0);
+        assertThat(range.mEndIndex).isEqualTo(unrestrictedCount);
+        assertThat(range.mEndIndex - range.mStartIndex).isEqualTo(unrestrictedCount);
+        assertThat(range.mLimitedCount).isEqualTo(unrestrictedCount);
+    }
+
+    private void verifyFilterBothEnds(
+            Adapter adapter,
+            int pivotPosition,
+            int maxCount,
+            int unrestrictedCount) {
+        int firstHalfRemainingItems = maxCount / 2;
+        int secondHalfRemainingItems = maxCount - firstHalfRemainingItems;
+        int clampedHeadItemCount = pivotPosition - firstHalfRemainingItems;
+        int clampedTailItemCount = unrestrictedCount - clampedHeadItemCount - maxCount;
+
+        verify(adapter).notifyItemInserted(unrestrictedCount);
+        verify(adapter).notifyItemRangeRemoved(
+                pivotPosition + secondHalfRemainingItems, clampedTailItemCount);
+        verify(adapter).notifyItemRangeRemoved(0, clampedHeadItemCount);
+        verify(adapter).notifyItemInserted(0);
+    }
+
+    private void verifyRemoveFilterBothEnds(
+            Adapter adapter,
+            int pivotPosition,
+            int maxCount,
+            int unrestrictedCount) {
+        int firstHalfRemainingItems = maxCount / 2;
+        int secondHalfRemainingItems = maxCount - firstHalfRemainingItems;
+        int clampedHeadItemCount = pivotPosition - firstHalfRemainingItems;
+        int clampedTailItemCount = unrestrictedCount - clampedHeadItemCount - maxCount;
+
+        verify(adapter).notifyItemRemoved(maxCount + 1);
+        verify(adapter).notifyItemRangeInserted(maxCount + 1, clampedTailItemCount);
+        verify(adapter).notifyItemRangeInserted(1, clampedHeadItemCount);
+        verify(adapter).notifyItemRemoved(0);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestContentLimitingAdapter.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestContentLimitingAdapter.java
new file mode 100644
index 0000000..1af9a70
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestContentLimitingAdapter.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.ui.test.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestContentLimitingAdapter extends ContentLimitingAdapter<TestViewHolder> {
+
+    private final List<String> mItems;
+
+    public TestContentLimitingAdapter(int numItems) {
+        mItems = new ArrayList<>();
+        for (int i = 0; i < numItems; i++) {
+            mItems.add("Item " + i);
+        }
+    }
+
+    @Override
+    protected TestViewHolder onCreateViewHolderImpl(@NonNull ViewGroup parent,
+            int viewType) {
+        View layout = LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.test_car_ui_recycler_view_list_item, parent, false);
+        return new TestViewHolder(layout);
+    }
+
+    @Override
+    protected void onBindViewHolderImpl(TestViewHolder holder, int position) {
+        holder.bind(mItems.get(position));
+    }
+
+    @Override
+    protected int getUnrestrictedItemCount() {
+        return mItems.size();
+    }
+
+    @Override
+    public int getConfigurationId() {
+        return 0;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestViewHolder.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestViewHolder.java
new file mode 100644
index 0000000..d6b6899
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestViewHolder.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.test.R;
+
+public class TestViewHolder extends RecyclerView.ViewHolder {
+
+    private CharSequence mText;
+
+    TestViewHolder(@NonNull View itemView) {
+        super(itemView);
+    }
+
+    void bind(CharSequence text) {
+        mText = text;
+        TextView textView = itemView.requireViewById(R.id.textTitle);
+        textView.setText(text);
+    }
+
+    CharSequence getText() {
+        return mText;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTest.java
new file mode 100644
index 0000000..251092a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2020 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.car.ui.toolbar;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.hasChildCount;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withHint;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.ui.actions.ViewActions.waitForView;
+import static com.android.car.ui.matchers.ViewMatchers.nthChildOfView;
+import static com.android.car.ui.matchers.ViewMatchers.withDrawable;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.TestCase.assertEquals;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.view.View;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.test.R;
+
+import org.hamcrest.Matcher;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.function.Consumer;
+
+/** Unit test for {@link ToolbarController}. */
+public class ToolbarTest {
+
+    @Rule
+    public ActivityTestRule<ToolbarTestActivity> mActivityRule =
+            new ActivityTestRule<>(ToolbarTestActivity.class);
+
+    @Test
+    public void test_setTitle_displaysTitle() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setTitle("Test title"));
+
+        onView(withText("Test title")).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void test_setSubtitle_displaysSubtitle() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setSubtitle("Test subtitle"));
+
+        onView(withText("Test subtitle")).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void test_setSearchHint_isDisplayed() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setSearchHint("Test search hint");
+            toolbar.setState(Toolbar.State.SEARCH);
+        });
+
+        onView(withHint("Test search hint")).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void setters_and_getters_test() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setTitle("Foo");
+            toolbar.setSearchHint("Foo2");
+            toolbar.setShowMenuItemsWhileSearching(true);
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            toolbar.setNavButtonMode(Toolbar.NavButtonMode.CLOSE);
+
+            assertThat(toolbar.getTitle().toString()).isEqualTo("Foo");
+            assertThat(toolbar.getSearchHint().toString()).isEqualTo("Foo2");
+            assertThat(toolbar.getShowMenuItemsWhileSearching()).isEqualTo(true);
+            assertThat(toolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
+            assertThat(toolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
+                    Toolbar.NavButtonMode.CLOSE);
+        });
+    }
+
+    @Test
+    public void test_setLogo_displaysLogo() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setLogo(R.drawable.ic_launcher));
+
+        onView(withDrawable(R.drawable.ic_launcher)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void pressBack_withoutListener_callsActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> toolbar.setState(Toolbar.State.SUBPAGE));
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertEquals(1, mActivityRule.getActivity().getTimesOnBackPressed());
+    }
+
+    @Test
+    public void pressBack_withListenerThatReturnsFalse_callsActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            toolbar.registerOnBackListener(() -> false);
+        });
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertEquals(1, mActivityRule.getActivity().getTimesOnBackPressed());
+    }
+
+    @Test
+    public void pressBack_withListenerThatReturnsTrue_doesntCallActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            toolbar.registerOnBackListener(() -> true);
+        });
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertEquals(0, mActivityRule.getActivity().getTimesOnBackPressed());
+    }
+
+    @Test
+    public void pressBack_withUnregisteredListener_doesntCallActivityOnBack() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setState(Toolbar.State.SUBPAGE);
+            Toolbar.OnBackListener listener = () -> true;
+            toolbar.registerOnBackListener(listener);
+            toolbar.registerOnBackListener(listener);
+            toolbar.unregisterOnBackListener(listener);
+        });
+
+        onView(withId(R.id.car_ui_toolbar_nav_icon_container)).perform(click());
+
+        assertEquals(1, mActivityRule.getActivity().getTimesOnBackPressed());
+    }
+
+    @Test
+    public void menuItems_setId_shouldWork() {
+        MenuItem item = MenuItem.builder(mActivityRule.getActivity()).build();
+
+        assertThat(item.getId()).isEqualTo(View.NO_ID);
+
+        item.setId(7);
+
+        assertThat(item.getId()).isEqualTo(7);
+    }
+
+    @Test
+    public void menuItems_whenClicked_shouldCallListener() throws Throwable {
+        MenuItem.OnClickListener callback = mock(MenuItem.OnClickListener.class);
+        MenuItem menuItem = MenuItem.builder(mActivityRule.getActivity())
+                .setTitle("Button!")
+                .setOnClickListener(callback)
+                .build();
+        runWithToolbar((toolbar) -> toolbar.setMenuItems(Collections.singletonList(menuItem)));
+
+        waitForMenuItems();
+
+        onView(firstMenuItem()).perform(click());
+
+        verify(callback).onClick(menuItem);
+    }
+
+    @Test
+    public void menuItems_null_shouldRemoveExistingMenuItems() throws Throwable {
+        runWithToolbar((toolbar) ->
+                toolbar.setMenuItems(Arrays.asList(
+                        MenuItem.builder(mActivityRule.getActivity())
+                                .setTitle("Button!")
+                                .build(),
+                        MenuItem.builder(mActivityRule.getActivity())
+                                .setTitle("Button2!")
+                                .build()
+                )));
+        waitForMenuItems();
+
+        onView(withId(R.id.car_ui_toolbar_menu_items_container)).check(matches(hasChildCount(2)));
+
+        runWithToolbar((toolbar) -> toolbar.setMenuItems(null));
+
+        onView(withId(R.id.car_ui_toolbar_menu_items_container)).check(matches(hasChildCount(0)));
+    }
+
+    @Test
+    public void menuItems_setVisibility_shouldHide() throws Throwable {
+        MenuItem menuItem = MenuItem.builder(mActivityRule.getActivity())
+                .setTitle("Button!")
+                .build();
+        runWithToolbar((toolbar) -> toolbar.setMenuItems(Collections.singletonList(menuItem)));
+        waitForMenuItems();
+
+        onView(withText("Button!")).check(matches(isDisplayed()));
+
+        runWithToolbar((toolbar) -> menuItem.setVisible(false));
+
+        onView(withText("Button!")).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void menuItems_searchScreen_shouldHideMenuItems() throws Throwable {
+        runWithToolbar((toolbar) -> {
+            toolbar.setMenuItems(Arrays.asList(
+                    MenuItem.builder(mActivityRule.getActivity())
+                            .setToSearch()
+                            .build(),
+                    MenuItem.builder(mActivityRule.getActivity())
+                            .setTitle("Button!")
+                            .build()));
+            toolbar.setShowMenuItemsWhileSearching(false);
+            toolbar.setState(Toolbar.State.SEARCH);
+        });
+        waitForMenuItems();
+
+        // All menuitems should be hidden if we're hiding menuitems while searching
+        onView(withText("Button!")).check(matches(not(isDisplayed())));
+        onView(firstMenuItem()).check(matches(not(isDisplayed())));
+
+        runWithToolbar((toolbar) -> toolbar.setShowMenuItemsWhileSearching(true));
+
+        // Even if not hiding MenuItems while searching, the search MenuItem should still be hidden
+        onView(withText("Button!")).check(matches(isDisplayed()));
+        onView(firstMenuItem()).check(matches(not(isDisplayed())));
+    }
+
+    private void runWithToolbar(Consumer<ToolbarController> toRun) throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            ToolbarController toolbar = CarUi.requireToolbar(mActivityRule.getActivity());
+            toRun.accept(toolbar);
+        });
+    }
+
+    private Matcher<View> firstMenuItem() {
+        return nthChildOfView(withId(R.id.car_ui_toolbar_menu_items_container), 0);
+    }
+
+    private void waitForMenuItems() {
+        onView(isRoot()).perform(waitForView(firstMenuItem(), 500));
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTestActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTestActivity.java
new file mode 100644
index 0000000..906305e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTestActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 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.car.ui.toolbar;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.test.R;
+
+/** An Activity used for testing {@link ToolbarController}. */
+public class ToolbarTestActivity extends Activity {
+
+    private int mTimesOnBackPressed = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.empty_test_activity);
+    }
+
+    /**
+     * ag/12161937 changes the behavior of pressing back on the top level activity, so
+     * assert the number of times onBackPressed() is called instead of if the activity isFinishing()
+     */
+    public int getTimesOnBackPressed() {
+        return mTimesOnBackPressed;
+    }
+
+    @Override
+    public void onBackPressed() {
+        super.onBackPressed();
+        mTimesOnBackPressed++;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/utils/ViewUtilsTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/utils/ViewUtilsTest.java
new file mode 100644
index 0000000..3cc9b7e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/utils/ViewUtilsTest.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2020 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.car.ui.utils;
+
+import static android.view.View.GONE;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import static com.android.car.ui.utils.ViewUtils.DEFAULT_FOCUS;
+import static com.android.car.ui.utils.ViewUtils.FOCUSED_BY_DEFAULT;
+import static com.android.car.ui.utils.ViewUtils.IMPLICIT_DEFAULT_FOCUS;
+import static com.android.car.ui.utils.ViewUtils.NO_FOCUS;
+import static com.android.car.ui.utils.ViewUtils.REGULAR_FOCUS;
+import static com.android.car.ui.utils.ViewUtils.SCROLLABLE_CONTAINER_FOCUS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.car.ui.FocusArea;
+import com.android.car.ui.FocusParkingView;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.recyclerview.TestContentLimitingAdapter;
+import com.android.car.ui.test.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/** Unit tests for {@link ViewUtils}. */
+public class ViewUtilsTest {
+
+    @Rule
+    public ActivityTestRule<ViewUtilsTestActivity> mActivityRule =
+            new ActivityTestRule<>(ViewUtilsTestActivity.class);
+
+    private ViewUtilsTestActivity mActivity;
+    private FocusArea mFocusArea1;
+    private FocusArea mFocusArea2;
+    private FocusArea mFocusArea3;
+    private FocusArea mFocusArea4;
+    private FocusArea mFocusArea5;
+    private FocusParkingView mFpv;
+    private View mView2;
+    private View mFocusedByDefault3;
+    private View mView4;
+    private View mDefaultFocus4;
+    private CarUiRecyclerView mList5;
+    private View mRoot;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mFocusArea1 = mActivity.findViewById(R.id.focus_area1);
+        mFocusArea2 = mActivity.findViewById(R.id.focus_area2);
+        mFocusArea3 = mActivity.findViewById(R.id.focus_area3);
+        mFocusArea4 = mActivity.findViewById(R.id.focus_area4);
+        mFocusArea5 = mActivity.findViewById(R.id.focus_area5);
+        mFpv = mActivity.findViewById(R.id.fpv);
+        mView2 = mActivity.findViewById(R.id.view2);
+        mFocusedByDefault3 = mActivity.findViewById(R.id.focused_by_default3);
+        mView4 = mActivity.findViewById(R.id.view4);
+        mDefaultFocus4 = mActivity.findViewById(R.id.default_focus4);
+        mList5 = mActivity.findViewById(R.id.list5);
+        mRoot = mFocusArea1.getRootView();
+
+        mRoot.post(() -> {
+            mList5.setLayoutManager(new LinearLayoutManager(mActivity));
+            mList5.setAdapter(new TestContentLimitingAdapter(/* numItems= */ 2));
+            CarUiUtils.setRotaryScrollEnabled(mList5, /* isVertical= */ true);
+        });
+    }
+
+    @Test
+    public void testRootVisible() {
+        mRoot.post(() -> assertThat(mRoot.getVisibility()).isEqualTo(VISIBLE));
+    }
+
+    @Test
+    public void testGetAncestorFocusArea() {
+        mRoot.post(() -> assertThat(ViewUtils.getAncestorFocusArea(mView2)).isEqualTo(mFocusArea2));
+    }
+
+    @Test
+    public void testGetAncestorFocusArea_doesNotReturnItself() {
+        mRoot.post(() -> assertThat(ViewUtils.getAncestorFocusArea(mFocusArea2)).isNull());
+    }
+
+    @Test
+    public void testGetAncestorFocusArea_outsideFocusArea() {
+        mRoot.post(() -> assertThat(ViewUtils.getAncestorFocusArea(mFpv)).isNull());
+    }
+
+    @Test
+    public void testGetAncestorScrollableContainer() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        View firstItem = mList5.getLayoutManager().findViewByPosition(0);
+                        assertThat(ViewUtils.getAncestorScrollableContainer(firstItem))
+                                .isEqualTo(mList5);
+                    }
+                }));
+    }
+
+    @Test
+    public void testGetAncestorScrollableContainer_returnNull() {
+        mRoot.post(() -> assertThat(ViewUtils.getAncestorScrollableContainer(mView2)).isNull());
+    }
+
+    @Test
+    public void testFindFocusedByDefaultView() {
+        mRoot.post(() -> {
+            View focusedByDefault = ViewUtils.findFocusedByDefaultView(mRoot);
+            assertThat(focusedByDefault).isEqualTo(mFocusedByDefault3);
+        });
+    }
+
+    @Test
+    public void testFindFocusedByDefaultView_skipNotFocusable() {
+        mRoot.post(() -> {
+            mFocusedByDefault3.setFocusable(false);
+            View focusedByDefault = ViewUtils.findFocusedByDefaultView(mRoot);
+            assertThat(focusedByDefault).isNull();
+        });
+    }
+
+    @Test
+    public void testFindFocusedByDefaultView_skipInvisibleView() {
+        mRoot.post(() -> {
+            mFocusArea3.setVisibility(INVISIBLE);
+            assertThat(mFocusArea3.getVisibility()).isEqualTo(INVISIBLE);
+            View focusedByDefault = ViewUtils.findFocusedByDefaultView(mRoot);
+            assertThat(focusedByDefault).isNull();
+        });
+    }
+
+    @Test
+    public void testFindFocusedByDefaultView_skipInvisibleAncestor() {
+        mRoot.post(() -> {
+            mRoot.setVisibility(INVISIBLE);
+            View focusedByDefault = ViewUtils.findFocusedByDefaultView(mFocusArea3);
+            assertThat(focusedByDefault).isNull();
+        });
+    }
+
+    @Test
+    public void testFindImplicitDefaultFocusView_inRoot() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        View firstItem = mList5.getLayoutManager().findViewByPosition(0);
+                        View implicitDefaultFocus = ViewUtils.findImplicitDefaultFocusView(mRoot);
+                        assertThat(implicitDefaultFocus).isEqualTo(firstItem);
+                    }
+                }));
+    }
+
+    @Test
+    public void testFindImplicitDefaultFocusView_inFocusArea() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        View firstItem = mList5.getLayoutManager().findViewByPosition(0);
+                        View implicitDefaultFocus =
+                                ViewUtils.findImplicitDefaultFocusView(mFocusArea5);
+                        assertThat(implicitDefaultFocus).isEqualTo(firstItem);
+                    }
+                }));
+    }
+
+    @Test
+    public void testFindImplicitDefaultFocusView_skipInvisibleAncestor() {
+        mRoot.post(() -> {
+            mRoot.setVisibility(INVISIBLE);
+            View implicitDefaultFocus = ViewUtils.findImplicitDefaultFocusView(mFocusArea5);
+            assertThat(implicitDefaultFocus).isNull();
+        });
+    }
+
+    @Test
+    public void testFindFirstFocusableDescendant() {
+        mRoot.post(() -> {
+            mFocusArea2.setFocusable(true);
+            View firstFocusable = ViewUtils.findFirstFocusableDescendant(mRoot);
+            assertThat(firstFocusable).isEqualTo(mFocusArea2);
+        });
+    }
+
+    @Test
+    public void testFindFirstFocusableDescendant_skipItself() {
+        mRoot.post(() -> {
+            mFocusArea2.setFocusable(true);
+            View firstFocusable = ViewUtils.findFirstFocusableDescendant(mFocusArea2);
+            assertThat(firstFocusable).isEqualTo(mView2);
+        });
+    }
+
+    @Test
+    public void testFindFirstFocusableDescendant_skipInvisibleAndGoneView() {
+        mRoot.post(() -> {
+            mFocusArea2.setVisibility(INVISIBLE);
+            mFocusArea3.setVisibility(GONE);
+            View firstFocusable = ViewUtils.findFirstFocusableDescendant(mRoot);
+            assertThat(firstFocusable).isEqualTo(mView4);
+        });
+    }
+
+    @Test
+    public void testFindFirstFocusableDescendant_skipInvisibleAncestor() {
+        mRoot.post(() -> {
+            mRoot.setVisibility(INVISIBLE);
+            View firstFocusable = ViewUtils.findFirstFocusableDescendant(mFocusArea2);
+            assertThat(firstFocusable).isNull();
+        });
+    }
+
+    @Test
+    public void testIsImplicitDefaultFocusView_firstItem() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        View firstItem = mList5.getLayoutManager().findViewByPosition(0);
+                        assertThat(ViewUtils.isImplicitDefaultFocusView(firstItem)).isTrue();
+                    }
+                }));
+    }
+
+    @Test
+    public void testIsImplicitDefaultFocusView_secondItem() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        View secondItem = mList5.getLayoutManager().findViewByPosition(1);
+                        assertThat(ViewUtils.isImplicitDefaultFocusView(secondItem)).isFalse();
+                    }
+                }));
+    }
+
+    @Test
+    public void testIsImplicitDefaultFocusView_normalView() {
+        mRoot.post(() -> assertThat(ViewUtils.isImplicitDefaultFocusView(mView2)).isFalse());
+    }
+
+    @Test
+    public void testIsImplicitDefaultFocusView_skipInvisibleAncestor() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        mFocusArea5.setVisibility(INVISIBLE);
+                        View firstItem = mList5.getLayoutManager().findViewByPosition(0);
+                        assertThat(ViewUtils.isImplicitDefaultFocusView(firstItem)).isFalse();
+                    }
+                }));
+    }
+
+    @Test
+    public void testRequestFocus() {
+        mRoot.post(() -> assertRequestFocus(mView2, true));
+    }
+
+    @Test
+    public void testRequestFocus_nullView() {
+        mRoot.post(() -> assertRequestFocus(null, false));
+    }
+
+    @Test
+    public void testRequestFocus_alreadyFocused() {
+        mRoot.post(() -> {
+            assertRequestFocus(mView2, true);
+            // mView2 is already focused before requesting focus.
+            assertRequestFocus(mView2, true);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_notFocusable() {
+        mRoot.post(() -> {
+            mView2.setFocusable(false);
+            assertRequestFocus(mView2, false);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_disabled() {
+        mRoot.post(() -> {
+            mView2.setEnabled(false);
+            assertRequestFocus(mView2, false);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_notVisible() {
+        mRoot.post(() -> {
+            mView2.setVisibility(View.INVISIBLE);
+            assertRequestFocus(mView2, false);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_skipInvisibleAncestor() {
+        mRoot.post(() -> {
+            mFocusArea2.setVisibility(View.INVISIBLE);
+            assertRequestFocus(mView2, false);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_zeroWidth() {
+        mRoot.post(() -> {
+            mView2.setRight(mView2.getLeft());
+            assertThat(mView2.getWidth()).isEqualTo(0);
+            assertRequestFocus(mView2, false);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_detachedFromWindow() {
+        mRoot.post(() -> {
+            mFocusArea2.removeView(mView2);
+            assertRequestFocus(mView2, false);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_FocusParkingView() {
+        mRoot.post(() -> {
+            assertRequestFocus(mView2, true);
+            assertRequestFocus(mFpv, false);
+        });
+    }
+
+    @Test
+    public void testRequestFocus_rotaryContainer() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        assertRequestFocus(mList5, false);
+                    }
+                }));
+    }
+
+    @Test
+    public void testRequestFocus_scrollableContainer() {
+        mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        assertRequestFocus(mList5, false);
+                    }
+                }));
+    }
+
+    @Test
+    public void testAdjustFocus_inRoot() {
+        mRoot.post(() -> {
+            assertRequestFocus(mView2, true);
+            ViewUtils.adjustFocus(mRoot, null);
+            assertThat(mFocusedByDefault3.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testAdjustFocus_inFocusAreaWithDefaultFocus() {
+        mRoot.post(() -> {
+            assertRequestFocus(mView2, true);
+            ViewUtils.adjustFocus(mFocusArea3, null);
+            assertThat(mFocusedByDefault3.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testAdjustFocus_inFocusAreaWithoutDefaultFocus() {
+        mRoot.post(() -> {
+            assertRequestFocus(mView4, true);
+            ViewUtils.adjustFocus(mFocusArea2, null);
+            assertThat(mView2.isFocused()).isTrue();
+        });
+    }
+
+    @Test
+    public void testAdjustFocus_inFocusAreaWithoutFocusableDescendant() {
+        mRoot.post(() -> {
+            assertRequestFocus(mView2, true);
+            boolean success = ViewUtils.adjustFocus(mFocusArea1, null);
+            assertThat(mFocusArea1.hasFocus()).isFalse();
+            assertThat(success).isFalse();
+        });
+    }
+
+    @Test
+    public void testAdjustFocus_differentFocusLevels() {
+        mRoot.post(() -> {
+            assertThat(ViewUtils.adjustFocus(mFocusArea2, SCROLLABLE_CONTAINER_FOCUS)).isTrue();
+            assertThat(ViewUtils.adjustFocus(mFocusArea2, REGULAR_FOCUS)).isFalse();
+
+            assertThat(ViewUtils.adjustFocus(mFocusArea5, REGULAR_FOCUS)).isTrue();
+            assertThat(ViewUtils.adjustFocus(mFocusArea5, IMPLICIT_DEFAULT_FOCUS)).isFalse();
+
+            assertThat(ViewUtils.adjustFocus(mFocusArea4, IMPLICIT_DEFAULT_FOCUS)).isTrue();
+            assertThat(ViewUtils.adjustFocus(mFocusArea4, DEFAULT_FOCUS)).isFalse();
+
+            assertThat(ViewUtils.adjustFocus(mFocusArea3, DEFAULT_FOCUS)).isTrue();
+            assertThat(ViewUtils.adjustFocus(mFocusArea3, FOCUSED_BY_DEFAULT)).isFalse();
+
+            View firstItem = mList5.getLayoutManager().findViewByPosition(0);
+            firstItem.setFocusable(false);
+            View secondItem = mList5.getLayoutManager().findViewByPosition(1);
+            secondItem.setFocusable(false);
+            assertThat(ViewUtils.adjustFocus(mFocusArea5, NO_FOCUS)).isTrue();
+            assertThat(ViewUtils.adjustFocus(mFocusArea5, SCROLLABLE_CONTAINER_FOCUS)).isFalse();
+        });
+    }
+
+    @Test
+    public void testGetFocusLevel() {
+        mRoot.post(() -> {
+            assertThat(ViewUtils.getFocusLevel(null)).isEqualTo(NO_FOCUS);
+            assertThat(ViewUtils.getFocusLevel(mFpv)).isEqualTo(NO_FOCUS);
+            mFocusArea2.setVisibility(INVISIBLE);
+            assertThat(ViewUtils.getFocusLevel(mView2)).isEqualTo(NO_FOCUS);
+
+            assertThat(ViewUtils.getFocusLevel(mList5)).isEqualTo(SCROLLABLE_CONTAINER_FOCUS);
+
+            assertThat(ViewUtils.getFocusLevel(mView4)).isEqualTo(REGULAR_FOCUS);
+
+            mRoot.post(() -> mList5.getViewTreeObserver().addOnGlobalLayoutListener(
+                    new ViewTreeObserver.OnGlobalLayoutListener() {
+                        @Override
+                        public void onGlobalLayout() {
+                            mList5.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                            View firstItem = mList5.getLayoutManager().findViewByPosition(0);
+                            assertThat(ViewUtils.getFocusLevel(firstItem))
+                                    .isEqualTo(IMPLICIT_DEFAULT_FOCUS);
+                        }
+                    }));
+
+            assertThat(ViewUtils.getFocusLevel(mDefaultFocus4)).isEqualTo(DEFAULT_FOCUS);
+
+            assertThat(ViewUtils.getFocusLevel(mFocusedByDefault3)).isEqualTo(FOCUSED_BY_DEFAULT);
+        });
+    }
+
+    private static void assertRequestFocus(@Nullable View view, boolean focused) {
+        boolean result = ViewUtils.requestFocus(view);
+        assertThat(result).isEqualTo(focused);
+        if (view != null) {
+            assertThat(view.isFocused()).isEqualTo(focused);
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/utils/ViewUtilsTestActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/utils/ViewUtilsTestActivity.java
new file mode 100644
index 0000000..87434d4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/utils/ViewUtilsTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.car.ui.utils;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.car.ui.test.R;
+
+/** An activity used for testing {@link ViewUtils}. */
+public class ViewUtilsTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.view_utils_test_activity);
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/ic_launcher.png b/car-ui-lib/car-ui-lib/src/androidTest/res/drawable/ic_launcher.png
similarity index 100%
copy from car-ui-lib/tests/paintbooth/res/drawable/ic_launcher.png
copy to car-ui-lib/car-ui-lib/src/androidTest/res/drawable/ic_launcher.png
Binary files differ
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/drawable/ic_settings_gear.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/drawable/ic_settings_gear.xml
new file mode 100644
index 0000000..2b7fa2f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/drawable/ic_settings_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020 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.
+-->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0">
+    <path
+        android:fillColor="#fff"
+        android:pathData="M38.86,25.95c0.08,-0.64 0.14,-1.29 0.14,-1.95s-0.06,-1.31 -0.14,-1.95l4.23,-3.31c0.38,-0.3 0.49,-0.84 0.24,-1.28l-4,-6.93c-0.25,-0.43 -0.77,-0.61 -1.22,-0.43l-4.98,2.01c-1.03,-0.79 -2.16,-1.46 -3.38,-1.97L29,4.84c-0.09,-0.47 -0.5,-0.84 -1,-0.84h-8c-0.5,0 -0.91,0.37 -0.99,0.84l-0.75,5.3c-1.22,0.51 -2.35,1.17 -3.38,1.97L9.9,10.1c-0.45,-0.17 -0.97,0 -1.22,0.43l-4,6.93c-0.25,0.43 -0.14,0.97 0.24,1.28l4.22,3.31C9.06,22.69 9,23.34 9,24s0.06,1.31 0.14,1.95l-4.22,3.31c-0.38,0.3 -0.49,0.84 -0.24,1.28l4,6.93c0.25,0.43 0.77,0.61 1.22,0.43l4.98,-2.01c1.03,0.79 2.16,1.46 3.38,1.97l0.75,5.3c0.08,0.47 0.49,0.84 0.99,0.84h8c0.5,0 0.91,-0.37 0.99,-0.84l0.75,-5.3c1.22,-0.51 2.35,-1.17 3.38,-1.97l4.98,2.01c0.45,0.17 0.97,0 1.22,-0.43l4,-6.93c0.25,-0.43 0.14,-0.97 -0.24,-1.28l-4.22,-3.31zM24,31c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
+</vector>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_gone_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_gone_test_activity.xml
new file mode 100644
index 0000000..4ba25eb
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_gone_test_activity.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:visibility="gone"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_invisible_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_invisible_test_activity.xml
new file mode 100644
index 0000000..647c79b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_invisible_test_activity.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:visibility="invisible"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_test_activity.xml
new file mode 100644
index 0000000..891a56f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/car_ui_recycler_view_test_activity.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/details_preference_widget.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/details_preference_widget.xml
new file mode 100644
index 0000000..3912de1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/details_preference_widget.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020 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.
+-->
+
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:src="@drawable/ic_settings_gear"/>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/empty_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/empty_test_activity.xml
new file mode 100644
index 0000000..899fb3d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/empty_test_activity.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/test_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_area_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_area_test_activity.xml
new file mode 100644
index 0000000..da1255d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_area_test_activity.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <com.android.car.ui.FocusParkingView
+        android:id="@+id/fpv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+    <com.android.car.ui.TestFocusArea
+        android:id="@+id/focus_area1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:startBoundOffset="10dp"
+        app:endBoundOffset="20dp"
+        app:topBoundOffset="30dp"
+        app:bottomBoundOffset="40dp">
+        <View
+            android:id="@+id/view1"
+            android:focusable="true"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+        <Button
+            android:id="@+id/button1"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+    </com.android.car.ui.TestFocusArea>
+    <com.android.car.ui.TestFocusArea
+        android:id="@+id/focus_area2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:defaultFocus="@+id/default_focus2"
+        app:highlightPaddingHorizontal="10dp"
+        app:highlightPaddingVertical="20dp"
+        app:highlightPaddingStart="30dp"
+        app:highlightPaddingTop="40dp"
+        app:startBoundOffset="50dp">
+        <View
+            android:id="@+id/view2"
+            android:focusable="true"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+        <View
+            android:id="@+id/default_focus2"
+            android:focusable="true"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+    </com.android.car.ui.TestFocusArea>
+    <com.android.car.ui.TestFocusArea
+        android:id="@+id/focus_area3"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:nudgeShortcut="@+id/nudge_shortcut3"
+        app:nudgeShortcutDirection="right">
+        <View
+            android:id="@+id/view3"
+            android:focusable="true"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+        <View
+            android:focusable="true"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+        <View
+            android:id="@+id/nudge_shortcut3"
+            android:focusable="true"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+    </com.android.car.ui.TestFocusArea>
+    <com.android.car.ui.TestFocusArea
+        android:id="@+id/focus_area4"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:nudgeLeft="@+id/focus_area2">
+        <View
+            android:id="@+id/view4"
+            android:focusable="true"
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+    </com.android.car.ui.TestFocusArea>
+</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_parking_view_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_parking_view_test_activity.xml
new file mode 100644
index 0000000..02d7326
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_parking_view_test_activity.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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="match_parent">
+    <com.android.car.ui.FocusParkingView
+        android:id="@+id/fpv"
+        android:layout_width="10dp"
+        android:layout_height="10dp"/>
+    <LinearLayout
+        android:id="@+id/parent1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <View
+            android:id="@+id/view1"
+            android:layout_width="100dp"
+            android:layout_height="40dp"
+            android:focusable="true"/>
+    </LinearLayout>
+    <View
+        android:id="@+id/focused_by_default"
+        android:layout_width="100dp"
+        android:layout_height="40dp"
+        android:focusable="true"
+        android:focusedByDefault="true"/>
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/test_car_ui_recycler_view_list_item.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/test_car_ui_recycler_view_list_item.xml
new file mode 100644
index 0000000..8297f6b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/test_car_ui_recycler_view_list_item.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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"
+    android:focusable="true">
+
+    <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/car-ui-lib/src/androidTest/res/layout/test_list_item.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/test_list_item.xml
new file mode 100644
index 0000000..1fab70e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/test_list_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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"
+    android:focusable="true">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="10dp"
+        android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body"
+        android:id="@+id/text" />
+
+</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/view_utils_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/view_utils_test_activity.xml
new file mode 100644
index 0000000..72c2366
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/view_utils_test_activity.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.FocusParkingView
+        android:id="@+id/fpv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+    <com.android.car.ui.FocusArea
+        android:id="@+id/focus_area1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <View
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+    </com.android.car.ui.FocusArea>
+    <com.android.car.ui.FocusArea
+        android:id="@+id/focus_area2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <View
+            android:layout_width="100dp"
+            android:layout_height="100dp"/>
+        <View
+            android:id="@+id/view2"
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:focusable="true"/>
+    </com.android.car.ui.FocusArea>
+    <com.android.car.ui.FocusArea
+        android:id="@+id/focus_area3"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <View
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:focusable="true"/>
+        <View
+            android:id="@+id/focused_by_default3"
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:focusable="true"
+            android:focusedByDefault="true"/>
+    </com.android.car.ui.FocusArea>
+    <com.android.car.ui.FocusArea
+        android:id="@+id/focus_area4"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:defaultFocus="@+id/default_focus4">
+        <View
+            android:id="@+id/view4"
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:focusable="true"/>
+        <View
+            android:id="@+id/default_focus4"
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:focusable="true"/>
+    </com.android.car.ui.FocusArea>
+    <com.android.car.ui.FocusArea
+        android:id="@+id/focus_area5"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <com.android.car.ui.recyclerview.CarUiRecyclerView
+            android:id="@+id/list5"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+    </com.android.car.ui.FocusArea>
+</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/values/arrays.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/values/arrays.xml
new file mode 100644
index 0000000..9606ddd
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/values/arrays.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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>
+
+    <!-- Used for the entries in a list preference [CHAR_LIMIT=NONE]-->
+    <string-array name="entries">
+        <!-- The first sample choice [CHAR_LIMIT=NONE]-->
+        <item>Choose me!</item>
+        <!-- The second sample choice [CHAR_LIMIT=NONE]-->
+        <item>No, me!</item>
+        <!-- The third sample choice [CHAR_LIMIT=NONE]-->
+        <item>What about me?!</item>
+    </string-array>
+
+    <!-- Used for the values in a list preference -->
+    <string-array name="entry_values" translatable="false">
+        <!-- The first sample value -->
+        <item>alpha</item>
+        <!-- The second sample value -->
+        <item>beta</item>
+        <!-- The third sample value -->
+        <item>charlie</item>
+    </string-array>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/values/strings.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/values/strings.xml
new file mode 100644
index 0000000..7926d9c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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>
+    <string name="preferences_screen_title">Preferences</string>
+    <string name="preference_dialog_category">Dialog preferences</string>
+    <string name="title_list_preference">List preference</string>
+    <string name="dialog_title_list_preference">Choose one option!</string>
+    <string name="title_multi_list_preference">Multi-select list preference</string>
+    <string name="summary_multi_list_preference">Shows a dialog with multiple choice options</string>
+    <string name="dialog_title_multi_list_preference">Choose some options!</string>
+    <string name="preference_widgets_category">Widgets</string>
+    <string name="title_checkbox_preference">Checkbox preference</string>
+    <string name="summary_checkbox_preference">Tap anywhere in this preference to toggle state</string>
+    <string name="title_switch_preference">Switch preference</string>
+    <string name="summary_switch_preference">Tap anywhere in this preference to toggle state</string>
+    <string name="title_dropdown_preference">Dropdown preference</string>
+    <string name="title_twoaction_preference">TwoAction preference</string>
+    <string name="summary_twoaction_preference">A widget should be visible on the right</string>
+
+    <string-array name="test_string_array">
+        <item>Item 1</item>
+        <item>Item 2</item>
+        <item>Item 3</item>
+    </string-array>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/xml/test_preferences.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/xml/test_preferences.xml
new file mode 100644
index 0000000..042bbb0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/xml/test_preferences.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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.
+  -->
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    app:title="@string/preferences_screen_title">
+
+    <PreferenceCategory
+        android:title="@string/preference_dialog_category"
+        android:order="1">
+
+        <ListPreference
+            android:dialogTitle="@string/dialog_title_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="list"
+            android:title="@string/title_list_preference"
+            app:useSimpleSummaryProvider="true"/>
+
+        <MultiSelectListPreference
+            android:dialogTitle="@string/dialog_title_multi_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="multi_select_list"
+            android:summary="@string/summary_multi_list_preference"
+            android:title="@string/title_multi_list_preference"/>
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/AlertDialogBuilder.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/AlertDialogBuilder.java
new file mode 100644
index 0000000..803bb29
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/AlertDialogBuilder.java
@@ -0,0 +1,742 @@
+/*
+ * 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.
+ */
+package com.android.car.ui;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.text.InputFilter;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.TextView;
+
+import androidx.annotation.ArrayRes;
+import androidx.annotation.AttrRes;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
+import com.android.car.ui.recyclerview.CarUiRadioButtonListItemAdapter;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * Wrapper for AlertDialog.Builder
+ */
+public class AlertDialogBuilder {
+
+    private AlertDialog.Builder mBuilder;
+    private Context mContext;
+    private boolean mPositiveButtonSet;
+    private boolean mNeutralButtonSet;
+    private boolean mNegativeButtonSet;
+    private CharSequence mTitle;
+    private CharSequence mSubtitle;
+    private Drawable mIcon;
+    private boolean mIconTinted;
+    private boolean mAllowDismissButton = true;
+    private boolean mHasSingleChoiceBodyButton = false;
+
+    public AlertDialogBuilder(Context context) {
+        // Resource id specified as 0 uses the parent contexts resolved value for alertDialogTheme.
+        this(context, /* themeResId= */0);
+    }
+
+    public AlertDialogBuilder(Context context, int themeResId) {
+        mBuilder = new AlertDialog.Builder(context, themeResId);
+        mContext = context;
+    }
+
+    public Context getContext() {
+        return mBuilder.getContext();
+    }
+
+    /**
+     * Set the title using the given resource id.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setTitle(@StringRes int titleId) {
+        return setTitle(mContext.getText(titleId));
+    }
+
+    /**
+     * Set the title displayed in the {@link Dialog}.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setTitle(CharSequence title) {
+        mTitle = title;
+        mBuilder.setTitle(title);
+        return this;
+    }
+
+    /**
+     * Sets a subtitle to be displayed in the {@link Dialog}.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setSubtitle(@StringRes int subtitle) {
+        return setSubtitle(mContext.getString(subtitle));
+    }
+
+    /**
+     * Sets a subtitle to be displayed in the {@link Dialog}.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setSubtitle(CharSequence subtitle) {
+        mSubtitle = subtitle;
+        return this;
+    }
+
+    /**
+     * Set the message to display using the given resource id.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setMessage(@StringRes int messageId) {
+        mBuilder.setMessage(messageId);
+        return this;
+    }
+
+    /**
+     * Set the message to display.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setMessage(CharSequence message) {
+        mBuilder.setMessage(message);
+        return this;
+    }
+
+    /**
+     * Set the resource id of the {@link Drawable} to be used in the title.
+     * <p>
+     * Takes precedence over values set using {@link #setIcon(Drawable)}.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setIcon(@DrawableRes int iconId) {
+        return setIcon(mContext.getDrawable(iconId));
+    }
+
+    /**
+     * Set the {@link Drawable} to be used in the title.
+     * <p>
+     * <strong>Note:</strong> To ensure consistent styling, the drawable
+     * should be inflated or constructed using the alert dialog's themed
+     * context obtained via {@link #getContext()}.
+     *
+     * @return this Builder object to allow for chaining of calls to set
+     * methods
+     */
+    public AlertDialogBuilder setIcon(Drawable icon) {
+        mIcon = icon;
+        return this;
+    }
+
+    /**
+     * Whether the icon provided by {@link #setIcon(Drawable)} should be
+     * tinted with the default system color.
+     *
+     * @return this Builder object to allow for chaining of calls to set
+     * methods.
+     */
+    public AlertDialogBuilder setIconTinted(boolean tinted) {
+        mIconTinted = tinted;
+        return this;
+    }
+
+    /**
+     * Set an icon as supplied by a theme attribute. e.g.
+     * {@link android.R.attr#alertDialogIcon}.
+     * <p>
+     * Takes precedence over values set using {@link #setIcon(Drawable)}.
+     *
+     * @param attrId ID of a theme attribute that points to a drawable resource.
+     */
+    public AlertDialogBuilder setIconAttribute(@AttrRes int attrId) {
+        mBuilder.setIconAttribute(attrId);
+        return this;
+    }
+
+    /**
+     * Set a listener to be invoked when the positive button of the dialog is pressed.
+     *
+     * @param textId The resource id of the text to display in the positive button
+     * @param listener The {@link DialogInterface.OnClickListener} to use.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setPositiveButton(@StringRes int textId,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setPositiveButton(textId, listener);
+        mPositiveButtonSet = true;
+        return this;
+    }
+
+    /**
+     * Set a listener to be invoked when the positive button of the dialog is pressed.
+     *
+     * @param text The text to display in the positive button
+     * @param listener The {@link DialogInterface.OnClickListener} to use.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setPositiveButton(CharSequence text,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setPositiveButton(text, listener);
+        mPositiveButtonSet = true;
+        return this;
+    }
+
+    /**
+     * Set a listener to be invoked when the negative button of the dialog is pressed.
+     *
+     * @param textId The resource id of the text to display in the negative button
+     * @param listener The {@link DialogInterface.OnClickListener} to use.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setNegativeButton(@StringRes int textId,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setNegativeButton(textId, listener);
+        mNegativeButtonSet = true;
+        return this;
+    }
+
+    /**
+     * Set a listener to be invoked when the negative button of the dialog is pressed.
+     *
+     * @param text The text to display in the negative button
+     * @param listener The {@link DialogInterface.OnClickListener} to use.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setNegativeButton(CharSequence text,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setNegativeButton(text, listener);
+        mNegativeButtonSet = true;
+        return this;
+    }
+
+    /**
+     * Set a listener to be invoked when the neutral button of the dialog is pressed.
+     *
+     * @param textId The resource id of the text to display in the neutral button
+     * @param listener The {@link DialogInterface.OnClickListener} to use.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setNeutralButton(@StringRes int textId,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setNeutralButton(textId, listener);
+        mNeutralButtonSet = true;
+        return this;
+    }
+
+    /**
+     * Set a listener to be invoked when the neutral button of the dialog is pressed.
+     *
+     * @param text The text to display in the neutral button
+     * @param listener The {@link DialogInterface.OnClickListener} to use.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setNeutralButton(CharSequence text,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setNeutralButton(text, listener);
+        mNeutralButtonSet = true;
+        return this;
+    }
+
+    /**
+     * Sets whether the dialog is cancelable or not.  Default is true.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setCancelable(boolean cancelable) {
+        mBuilder.setCancelable(cancelable);
+        return this;
+    }
+
+    /**
+     * Sets the callback that will be called if the dialog is canceled.
+     *
+     * <p>Even in a cancelable dialog, the dialog may be dismissed for reasons other than
+     * being canceled or one of the supplied choices being selected.
+     * If you are interested in listening for all cases where the dialog is dismissed
+     * and not just when it is canceled, see
+     * {@link #setOnDismissListener(android.content.DialogInterface.OnDismissListener)
+     * setOnDismissListener}.</p>
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     * @see #setCancelable(boolean)
+     * @see #setOnDismissListener(android.content.DialogInterface.OnDismissListener)
+     */
+    public AlertDialogBuilder setOnCancelListener(
+            DialogInterface.OnCancelListener onCancelListener) {
+        mBuilder.setOnCancelListener(onCancelListener);
+        return this;
+    }
+
+    /**
+     * Sets the callback that will be called when the dialog is dismissed for any reason.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setOnDismissListener(
+            DialogInterface.OnDismissListener onDismissListener) {
+        mBuilder.setOnDismissListener(onDismissListener);
+        return this;
+    }
+
+    /**
+     * Sets the callback that will be called if a key is dispatched to the dialog.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setOnKeyListener(DialogInterface.OnKeyListener onKeyListener) {
+        mBuilder.setOnKeyListener(onKeyListener);
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content, you will be notified of the
+     * selected item via the supplied listener. This should be an array type i.e. R.array.foo
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setItems(@ArrayRes int itemsId,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setItems(itemsId, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content, you will be notified of the
+     * selected item via the supplied listener.
+     *
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setItems(CharSequence[] items,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setItems(items, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * This was not supposed to be in the Chassis API because it allows custom views.
+     *
+     * @deprecated Use {@link #setAdapter(CarUiListItemAdapter)} instead.
+     */
+    @Deprecated
+    public AlertDialogBuilder setAdapter(final ListAdapter adapter,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setAdapter(adapter, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Display all the {@link com.android.car.ui.recyclerview.CarUiListItem CarUiListItems} in a
+     * {@link CarUiListItemAdapter}. You should set click listeners on the CarUiListItems as
+     * opposed to a callback in this function.
+     */
+    public AlertDialogBuilder setAdapter(final CarUiListItemAdapter adapter) {
+        setCustomList(adapter);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    private void setCustomList(@NonNull CarUiListItemAdapter adapter) {
+        View customList = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_alert_dialog_list, null);
+        RecyclerView mList = CarUiUtils.requireViewByRefId(customList, R.id.list);
+        mList.setLayoutManager(new LinearLayoutManager(mContext));
+        mList.setAdapter(adapter);
+        mBuilder.setView(customList);
+    }
+
+    /**
+     * Set a list of items, which are supplied by the given {@link Cursor}, to be
+     * displayed in the dialog as the content, you will be notified of the
+     * selected item via the supplied listener.
+     *
+     * @param cursor The {@link Cursor} to supply the list of items
+     * @param listener The listener that will be called when an item is clicked.
+     * @param labelColumn The column name on the cursor containing the string to display
+     * in the label.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setCursor(final Cursor cursor,
+            final DialogInterface.OnClickListener listener,
+            String labelColumn) {
+        mBuilder.setCursor(cursor, listener, labelColumn);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content,
+     * you will be notified of the selected item via the supplied listener.
+     * This should be an array type, e.g. R.array.foo. The list will have
+     * a check mark displayed to the right of the text for each checked
+     * item. Clicking on an item in the list will not dismiss the dialog.
+     * Clicking on a button will dismiss the dialog.
+     *
+     * @param itemsId the resource id of an array i.e. R.array.foo
+     * @param checkedItems specifies which items are checked. It should be null in which case no
+     * items are checked. If non null it must be exactly the same length as the array of
+     * items.
+     * @param listener notified when an item on the list is clicked. The dialog will not be
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems,
+            final DialogInterface.OnMultiChoiceClickListener listener) {
+        mBuilder.setMultiChoiceItems(itemsId, checkedItems, listener);
+        mHasSingleChoiceBodyButton = false;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content,
+     * you will be notified of the selected item via the supplied listener.
+     * The list will have a check mark displayed to the right of the text
+     * for each checked item. Clicking on an item in the list will not
+     * dismiss the dialog. Clicking on a button will dismiss the dialog.
+     *
+     * @param items the text of the items to be displayed in the list.
+     * @param checkedItems specifies which items are checked. It should be null in which case no
+     * items are checked. If non null it must be exactly the same length as the array of
+     * items.
+     * @param listener notified when an item on the list is clicked. The dialog will not be
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems,
+            final DialogInterface.OnMultiChoiceClickListener listener) {
+        mBuilder.setMultiChoiceItems(items, checkedItems, listener);
+        mHasSingleChoiceBodyButton = false;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content,
+     * you will be notified of the selected item via the supplied listener.
+     * The list will have a check mark displayed to the right of the text
+     * for each checked item. Clicking on an item in the list will not
+     * dismiss the dialog. Clicking on a button will dismiss the dialog.
+     *
+     * @param cursor the cursor used to provide the items.
+     * @param isCheckedColumn specifies the column name on the cursor to use to determine
+     * whether a checkbox is checked or not. It must return an integer value where 1
+     * means checked and 0 means unchecked.
+     * @param labelColumn The column name on the cursor containing the string to display in the
+     * label.
+     * @param listener notified when an item on the list is clicked. The dialog will not be
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setMultiChoiceItems(Cursor cursor, String isCheckedColumn,
+            String labelColumn,
+            final DialogInterface.OnMultiChoiceClickListener listener) {
+        mBuilder.setMultiChoiceItems(cursor, isCheckedColumn, labelColumn, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content, you will be notified of
+     * the selected item via the supplied listener. This should be an array type i.e.
+     * R.array.foo The list will have a check mark displayed to the right of the text for the
+     * checked item. Clicking on an item in the list will not dismiss the dialog. Clicking on a
+     * button will dismiss the dialog.
+     *
+     * @param itemsId the resource id of an array i.e. R.array.foo
+     * @param checkedItem specifies which item is checked. If -1 no items are checked.
+     * @param listener notified when an item on the list is clicked. The dialog will not be
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setSingleChoiceItems(itemsId, checkedItem, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content, you will be notified of
+     * the selected item via the supplied listener. The list will have a check mark displayed to
+     * the right of the text for the checked item. Clicking on an item in the list will not
+     * dismiss the dialog. Clicking on a button will dismiss the dialog.
+     *
+     * @param cursor the cursor to retrieve the items from.
+     * @param checkedItem specifies which item is checked. If -1 no items are checked.
+     * @param labelColumn The column name on the cursor containing the string to display in the
+     * label.
+     * @param listener notified when an item on the list is clicked. The dialog will not be
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setSingleChoiceItems(Cursor cursor, int checkedItem,
+            String labelColumn,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setSingleChoiceItems(cursor, checkedItem, labelColumn, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content, you will be notified of
+     * the selected item via the supplied listener. The list will have a check mark displayed to
+     * the right of the text for the checked item. Clicking on an item in the list will not
+     * dismiss the dialog. Clicking on a button will dismiss the dialog.
+     *
+     * @param items the items to be displayed.
+     * @param checkedItem specifies which item is checked. If -1 no items are checked.
+     * @param listener notified when an item on the list is clicked. The dialog will not be
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setSingleChoiceItems(CharSequence[] items, int checkedItem,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setSingleChoiceItems(items, checkedItem, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * This was not supposed to be in the Chassis API because it allows custom views.
+     *
+     * @deprecated Use {@link #setSingleChoiceItems(CarUiRadioButtonListItemAdapter,
+     * DialogInterface.OnClickListener)} instead.
+     */
+    @Deprecated
+    public AlertDialogBuilder setSingleChoiceItems(ListAdapter adapter, int checkedItem,
+            final DialogInterface.OnClickListener listener) {
+        mBuilder.setSingleChoiceItems(adapter, checkedItem, listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content, you will be notified of
+     * the selected item via the supplied listener. The list will have a check mark displayed to
+     * the right of the text for the checked item. Clicking on an item in the list will not
+     * dismiss the dialog. Clicking on a button will dismiss the dialog.
+     *
+     * @param adapter The {@link CarUiRadioButtonListItemAdapter} to supply the list of items
+     * @param listener notified when an item on the list is clicked. The dialog will not be
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     *
+     * @deprecated Use {@link #setSingleChoiceItems(CarUiRadioButtonListItemAdapter)} instead.
+     */
+    @Deprecated
+    public AlertDialogBuilder setSingleChoiceItems(CarUiRadioButtonListItemAdapter adapter,
+            final DialogInterface.OnClickListener listener) {
+        setCustomList(adapter);
+        mHasSingleChoiceBodyButton = false;
+        return this;
+    }
+
+    /**
+     * Set a list of items to be displayed in the dialog as the content,The list will have a check
+     * mark displayed to the right of the text for the checked item. Clicking on an item in the list
+     * will not dismiss the dialog. Clicking on a button will dismiss the dialog.
+     *
+     * @param adapter The {@link CarUiRadioButtonListItemAdapter} to supply the list of items
+     * dismissed when an item is clicked. It will only be dismissed if clicked on a
+     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
+     * @return This Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setSingleChoiceItems(CarUiRadioButtonListItemAdapter adapter) {
+        setCustomList(adapter);
+        mHasSingleChoiceBodyButton = false;
+        return this;
+    }
+
+    /**
+     * Sets a listener to be invoked when an item in the list is selected.
+     *
+     * @param listener the listener to be invoked
+     * @return this Builder object to allow for chaining of calls to set methods
+     * @see AdapterView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
+     */
+    public AlertDialogBuilder setOnItemSelectedListener(
+            final AdapterView.OnItemSelectedListener listener) {
+        mBuilder.setOnItemSelectedListener(listener);
+        mHasSingleChoiceBodyButton = true;
+        return this;
+    }
+
+    /**
+     * Sets a custom edit text box within the alert dialog.
+     *
+     * @param prompt the string that will be set on the edit text view
+     * @param textChangedListener textWatcher whose methods are called whenever this TextView's text
+     * changes {@link null} otherwise.
+     * @param inputFilters list of input filters, {@link null} if no filter is needed
+     * @param inputType See {@link EditText#setInputType(int)}, except
+     *                  {@link android.text.InputType#TYPE_NULL} will not be set.
+     * @return this Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setEditBox(String prompt, TextWatcher textChangedListener,
+            InputFilter[] inputFilters, int inputType) {
+        View contentView = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_alert_dialog_edit_text, null);
+
+        EditText editText = CarUiUtils.requireViewByRefId(contentView, R.id.textbox);
+        editText.setText(prompt);
+
+        if (textChangedListener != null) {
+            editText.addTextChangedListener(textChangedListener);
+        }
+
+        if (inputFilters != null) {
+            editText.setFilters(inputFilters);
+        }
+
+        if (inputType != 0) {
+            editText.setInputType(inputType);
+        }
+
+        mBuilder.setView(contentView);
+        return this;
+    }
+
+    /**
+     * Sets a custom edit text box within the alert dialog.
+     *
+     * @param prompt the string that will be set on the edit text view
+     * @param textChangedListener textWatcher whose methods are called whenever this TextView's text
+     * changes {@link null} otherwise.
+     * @param inputFilters list of input filters, {@link null} if no filter is needed
+     * @return this Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setEditBox(String prompt, TextWatcher textChangedListener,
+            InputFilter[] inputFilters) {
+        return setEditBox(prompt, textChangedListener, inputFilters, 0);
+    }
+
+    /**
+     * By default, the AlertDialogBuilder may add a "Dismiss" button if you don't provide
+     * a positive/negative/neutral button. This is so that the dialog is still dismissible
+     * using the rotary controller. If however, you add buttons that can close the dialog via
+     * {@link #setAdapter(CarUiListItemAdapter)} or a similar method, then you may wish to
+     * suppress the addition of the dismiss button, which this method allows for.
+     *
+     * @param allowDismissButton If true, a "Dismiss" button may be added to the dialog.
+     *                           If false, it will never be added.
+     * @return this Builder object to allow for chaining of calls to set methods
+     */
+    public AlertDialogBuilder setAllowDismissButton(boolean allowDismissButton) {
+        mAllowDismissButton = allowDismissButton;
+        return this;
+    }
+
+
+    /** Final steps common to both {@link #create()} and {@link #show()} */
+    private void prepareDialog() {
+        View customTitle = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_alert_dialog_title_with_subtitle, null);
+
+        TextView mTitleView = CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_title);
+        TextView mSubtitleView =
+                CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_subtitle);
+        mSubtitleView.setMovementMethod(LinkMovementMethod.getInstance());
+        ImageView mIconView = CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_icon);
+
+        mTitleView.setText(mTitle);
+        mTitleView.setVisibility(TextUtils.isEmpty(mTitle) ? View.GONE : View.VISIBLE);
+        mSubtitleView.setText(mSubtitle);
+        mSubtitleView.setVisibility(TextUtils.isEmpty(mSubtitle) ? View.GONE : View.VISIBLE);
+        mIconView.setImageDrawable(mIcon);
+        mIconView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
+        if (mIconTinted) {
+            mIconView.setImageTintList(
+                    mContext.getColorStateList(R.color.car_ui_dialog_icon_color));
+        }
+        mBuilder.setCustomTitle(customTitle);
+
+        if (!mAllowDismissButton && !mHasSingleChoiceBodyButton
+                && !mNeutralButtonSet && !mNegativeButtonSet && !mPositiveButtonSet) {
+            throw new RuntimeException(
+                    "The dialog must have at least one button to disable the dismiss button");
+        }
+        if (mContext.getResources().getBoolean(R.bool.car_ui_alert_dialog_force_dismiss_button)
+                && !mNeutralButtonSet && !mNegativeButtonSet && !mPositiveButtonSet
+                && mAllowDismissButton) {
+            String mDefaultButtonText = mContext.getString(
+                    R.string.car_ui_alert_dialog_default_button);
+            mBuilder.setNegativeButton(mDefaultButtonText, (dialog, which) -> {
+            });
+        }
+    }
+
+    /**
+     * Creates an {@link AlertDialog} with the arguments supplied to this
+     * builder.
+     * <p>
+     * Calling this method does not display the dialog. If no additional
+     * processing is needed, {@link #show()} may be called instead to both
+     * create and display the dialog.
+     */
+    public AlertDialog create() {
+        prepareDialog();
+        AlertDialog alertDialog = mBuilder.create();
+
+        // Put a FocusParkingView at the end of dialog window to prevent rotary controller
+        // wrap-around. Android will focus on the first view automatically when the dialog is shown,
+        // and we want it to focus on the title instead of the FocusParkingView, so we put the
+        // FocusParkingView at the end of dialog window.
+        ViewGroup root = (ViewGroup) alertDialog.getWindow().getDecorView().getRootView();
+        FocusParkingView fpv = new FocusParkingView(mContext);
+        root.addView(fpv);
+
+        return alertDialog;
+    }
+
+    /**
+     * Creates an {@link AlertDialog} with the arguments supplied to this
+     * builder and immediately displays the dialog.
+     */
+    public AlertDialog show() {
+        AlertDialog alertDialog = create();
+        alertDialog.show();
+        return alertDialog;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusArea.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusArea.java
new file mode 100644
index 0000000..0488d28
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusArea.java
@@ -0,0 +1,747 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+
+import static com.android.car.ui.utils.RotaryConstants.ACTION_NUDGE_SHORTCUT;
+import static com.android.car.ui.utils.RotaryConstants.ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_BOTTOM_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_LEFT_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_RIGHT_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.FOCUS_AREA_TOP_BOUND_OFFSET;
+import static com.android.car.ui.utils.RotaryConstants.NUDGE_DIRECTION;
+import static com.android.car.ui.utils.ViewUtils.NO_FOCUS;
+import static com.android.car.ui.utils.ViewUtils.REGULAR_FOCUS;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.LinearLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.ui.utils.CarUiUtils;
+import com.android.car.ui.utils.ViewUtils;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A {@link LinearLayout} used as a navigation block for the rotary controller.
+ * <p>
+ * The {@link com.android.car.rotary.RotaryService} looks for instances of {@link FocusArea} in the
+ * view hierarchy when handling rotate and nudge actions. When receiving a rotation event ({@link
+ * android.car.input.RotaryEvent}), RotaryService will move the focus to another {@link View} that
+ * can take focus within the same FocusArea. When receiving a nudge event ({@link
+ * KeyEvent#KEYCODE_SYSTEM_NAVIGATION_UP}, {@link KeyEvent#KEYCODE_SYSTEM_NAVIGATION_DOWN}, {@link
+ * KeyEvent#KEYCODE_SYSTEM_NAVIGATION_LEFT}, or {@link KeyEvent#KEYCODE_SYSTEM_NAVIGATION_RIGHT}),
+ * RotaryService will move the focus to another view that can take focus in another (typically
+ * adjacent) FocusArea.
+ * <p>
+ * If enabled, FocusArea can draw highlights when one of its descendants has focus and it's not in
+ * touch mode.
+ * <p>
+ * When creating a navigation block in the layout file, if you intend to use a LinearLayout as a
+ * container for that block, just use a FocusArea instead; otherwise wrap the block in a FocusArea.
+ * <p>
+ * DO NOT nest a FocusArea inside another FocusArea because it will result in undefined navigation
+ * behavior.
+ */
+public class FocusArea extends LinearLayout {
+
+    private static final String TAG = "FocusArea";
+
+    private static final int INVALID_DIMEN = -1;
+
+    private static final int INVALID_DIRECTION = -1;
+
+    private static final List<Integer> NUDGE_DIRECTIONS =
+            Arrays.asList(FOCUS_LEFT, FOCUS_RIGHT, FOCUS_UP, FOCUS_DOWN);
+
+    /** Whether the FocusArea's descendant has focus (the FocusArea itself is not focusable). */
+    private boolean mHasFocus;
+
+    /**
+     * Whether to draw {@link #mForegroundHighlight} when one of the FocusArea's descendants has
+     * focus and it's not in touch mode.
+     */
+    private boolean mEnableForegroundHighlight;
+
+    /**
+     * Whether to draw {@link #mBackgroundHighlight} when one of the FocusArea's descendants has
+     * focus and it's not in touch mode.
+     */
+    private boolean mEnableBackgroundHighlight;
+
+    /**
+     * Highlight (typically outline of the FocusArea) drawn on top of the FocusArea and its
+     * descendants.
+     */
+    private Drawable mForegroundHighlight;
+
+    /**
+     * Highlight (typically a solid or gradient shape) drawn on top of the FocusArea but behind its
+     * descendants.
+     */
+    private Drawable mBackgroundHighlight;
+
+    /** The padding (in pixels) of the FocusArea highlight. */
+    private int mPaddingLeft;
+    private int mPaddingRight;
+    private int mPaddingTop;
+    private int mPaddingBottom;
+
+    /** The offset (in pixels) of the FocusArea's bounds. */
+    private int mLeftOffset;
+    private int mRightOffset;
+    private int mTopOffset;
+    private int mBottomOffset;
+
+    /** Whether the layout direction is {@link View#LAYOUT_DIRECTION_RTL}. */
+    private boolean mRtl;
+
+    /** The ID of the view specified in {@code app:defaultFocus}. */
+    private int mDefaultFocusId;
+    /** The view specified in {@code app:defaultFocus}. */
+    @Nullable
+    private View mDefaultFocusView;
+
+    /**
+     * Whether to focus on the {@code app:defaultFocus} view when nudging to the FocusArea, even if
+     * there was another view in the FocusArea focused before.
+     */
+    private boolean mDefaultFocusOverridesHistory;
+
+    /** The ID of the view specified in {@code app:nudgeShortcut}. */
+    private int mNudgeShortcutId;
+    /** The view specified in {@code app:nudgeShortcut}. */
+    @Nullable
+    private View mNudgeShortcutView;
+
+    /** The direction specified in {@code app:nudgeShortcutDirection}. */
+    private int mNudgeShortcutDirection;
+
+    /**
+     * Map of nudge target FocusArea IDs specified in {@code app:nudgeLeft}, {@code app:nudgRight},
+     * {@code app:nudgeUp}, or {@code app:nudgeDown}.
+     */
+    private Map<Integer, Integer> mSpecifiedNudgeIdMap;
+
+    /** Map of specified nudge target FocusAreas. */
+    private Map<Integer, FocusArea> mSpecifiedNudgeFocusAreaMap;
+
+    /**
+     * Cache of focus history and nudge history of the rotary controller.
+     * <p>
+     * For focus history, the previously focused view and a timestamp will be saved when the
+     * focused view has changed.
+     * <p>
+     * For nudge history, the target FocusArea, direction, and a timestamp will be saved when the
+     * focus has moved from another FocusArea to this FocusArea. There are 2 cases:
+     * <ul>
+     *     <li>The focus is moved to another FocusArea because this FocusArea has called {@link
+     *         #nudgeToAnotherFocusArea}. In this case, the target FocusArea and direction are
+     *         trivial to this FocusArea.
+     *     <li>The focus is moved to this FocusArea because RotaryService has performed {@link
+     *         AccessibilityNodeInfo#ACTION_FOCUS} on this FocusArea. In this case, this FocusArea
+     *         can get the source FocusArea through the {@link
+     *         android.view.ViewTreeObserver.OnGlobalFocusChangeListener} registered, and can get
+     *         the direction when handling the action. Since the listener is triggered before
+     *         {@link #requestFocus} returns (which is called when handling the action), the
+     *         source FocusArea is revealed earlier than the direction, so the nudge history should
+     *         be saved when the direction is revealed.
+     * </ul>
+     */
+    private RotaryCache mRotaryCache;
+
+    /** Whether to clear focus area history when the user rotates the rotary controller. */
+    private boolean mClearFocusAreaHistoryWhenRotating;
+
+    /** The FocusArea that had focus before this FocusArea, if any. */
+    private FocusArea mPreviousFocusArea;
+
+    /** The focused view in this FocusArea, if any. */
+    private View mFocusedView;
+
+    public FocusArea(Context context) {
+        super(context);
+        init(context, null);
+    }
+
+    public FocusArea(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs);
+    }
+
+    public FocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs);
+    }
+
+    public FocusArea(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(context, attrs);
+    }
+
+    private void init(Context context, @Nullable AttributeSet attrs) {
+        Resources resources = getContext().getResources();
+        mEnableForegroundHighlight = resources.getBoolean(
+                R.bool.car_ui_enable_focus_area_foreground_highlight);
+        mEnableBackgroundHighlight = resources.getBoolean(
+                R.bool.car_ui_enable_focus_area_background_highlight);
+        mForegroundHighlight = resources.getDrawable(
+                R.drawable.car_ui_focus_area_foreground_highlight, getContext().getTheme());
+        mBackgroundHighlight = resources.getDrawable(
+                R.drawable.car_ui_focus_area_background_highlight, getContext().getTheme());
+
+        mDefaultFocusOverridesHistory = resources.getBoolean(
+                R.bool.car_ui_focus_area_default_focus_overrides_history);
+        mClearFocusAreaHistoryWhenRotating = resources.getBoolean(
+                R.bool.car_ui_clear_focus_area_history_when_rotating);
+
+        @RotaryCache.CacheType
+        int focusHistoryCacheType = resources.getInteger(R.integer.car_ui_focus_history_cache_type);
+        int focusHistoryExpirationPeriodMs =
+                resources.getInteger(R.integer.car_ui_focus_history_expiration_period_ms);
+        @RotaryCache.CacheType
+        int focusAreaHistoryCacheType = resources.getInteger(
+                R.integer.car_ui_focus_area_history_cache_type);
+        int focusAreaHistoryExpirationPeriodMs =
+                resources.getInteger(R.integer.car_ui_focus_area_history_expiration_period_ms);
+        mRotaryCache = new RotaryCache(focusHistoryCacheType, focusHistoryExpirationPeriodMs,
+                focusAreaHistoryCacheType, focusAreaHistoryExpirationPeriodMs);
+
+        // Ensure that an AccessibilityNodeInfo is created for this view.
+        setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+
+        // By default all ViewGroup subclasses do not call their draw() and onDraw() methods. We
+        // should enable it since we override these methods.
+        setWillNotDraw(false);
+
+        registerFocusChangeListener();
+
+        initAttrs(context, attrs);
+    }
+
+    private void registerFocusChangeListener() {
+        getViewTreeObserver().addOnGlobalFocusChangeListener(
+                (oldFocus, newFocus) -> {
+                    boolean hasFocus = hasFocus();
+                    saveFocusHistory(hasFocus);
+                    maybeUpdatePreviousFocusArea(hasFocus, oldFocus);
+                    maybeClearFocusAreaHistory(hasFocus, oldFocus);
+                    maybeUpdateFocusAreaHighlight(hasFocus);
+                    mHasFocus = hasFocus;
+                });
+    }
+
+    private void saveFocusHistory(boolean hasFocus) {
+        if (!hasFocus) {
+            mRotaryCache.saveFocusedView(mFocusedView, SystemClock.uptimeMillis());
+            mFocusedView = null;
+            return;
+        }
+        View v = getFocusedChild();
+        while (v != null) {
+            if (v.isFocused()) {
+                break;
+            }
+            v = v instanceof ViewGroup ? ((ViewGroup) v).getFocusedChild() : null;
+        }
+        mFocusedView = v;
+    }
+
+    /**
+     * Updates {@link #mPreviousFocusArea} when the focus has moved from another FocusArea to this
+     * FocusArea, and sets it to {@code null} in any other cases.
+     */
+    private void maybeUpdatePreviousFocusArea(boolean hasFocus, View oldFocus) {
+        if (mHasFocus || !hasFocus || oldFocus == null || oldFocus instanceof FocusParkingView) {
+            mPreviousFocusArea = null;
+            return;
+        }
+        mPreviousFocusArea = ViewUtils.getAncestorFocusArea(oldFocus);
+        if (mPreviousFocusArea == null) {
+            Log.w(TAG, "No parent FocusArea for " + oldFocus);
+        }
+    }
+
+    /**
+     * Clears FocusArea nudge history when the user rotates the controller to move focus within this
+     * FocusArea.
+     */
+    private void maybeClearFocusAreaHistory(boolean hasFocus, View oldFocus) {
+        if (!mClearFocusAreaHistoryWhenRotating) {
+            return;
+        }
+        if (!hasFocus || oldFocus == null) {
+            return;
+        }
+        FocusArea oldFocusArea = ViewUtils.getAncestorFocusArea(oldFocus);
+        if (oldFocusArea != this) {
+            return;
+        }
+        mRotaryCache.clearFocusAreaHistory();
+    }
+
+    /** Updates highlight of the FocusArea if this FocusArea has gained or lost focus. */
+    private void maybeUpdateFocusAreaHighlight(boolean hasFocus) {
+        if (!mEnableBackgroundHighlight && !mEnableForegroundHighlight) {
+            return;
+        }
+        if (mHasFocus != hasFocus) {
+            invalidate();
+        }
+    }
+
+    private void initAttrs(Context context, @Nullable AttributeSet attrs) {
+        if (attrs == null) {
+            return;
+        }
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FocusArea);
+        try {
+            mDefaultFocusId = a.getResourceId(R.styleable.FocusArea_defaultFocus, View.NO_ID);
+
+            // Initialize the highlight padding. The padding, for example, left padding, is set in
+            // the following order:
+            // 1. if highlightPaddingStart (or highlightPaddingEnd in RTL layout) specified, use it
+            // 2. otherwise, if highlightPaddingHorizontal is specified, use it
+            // 3. otherwise use 0
+
+            int paddingStart = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_highlightPaddingStart, INVALID_DIMEN);
+            if (paddingStart == INVALID_DIMEN) {
+                paddingStart = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_highlightPaddingHorizontal, 0);
+            }
+
+            int paddingEnd = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_highlightPaddingEnd, INVALID_DIMEN);
+            if (paddingEnd == INVALID_DIMEN) {
+                paddingEnd = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_highlightPaddingHorizontal, 0);
+            }
+
+            mRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+            mPaddingLeft = mRtl ? paddingEnd : paddingStart;
+            mPaddingRight = mRtl ? paddingStart : paddingEnd;
+
+            mPaddingTop = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_highlightPaddingTop, INVALID_DIMEN);
+            if (mPaddingTop == INVALID_DIMEN) {
+                mPaddingTop = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_highlightPaddingVertical, 0);
+            }
+
+            mPaddingBottom = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_highlightPaddingBottom, INVALID_DIMEN);
+            if (mPaddingBottom == INVALID_DIMEN) {
+                mPaddingBottom = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_highlightPaddingVertical, 0);
+            }
+
+            // Initialize the offset of the FocusArea's bounds. The offset, for example, left
+            // offset, is set in the following order:
+            // 1. if startBoundOffset (or endBoundOffset in RTL layout) specified, use it
+            // 2. otherwise, if horizontalBoundOffset is specified, use it
+            // 3. otherwise use mPaddingLeft
+
+            int startOffset = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_startBoundOffset, INVALID_DIMEN);
+            if (startOffset == INVALID_DIMEN) {
+                startOffset = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_horizontalBoundOffset, paddingStart);
+            }
+
+            int endOffset = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_endBoundOffset, INVALID_DIMEN);
+            if (endOffset == INVALID_DIMEN) {
+                endOffset = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_horizontalBoundOffset, paddingEnd);
+            }
+
+            mLeftOffset = mRtl ? endOffset : startOffset;
+            mRightOffset = mRtl ? startOffset : endOffset;
+
+            mTopOffset = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_topBoundOffset, INVALID_DIMEN);
+            if (mTopOffset == INVALID_DIMEN) {
+                mTopOffset = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_verticalBoundOffset, mPaddingTop);
+            }
+
+            mBottomOffset = a.getDimensionPixelSize(
+                    R.styleable.FocusArea_bottomBoundOffset, INVALID_DIMEN);
+            if (mBottomOffset == INVALID_DIMEN) {
+                mBottomOffset = a.getDimensionPixelSize(
+                        R.styleable.FocusArea_verticalBoundOffset, mPaddingBottom);
+            }
+
+            mNudgeShortcutId = a.getResourceId(R.styleable.FocusArea_nudgeShortcut, View.NO_ID);
+            mNudgeShortcutDirection = a.getInt(
+                    R.styleable.FocusArea_nudgeShortcutDirection, INVALID_DIRECTION);
+            if ((mNudgeShortcutId == View.NO_ID) ^ (mNudgeShortcutDirection == INVALID_DIRECTION)) {
+                throw new IllegalStateException("nudgeShortcut and nudgeShortcutDirection must "
+                        + "be specified together");
+            }
+
+            mSpecifiedNudgeIdMap = new HashMap<>();
+            mSpecifiedNudgeIdMap.put(FOCUS_LEFT,
+                    a.getResourceId(R.styleable.FocusArea_nudgeLeft, View.NO_ID));
+            mSpecifiedNudgeIdMap.put(FOCUS_RIGHT,
+                    a.getResourceId(R.styleable.FocusArea_nudgeRight, View.NO_ID));
+            mSpecifiedNudgeIdMap.put(FOCUS_UP,
+                    a.getResourceId(R.styleable.FocusArea_nudgeUp, View.NO_ID));
+            mSpecifiedNudgeIdMap.put(FOCUS_DOWN,
+                    a.getResourceId(R.styleable.FocusArea_nudgeDown, View.NO_ID));
+        } finally {
+            a.recycle();
+        }
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        if (mDefaultFocusId != View.NO_ID) {
+            mDefaultFocusView = CarUiUtils.requireViewByRefId(this, mDefaultFocusId);
+        }
+        if (mNudgeShortcutId != View.NO_ID) {
+            mNudgeShortcutView = CarUiUtils.requireViewByRefId(this, mNudgeShortcutId);
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+        if (mRtl != rtl) {
+            mRtl = rtl;
+
+            int temp = mPaddingLeft;
+            mPaddingLeft = mPaddingRight;
+            mPaddingRight = temp;
+
+            temp = mLeftOffset;
+            mLeftOffset = mRightOffset;
+            mRightOffset = temp;
+        }
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        // To ensure the focus is initialized properly in rotary mode when there is a window focus
+        // change, this FocusArea will grab the focus from the currently focused view if one of this
+        // FocusArea's descendants is a better focus candidate than the currently focused view.
+        if (hasWindowFocus && !isInTouchMode()) {
+            maybeAdjustFocus();
+        }
+        super.onWindowFocusChanged(hasWindowFocus);
+    }
+
+    /**
+     * Focuses on another view in this FocusArea if the view is a better focus candidate than the
+     * currently focused view.
+     */
+    private boolean maybeAdjustFocus() {
+        View root = getRootView();
+        View focus = root.findFocus();
+        return ViewUtils.adjustFocus(root, focus);
+    }
+
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        switch (action) {
+            case ACTION_FOCUS:
+                // Repurpose ACTION_FOCUS to focus on its descendant. We can do this because
+                // FocusArea is not focusable and it didn't consume ACTION_FOCUS previously.
+                boolean success = focusOnDescendant();
+                if (success && mPreviousFocusArea != null) {
+                    int direction = getNudgeDirection(arguments);
+                    if (direction != INVALID_DIRECTION) {
+                        saveFocusAreaHistory(direction, mPreviousFocusArea, this,
+                                SystemClock.uptimeMillis());
+                    }
+                }
+                return success;
+            case ACTION_NUDGE_SHORTCUT:
+                return nudgeToShortcutView(arguments);
+            case ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA:
+                return nudgeToAnotherFocusArea(arguments);
+            default:
+                return super.performAccessibilityAction(action, arguments);
+        }
+    }
+
+    private boolean focusOnDescendant() {
+        if (mDefaultFocusOverridesHistory) {
+            // Check mDefaultFocus before last focused view.
+            if (focusDefaultFocusView() || focusOnLastFocusedView()) {
+                return true;
+            }
+        } else {
+            // Check last focused view before mDefaultFocus.
+            if (focusOnLastFocusedView() || focusDefaultFocusView()) {
+                return true;
+            }
+        }
+        return focusOnFirstFocusableView();
+    }
+
+    private boolean focusDefaultFocusView() {
+        return ViewUtils.adjustFocus(this, /* currentLevel= */ REGULAR_FOCUS);
+    }
+
+    /**
+     * Gets the {@code app:defaultFocus} view.
+     *
+     * @hidden
+     */
+    public View getDefaultFocusView() {
+        return mDefaultFocusView;
+    }
+
+    private boolean focusOnLastFocusedView() {
+        View lastFocusedView = mRotaryCache.getFocusedView(SystemClock.uptimeMillis());
+        return ViewUtils.requestFocus(lastFocusedView);
+    }
+
+    private boolean focusOnFirstFocusableView() {
+        return ViewUtils.adjustFocus(this, /* currentLevel= */ NO_FOCUS);
+    }
+
+    private boolean nudgeToShortcutView(Bundle arguments) {
+        if (mNudgeShortcutDirection == INVALID_DIRECTION) {
+            // No nudge shortcut configured for this FocusArea.
+            return false;
+        }
+        if (arguments == null
+                || arguments.getInt(NUDGE_DIRECTION, INVALID_DIRECTION)
+                    != mNudgeShortcutDirection) {
+            // The user is not nudging in the nudge shortcut direction.
+            return false;
+        }
+        if (mNudgeShortcutView.isFocused()) {
+            // The nudge shortcut view is already focused; return false so that the user can
+            // nudge to another FocusArea.
+            return false;
+        }
+        return ViewUtils.requestFocus(mNudgeShortcutView);
+    }
+
+    private boolean nudgeToAnotherFocusArea(Bundle arguments) {
+        int direction = getNudgeDirection(arguments);
+        long elapsedRealtime = SystemClock.uptimeMillis();
+
+        // Try to nudge to specified FocusArea, if any.
+        FocusArea targetFocusArea = getSpecifiedFocusArea(direction);
+        boolean success = targetFocusArea != null && targetFocusArea.focusOnDescendant();
+
+        // If failed, try to nudge to cached FocusArea, if any.
+        if (!success) {
+            targetFocusArea = mRotaryCache.getCachedFocusArea(direction, elapsedRealtime);
+            success = targetFocusArea != null && targetFocusArea.focusOnDescendant();
+        }
+
+        return success;
+    }
+
+    private static int getNudgeDirection(Bundle arguments) {
+        return arguments == null
+                ? INVALID_DIRECTION
+                : arguments.getInt(NUDGE_DIRECTION, INVALID_DIRECTION);
+    }
+
+    private void saveFocusAreaHistory(int direction, @NonNull FocusArea sourceFocusArea,
+            @NonNull FocusArea targetFocusArea, long elapsedRealtime) {
+        // Save one-way rather than two-way nudge history to avoid infinite nudge loop.
+        if (sourceFocusArea.mRotaryCache.getCachedFocusArea(direction, elapsedRealtime) == null) {
+            // Save reversed nudge history so that the users can nudge back to where they were.
+            int oppositeDirection = getOppositeDirection(direction);
+            targetFocusArea.mRotaryCache.saveFocusArea(oppositeDirection, sourceFocusArea,
+                    elapsedRealtime);
+        }
+    }
+
+    /** Returns the direction opposite the given {@code direction} */
+    @VisibleForTesting
+    private static int getOppositeDirection(int direction) {
+        switch (direction) {
+            case View.FOCUS_LEFT:
+                return View.FOCUS_RIGHT;
+            case View.FOCUS_RIGHT:
+                return View.FOCUS_LEFT;
+            case View.FOCUS_UP:
+                return View.FOCUS_DOWN;
+            case View.FOCUS_DOWN:
+                return View.FOCUS_UP;
+        }
+        throw new IllegalArgumentException("direction must be "
+                + "FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, or FOCUS_RIGHT.");
+    }
+
+    @Nullable
+    private FocusArea getSpecifiedFocusArea(int direction) {
+        maybeInitializeSpecifiedFocusAreas();
+        return mSpecifiedNudgeFocusAreaMap.get(direction);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        // Draw highlight on top of this FocusArea (including its background and content) but
+        // behind its children.
+        if (mEnableBackgroundHighlight && mHasFocus && !isInTouchMode()) {
+            mBackgroundHighlight.setBounds(
+                    mPaddingLeft + getScrollX(),
+                    mPaddingTop + getScrollY(),
+                    getScrollX() + getWidth() - mPaddingRight,
+                    getScrollY() + getHeight() - mPaddingBottom);
+            mBackgroundHighlight.draw(canvas);
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+
+        // Draw highlight on top of this FocusArea (including its background and content) and its
+        // children (including background, content, focus highlight, etc).
+        if (mEnableForegroundHighlight && mHasFocus && !isInTouchMode()) {
+            mForegroundHighlight.setBounds(
+                    mPaddingLeft + getScrollX(),
+                    mPaddingTop + getScrollY(),
+                    getScrollX() + getWidth() - mPaddingRight,
+                    getScrollY() + getHeight() - mPaddingBottom);
+            mForegroundHighlight.draw(canvas);
+        }
+    }
+
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return FocusArea.class.getName();
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        Bundle bundle = info.getExtras();
+        bundle.putInt(FOCUS_AREA_LEFT_BOUND_OFFSET, mLeftOffset);
+        bundle.putInt(FOCUS_AREA_RIGHT_BOUND_OFFSET, mRightOffset);
+        bundle.putInt(FOCUS_AREA_TOP_BOUND_OFFSET, mTopOffset);
+        bundle.putInt(FOCUS_AREA_BOTTOM_BOUND_OFFSET, mBottomOffset);
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        if (isInTouchMode()) {
+            return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
+        }
+        return maybeAdjustFocus();
+    }
+
+    @Override
+    public boolean restoreDefaultFocus() {
+        return maybeAdjustFocus();
+    }
+
+    private void maybeInitializeSpecifiedFocusAreas() {
+        if (mSpecifiedNudgeFocusAreaMap != null) {
+            return;
+        }
+        View root = getRootView();
+        mSpecifiedNudgeFocusAreaMap = new HashMap<>();
+        for (Integer direction : NUDGE_DIRECTIONS) {
+            int id = mSpecifiedNudgeIdMap.get(direction);
+            mSpecifiedNudgeFocusAreaMap.put(direction, root.findViewById(id));
+        }
+    }
+
+    /**
+     * Sets the padding (in pixels) of the FocusArea highlight.
+     * <p>
+     * It doesn't affect other values, such as the paddings on its child views.
+     */
+    public void setHighlightPadding(int left, int top, int right, int bottom) {
+        if (mPaddingLeft == left && mPaddingTop == top && mPaddingRight == right
+                && mPaddingBottom == bottom) {
+            return;
+        }
+        mPaddingLeft = left;
+        mPaddingTop = top;
+        mPaddingRight = right;
+        mPaddingBottom = bottom;
+        invalidate();
+    }
+
+    /**
+     * Sets the offset (in pixels) of the FocusArea's bounds.
+     * <p>
+     * It only affects the perceived bounds for the purposes of finding the nudge target. It doesn't
+     * affect the FocusArea's view bounds or highlight bounds. The offset should only be used when
+     * FocusAreas are overlapping and nudge interaction is ambiguous.
+     */
+    public void setBoundsOffset(int left, int top, int right, int bottom) {
+        mLeftOffset = left;
+        mTopOffset = top;
+        mRightOffset = right;
+        mBottomOffset = bottom;
+    }
+
+    /** Sets the default focus view in this FocusArea. */
+    public void setDefaultFocus(@NonNull View defaultFocus) {
+        mDefaultFocusView = defaultFocus;
+    }
+
+    @VisibleForTesting
+    void enableForegroundHighlight() {
+        mEnableForegroundHighlight = true;
+    }
+
+    @VisibleForTesting
+    void setDefaultFocusOverridesHistory(boolean override) {
+        mDefaultFocusOverridesHistory = override;
+    }
+
+    @VisibleForTesting
+    void setRotaryCache(@NonNull RotaryCache rotaryCache) {
+        mRotaryCache = rotaryCache;
+    }
+
+    @VisibleForTesting
+    void setClearFocusAreaHistoryWhenRotating(boolean clear) {
+        mClearFocusAreaHistoryWhenRotating = clear;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusParkingView.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusParkingView.java
new file mode 100644
index 0000000..9d5cfeb
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusParkingView.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+
+import static com.android.car.ui.utils.RotaryConstants.ACTION_HIDE_IME;
+import static com.android.car.ui.utils.RotaryConstants.ACTION_RESTORE_DEFAULT_FOCUS;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.inputmethod.InputMethodManager;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.utils.ViewUtils;
+
+/**
+ * A transparent {@link View} that can take focus. It's used by {@link
+ * com.android.car.rotary.RotaryService} to support rotary controller navigation. It's also used to
+ * initialize the focus when in rotary mode.
+ * <p>
+ * To support the rotary controller, each {@link android.view.Window} must have a FocusParkingView
+ * as the first focusable view in the view tree, and outside of all {@link FocusArea}s.
+ * <p>
+ * Android doesn't clear focus automatically when focus is set in another window. If we try to clear
+ * focus in the previous window, Android will re-focus a view in that window, resulting in two
+ * windows being focused simultaneously. Adding this view to each window can fix this issue. This
+ * view is transparent and its default focus highlight is disabled, so it's invisible to the user no
+ * matter whether it's focused or not. It can take focus so that RotaryService can "park" the focus
+ * on it to remove the focus highlight.
+ * <p>
+ * If there is only one focus area in the current window, rotating the controller within the focus
+ * area will cause RotaryService to move the focus around from the view on the right to the view on
+ * the left or vice versa. Adding this view to each window can fix this issue. When RotaryService
+ * finds out the focus target is a FocusParkingView, it will know a wrap-around is going to happen.
+ * Then it will avoid the wrap-around by not moving focus.
+ * <p>
+ * To ensure the focus is initialized properly when there is a window change, the FocusParkingView
+ * will not get focused when the framework wants to focus on it. Instead, it will try to find a
+ * better focus target in the window and focus on the target. That said, the FocusParkingView can
+ * still be focused in order to clear focus highlight in the window, such as when RotaryService
+ * performs {@link android.view.accessibility.AccessibilityNodeInfo#ACTION_FOCUS} on the
+ * FocusParkingView, or the window has lost focus.
+ */
+public class FocusParkingView extends View {
+
+    /**
+     * The focused view in the window containing this FocusParkingView. It's null if no view is
+     * focused, or the focused view is a FocusParkingView.
+     */
+    @Nullable
+    private View mFocusedView;
+
+    /** The scrollable container that contains the {@link #mFocusedView}, if any. */
+    @Nullable
+    ViewGroup mScrollableContainer;
+
+    /**
+     * Whether to restore focus when the frameworks wants to focus this view. When false, this view
+     * allows itself to be focused instead. This should be false for the {@code FocusParkingView} in
+     * an {@code ActivityView}. The default value is true.
+     */
+    private boolean mShouldRestoreFocus;
+
+    public FocusParkingView(Context context) {
+        super(context);
+        init(context, /* attrs= */ null);
+    }
+
+    public FocusParkingView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs);
+    }
+
+    public FocusParkingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs);
+    }
+
+    public FocusParkingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(context, attrs);
+    }
+
+    private void init(Context context, @Nullable AttributeSet attrs) {
+        if (attrs != null) {
+            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FocusParkingView);
+            mShouldRestoreFocus = a.getBoolean(R.styleable.FocusParkingView_shouldRestoreFocus,
+                    /* defValue= */ true);
+        }
+
+        // This view is focusable, visible and enabled so it can take focus.
+        setFocusable(View.FOCUSABLE);
+        setVisibility(VISIBLE);
+        setEnabled(true);
+
+        // This view is not clickable so it won't affect the app's behavior when the user clicks on
+        // it by accident.
+        setClickable(false);
+
+        // This view is always transparent.
+        setAlpha(0f);
+
+        // Prevent Android from drawing the default focus highlight for this view when it's focused.
+        setDefaultFocusHighlightEnabled(false);
+
+        // Keep track of the focused view so that we can recover focus when it's removed.
+        getViewTreeObserver().addOnGlobalFocusChangeListener((oldFocus, newFocus) -> {
+            mFocusedView = newFocus instanceof FocusParkingView ? null : newFocus;
+            mScrollableContainer = ViewUtils.getAncestorScrollableContainer(mFocusedView);
+        });
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // This size of the view is always 1 x 1 pixel, no matter what value is set in the layout
+        // file (match_parent, wrap_content, 100dp, 0dp, etc). Small size is to ensure it has little
+        // impact on the layout, non-zero size is to ensure it can take focus.
+        setMeasuredDimension(1, 1);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        if (!hasWindowFocus) {
+            // We need to clear the focus highlight(by parking the focus on the FocusParkingView)
+            // once the current window goes to background. This can't be done by RotaryService
+            // because RotaryService sees the window as removed, thus can't perform any action
+            // (such as focus, clear focus) on the nodes in the window. So FocusParkingView has to
+            // grab the focus proactively.
+            super.requestFocus(FOCUS_DOWN, null);
+
+            // OnGlobalFocusChangeListener won't be triggered when the window lost focus, so reset
+            // the focused view here.
+            mFocusedView = null;
+            mScrollableContainer = null;
+        } else if (isFocused()) {
+            // When FocusParkingView is focused and the window just gets focused, transfer the view
+            // focus to a non-FocusParkingView in the window.
+            restoreFocusInRoot(/* checkForTouchMode= */ true);
+        }
+        super.onWindowFocusChanged(hasWindowFocus);
+    }
+
+    @Override
+    public CharSequence getAccessibilityClassName() {
+        return FocusParkingView.class.getName();
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        switch (action) {
+            case ACTION_RESTORE_DEFAULT_FOCUS:
+                return restoreFocusInRoot(/* checkForTouchMode= */ false);
+            case ACTION_HIDE_IME:
+                InputMethodManager inputMethodManager =
+                        getContext().getSystemService(InputMethodManager.class);
+                return inputMethodManager.hideSoftInputFromWindow(getWindowToken(),
+                        /* flags= */ 0);
+            case ACTION_FOCUS:
+                // Don't leave this to View to handle as it will exit touch mode.
+                if (!hasFocus()) {
+                    return super.requestFocus(FOCUS_DOWN, null);
+                }
+                return false;
+        }
+        return super.performAccessibilityAction(action, arguments);
+    }
+
+    @Override
+    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+        if (!mShouldRestoreFocus) {
+            return super.requestFocus(direction, previouslyFocusedRect);
+        }
+        // Find a better target to focus instead of focusing this FocusParkingView when the
+        // framework wants to focus it.
+        return restoreFocusInRoot(/* checkForTouchMode= */ true);
+    }
+
+    @Override
+    public boolean restoreDefaultFocus() {
+        if (!mShouldRestoreFocus) {
+            return super.restoreDefaultFocus();
+        }
+        // Find a better target to focus instead of focusing this FocusParkingView when the
+        // framework wants to focus it.
+        return restoreFocusInRoot(/* checkForTouchMode= */ true);
+    }
+
+    /**
+     * Sets whether this view should restore focus when the framework wants to focus this view. When
+     * set to false, this view allows itself to be focused instead. This should be set to false for
+     * the {@code FocusParkingView} in an {@code ActivityView}.  The default value is true.
+     */
+    public void setShouldRestoreFocus(boolean shouldRestoreFocus) {
+        mShouldRestoreFocus = shouldRestoreFocus;
+    }
+
+    private boolean restoreFocusInRoot(boolean checkForTouchMode) {
+        // Don't do anything in touch mode if checkForTouchMode is true.
+        if (checkForTouchMode && isInTouchMode()) {
+            return false;
+        }
+        // The focused view was in a scrollable container and the Framework unfocused it because it
+        // was scrolled off the screen. In this case focus on the scrollable container so that the
+        // rotary controller can scroll the scrollable container.
+        if (maybeFocusOnScrollableContainer()) {
+            return true;
+        }
+        // Otherwise try to find the best target view to focus.
+        if (ViewUtils.adjustFocus(getRootView(), /* currentFocus= */ null)) {
+            return true;
+        }
+        // It failed to find a target view (e.g., all the views are not shown), so focus on this
+        // FocusParkingView as fallback.
+        return super.requestFocus(FOCUS_DOWN, /* previouslyFocusedRect= */ null);
+    }
+
+    private boolean maybeFocusOnScrollableContainer() {
+        // If the focused view was in a scrollable container and it was scrolled off the screen,
+        // focus on the scrollable container. When a view is scrolled off the screen, it is no
+        // longer attached to window and its parent is not null. When a view is removed, its parent
+        // is null. There is no need to focus on the scrollable container when its focused element
+        // is removed.
+        if (mFocusedView != null && !mFocusedView.isAttachedToWindow()
+                && mFocusedView.getParent() != null && mScrollableContainer != null
+                && mScrollableContainer.isAttachedToWindow() && mScrollableContainer.isShown()) {
+            RecyclerView recyclerView = mScrollableContainer instanceof RecyclerView
+                    ? (RecyclerView) mScrollableContainer
+                    : null;
+            if (mScrollableContainer.requestFocus()) {
+                if (recyclerView != null && recyclerView.isComputingLayout()) {
+                    // When a RecyclerView gains focus, it won't dispatch AccessibilityEvent if its
+                    // layout is not ready. So wait until its layout is ready then dispatch the
+                    // event.
+                    getViewTreeObserver().addOnGlobalLayoutListener(
+                            new ViewTreeObserver.OnGlobalLayoutListener() {
+                                @Override
+                                public void onGlobalLayout() {
+                                    // At this point the layout is complete and the dimensions of
+                                    // recyclerView and any child views are known.
+                                    recyclerView.sendAccessibilityEvent(TYPE_VIEW_FOCUSED);
+                                    getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                                }
+                            });
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/RotaryCache.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/RotaryCache.java
new file mode 100644
index 0000000..18f9fb0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/RotaryCache.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2020 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.car.ui;
+
+import android.os.SystemClock;
+import android.view.View;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+
+/**
+ * Cache used by {@link FocusArea} to save focus history and nudge history of the rotary controller.
+ */
+class RotaryCache {
+    /** The cache is disabled. */
+    @VisibleForTesting
+    static final int CACHE_TYPE_DISABLED = 1;
+    /** Entries in the cache will expire after a period of time. */
+    @VisibleForTesting
+    static final int CACHE_TYPE_EXPIRED_AFTER_SOME_TIME = 2;
+    /** Entries in the cache will never expire. */
+    @VisibleForTesting
+    static final int CACHE_TYPE_NEVER_EXPIRE = 3;
+
+    @IntDef(flag = true, value = {
+            CACHE_TYPE_DISABLED, CACHE_TYPE_EXPIRED_AFTER_SOME_TIME, CACHE_TYPE_NEVER_EXPIRE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CacheType {
+    }
+
+    /** Cache of focused view. */
+    @NonNull
+    private final FocusCache mFocusCache;
+
+    /** Cache of FocusAreas that were nudged to. */
+    @NonNull
+    private final FocusAreaCache mFocusAreaCache;
+
+    /** A record of when a View was focused. */
+    private static class FocusHistory {
+        /** The focused view. */
+        final View mFocusedView;
+        /** The {@link SystemClock#uptimeMillis} when this history was recorded. */
+        final long mTimestamp;
+
+        FocusHistory(@NonNull View focusedView, long timestamp) {
+            mFocusedView = focusedView;
+            mTimestamp = timestamp;
+        }
+    }
+
+    /** Cache of focused view. */
+    private static class FocusCache {
+        /** The cache type. */
+        @CacheType
+        final int mCacheType;
+        /** How many milliseconds before the entry in the cache expires. */
+        long mExpirationPeriodMs;
+        /** The record of focused view. */
+        @NonNull
+        FocusHistory mFocusHistory;
+
+        FocusCache(@CacheType int cacheType, final long expirationPeriodMs) {
+            mCacheType = cacheType;
+            mExpirationPeriodMs = expirationPeriodMs;
+            if (mCacheType == CACHE_TYPE_EXPIRED_AFTER_SOME_TIME && mExpirationPeriodMs <= 0) {
+                throw new IllegalArgumentException(
+                        "Expiration time must be positive if CacheType is "
+                                + "CACHE_TYPE_EXPIRED_AFTER_SOME_TIME");
+            }
+        }
+
+        View getFocusedView(long elapsedRealtime) {
+            return isValidHistory(elapsedRealtime) ? mFocusHistory.mFocusedView : null;
+        }
+
+        void setFocusedView(@NonNull View focusedView, long elapsedRealtime) {
+            if (mCacheType == CACHE_TYPE_DISABLED) {
+                return;
+            }
+            mFocusHistory = new FocusHistory(focusedView, elapsedRealtime);
+        }
+
+        boolean isValidHistory(long elapsedRealtime) {
+            if (mFocusHistory == null) {
+                return false;
+            }
+            switch (mCacheType) {
+                case CACHE_TYPE_NEVER_EXPIRE:
+                    return true;
+                case CACHE_TYPE_EXPIRED_AFTER_SOME_TIME:
+                    return elapsedRealtime < mFocusHistory.mTimestamp + mExpirationPeriodMs;
+                default:
+                    return false;
+            }
+        }
+    }
+
+    /** A record of a FocusArea that was nudged to. */
+    private static class FocusAreaHistory {
+        /** The FocusArea that was nudged to. */
+        @NonNull
+        final FocusArea mFocusArea;
+        /** The {@link SystemClock#uptimeMillis} when this history was recorded. */
+        final long mTimestamp;
+
+        FocusAreaHistory(@NonNull FocusArea focusArea, long timestamp) {
+            mFocusArea = focusArea;
+            mTimestamp = timestamp;
+        }
+    }
+
+    /** Cache of FocusAreas that were nudged to. */
+    private static class FocusAreaCache extends HashMap<Integer, FocusAreaHistory> {
+        /** Type of the cache. */
+        @CacheType
+        private final int mCacheType;
+        /** How many milliseconds before an entry in the cache expires. */
+        private final int mExpirationPeriodMs;
+
+        FocusAreaCache(@CacheType int cacheType, int expirationPeriodMs) {
+            mCacheType = cacheType;
+            mExpirationPeriodMs = expirationPeriodMs;
+            if (mCacheType == CACHE_TYPE_EXPIRED_AFTER_SOME_TIME && mExpirationPeriodMs <= 0) {
+                throw new IllegalArgumentException(
+                        "Expiration time must be positive if CacheType is "
+                                + "CACHE_TYPE_EXPIRED_AFTER_SOME_TIME");
+            }
+        }
+
+        void put(int direction, @NonNull FocusArea targetFocusArea, long elapsedRealtime) {
+            if (mCacheType == CACHE_TYPE_DISABLED) {
+                return;
+            }
+            put(direction, new FocusAreaHistory(targetFocusArea, elapsedRealtime));
+        }
+
+        FocusArea get(int direction, long elapsedRealtime) {
+            FocusAreaHistory history = get(direction);
+            return isValidHistory(history, elapsedRealtime) ? history.mFocusArea : null;
+        }
+
+        boolean isValidHistory(@Nullable FocusAreaHistory history, long elapsedRealtime) {
+            if (history == null) {
+                return false;
+            }
+            switch (mCacheType) {
+                case CACHE_TYPE_NEVER_EXPIRE:
+                    return true;
+                case CACHE_TYPE_EXPIRED_AFTER_SOME_TIME:
+                    return elapsedRealtime - history.mTimestamp < mExpirationPeriodMs;
+                default:
+                    return false;
+            }
+        }
+    }
+
+    RotaryCache(@CacheType int focusHistoryCacheType,
+            int focusHistoryExpirationPeriodMs,
+            @CacheType int focusAreaHistoryCacheType,
+            int focusAreaHistoryExpirationPeriodMs) {
+        mFocusCache = new FocusCache(focusHistoryCacheType, focusHistoryExpirationPeriodMs);
+        mFocusAreaCache = new FocusAreaCache(
+                focusAreaHistoryCacheType, focusAreaHistoryExpirationPeriodMs);
+    }
+
+    /**
+     * Searches the cache to find the last focused view of the FocusArea. Returns the view, or null
+     * if there is nothing in the cache, the cache is stale.
+     */
+    @Nullable
+    View getFocusedView(long elapsedRealtime) {
+        return mFocusCache.getFocusedView(elapsedRealtime);
+    }
+
+    /** Saves the focused view. */
+    void saveFocusedView(@NonNull View view, long elapsedRealtime) {
+        mFocusCache.setFocusedView(view, elapsedRealtime);
+    }
+
+    /**
+     * Searches the cache to find the target FocusArea for a nudge in a given {@code direction}.
+     * Returns the target FocusArea, or null if there is nothing in the cache, the cache is stale.
+     */
+    @Nullable
+    FocusArea getCachedFocusArea(int direction, long elapsedRealtime) {
+        return mFocusAreaCache.get(direction, elapsedRealtime);
+    }
+
+    /** Saves the FocusArea nudge history. */
+    void saveFocusArea(int direction, @NonNull FocusArea targetFocusArea, long elapsedRealtime) {
+        mFocusAreaCache.put(direction, targetFocusArea, elapsedRealtime);
+    }
+
+    /** Clears the FocusArea nudge history cache. */
+    void clearFocusAreaHistory() {
+        mFocusAreaCache.clear();
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/baselayout/ClickBlockingView.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/baselayout/ClickBlockingView.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/baselayout/ClickBlockingView.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/baselayout/ClickBlockingView.java
diff --git a/car-ui-lib/src/com/android/car/ui/baselayout/Insets.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/baselayout/Insets.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/baselayout/Insets.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/baselayout/Insets.java
diff --git a/car-ui-lib/src/com/android/car/ui/baselayout/InsetsChangedListener.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/baselayout/InsetsChangedListener.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/baselayout/InsetsChangedListener.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/baselayout/InsetsChangedListener.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/BaseLayoutController.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/BaseLayoutController.java
new file mode 100644
index 0000000..1e5a46c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/BaseLayoutController.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2020 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.car.ui.core;
+
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+
+import android.app.Activity;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.util.Pair;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.car.ui.R;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.toolbar.ToolbarController;
+import com.android.car.ui.toolbar.ToolbarControllerImpl;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * BaseLayoutController accepts an {@link Activity} and sets up the base layout inside of it.
+ * It also exposes a {@link ToolbarController} to access the toolbar. This may be null if
+ * used with a base layout without a Toolbar.
+ */
+final class BaseLayoutController {
+
+    private static final Map<Activity, BaseLayoutController> sBaseLayoutMap = new WeakHashMap<>();
+
+    private InsetsUpdater mInsetsUpdater;
+
+    /**
+     * Gets a BaseLayoutController for the given {@link Activity}. Must have called
+     * {@link #build(Activity)} with the same activity earlier, otherwise will return null.
+     */
+    @Nullable
+    /* package */ static BaseLayoutController getBaseLayout(Activity activity) {
+        return sBaseLayoutMap.get(activity);
+    }
+
+    @Nullable
+    private ToolbarController mToolbarController;
+
+    private BaseLayoutController(Activity activity) {
+        installBaseLayout(activity);
+    }
+
+    /**
+     * Create a new BaseLayoutController for the given {@link Activity}.
+     *
+     * <p>You can get a reference to it by calling {@link #getBaseLayout(Activity)}.
+     */
+    /* package */
+    static void build(Activity activity) {
+        if (getThemeBoolean(activity, R.attr.carUiBaseLayout)) {
+            sBaseLayoutMap.put(activity, new BaseLayoutController(activity));
+        }
+    }
+
+    /**
+     * Destroy the BaseLayoutController for the given {@link Activity}.
+     */
+    /* package */
+    static void destroy(Activity activity) {
+        sBaseLayoutMap.remove(activity);
+    }
+
+    /**
+     * Gets the {@link ToolbarController} for activities created with carUiBaseLayout and
+     * carUiToolbar set to true.
+     */
+    @Nullable
+    /* package */ ToolbarController getToolbarController() {
+        return mToolbarController;
+    }
+
+    /* package */ Insets getInsets() {
+        return mInsetsUpdater.getInsets();
+    }
+
+    /* package */ void dispatchNewInsets(Insets insets) {
+        mInsetsUpdater.dispatchNewInsets(insets);
+    }
+
+    /* package */ void replaceInsetsChangedListenerWith(InsetsChangedListener listener) {
+        mInsetsUpdater.replaceInsetsChangedListenerWith(listener);
+    }
+
+    /**
+     * Installs the base layout into an activity, moving its content view under the base layout.
+     *
+     * <p>This function must be called during the onCreate() of the {@link Activity}.
+     *
+     * @param activity The {@link Activity} to install a base layout in.
+     */
+    private void installBaseLayout(Activity activity) {
+        boolean toolbarEnabled = getThemeBoolean(activity, R.attr.carUiToolbar);
+        Pair<ToolbarController, InsetsUpdater> results = installBaseLayoutAround(
+                activity,
+                requireViewByRefId(activity.getWindow().getDecorView(), android.R.id.content),
+                toolbarEnabled);
+
+        mToolbarController = results.first;
+        mInsetsUpdater = results.second;
+    }
+
+    /**
+     * Installs a base layout *around* the provided contentView.
+     *
+     * @param activity May be null. Used to dispatch inset changes to, if it implements
+     *                 {@link InsetsChangedListener}
+     * @param contentView The view to install the base layout around.
+     * @param toolbarEnabled If there should be a toolbar in the base layout.
+     * @return Both the {@link ToolbarController} and {@link InsetsUpdater} for the base layout.
+     *         The InsetsUpdater will never be null. The ToolbarController will be null if
+     *         {@code toolbarEnabled} was false.
+     */
+    public static Pair<ToolbarController, InsetsUpdater> installBaseLayoutAround(
+            @Nullable Activity activity,
+            @NonNull View contentView,
+            boolean toolbarEnabled) {
+        boolean legacyToolbar = Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q;
+        @LayoutRes final int baseLayoutRes;
+
+        if (toolbarEnabled) {
+            baseLayoutRes = legacyToolbar
+                    ? R.layout.car_ui_base_layout_toolbar_legacy
+                    : R.layout.car_ui_base_layout_toolbar;
+        } else {
+            baseLayoutRes = R.layout.car_ui_base_layout;
+        }
+
+        View baseLayout = LayoutInflater.from(contentView.getContext())
+                .inflate(baseLayoutRes, null, false);
+
+        // Replace the app's content view with a base layout
+        ViewGroup contentViewParent = (ViewGroup) contentView.getParent();
+        int contentIndex = contentViewParent.indexOfChild(contentView);
+        contentViewParent.removeView(contentView);
+        contentViewParent.addView(baseLayout, contentIndex, contentView.getLayoutParams());
+
+        // Add the app's content view to the baseLayout's content view container
+        FrameLayout contentViewContainer = requireViewByRefId(baseLayout,
+                R.id.car_ui_base_layout_content_container);
+        contentViewContainer.addView(contentView, new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        ToolbarController toolbarController = null;
+        if (toolbarEnabled) {
+            if (legacyToolbar) {
+                toolbarController = requireViewByRefId(baseLayout, R.id.car_ui_toolbar);
+            } else {
+                toolbarController = new ToolbarControllerImpl(baseLayout);
+            }
+        }
+
+        InsetsUpdater insetsUpdater = new InsetsUpdater(activity, baseLayout, contentView);
+
+        return Pair.create(toolbarController, insetsUpdater);
+    }
+
+    /**
+     * Gets the boolean value of an Attribute from an {@link Activity Activity's}
+     * {@link android.content.res.Resources.Theme}.
+     */
+    private static boolean getThemeBoolean(Activity activity, int attr) {
+        TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{attr});
+
+        try {
+            return a.getBoolean(0, false);
+        } finally {
+            a.recycle();
+        }
+    }
+
+    /**
+     * InsetsUpdater waits for layout changes, and when there is one, calculates the appropriate
+     * insets into the content view.
+     *
+     * <p>It then calls {@link InsetsChangedListener#onCarUiInsetsChanged(Insets)} on the
+     * {@link Activity} and any {@link Fragment Fragments} the Activity might have. If
+     * none of the Activity/Fragments implement {@link InsetsChangedListener}, it will set
+     * padding on the content view equal to the insets.
+     */
+    static final class InsetsUpdater {
+        // These tags mark views that should overlay the content view in the base layout.
+        // OEMs should add them to views in their base layout, ie: android:tag="car_ui_left_inset"
+        // Apps will then be able to draw under these views, but will be encouraged to not put
+        // any user-interactable content there.
+        private static final String LEFT_INSET_TAG = "car_ui_left_inset";
+        private static final String RIGHT_INSET_TAG = "car_ui_right_inset";
+        private static final String TOP_INSET_TAG = "car_ui_top_inset";
+        private static final String BOTTOM_INSET_TAG = "car_ui_bottom_inset";
+
+        @Nullable
+        private final Activity mActivity;
+        private final View mContentView;
+        private final View mContentViewContainer; // Equivalent to mContentView except in Media
+        private final View mLeftInsetView;
+        private final View mRightInsetView;
+        private final View mTopInsetView;
+        private final View mBottomInsetView;
+        private InsetsChangedListener mInsetsChangedListenerDelegate;
+
+        @NonNull
+        private Insets mInsets = new Insets();
+
+        /**
+         * Constructs an InsetsUpdater that calculates and dispatches insets to an {@link Activity}.
+         *
+         * @param activity    The activity that is using base layouts. Used to dispatch insets to if
+         *                    it implements {@link InsetsChangedListener}
+         * @param baseLayout  The root view of the base layout
+         * @param contentView The android.R.id.content View
+         */
+        InsetsUpdater(
+                @Nullable Activity activity,
+                @NonNull View baseLayout,
+                @NonNull View contentView) {
+            mActivity = activity;
+            mContentView = contentView;
+            mContentViewContainer = requireViewByRefId(baseLayout,
+                    R.id.car_ui_base_layout_content_container);
+
+            mLeftInsetView = baseLayout.findViewWithTag(LEFT_INSET_TAG);
+            mRightInsetView = baseLayout.findViewWithTag(RIGHT_INSET_TAG);
+            mTopInsetView = baseLayout.findViewWithTag(TOP_INSET_TAG);
+            mBottomInsetView = baseLayout.findViewWithTag(BOTTOM_INSET_TAG);
+
+            final View.OnLayoutChangeListener layoutChangeListener =
+                    (View v, int left, int top, int right, int bottom,
+                            int oldLeft, int oldTop, int oldRight, int oldBottom) -> {
+                        if (left != oldLeft || top != oldTop
+                                || right != oldRight || bottom != oldBottom) {
+                            recalcInsets();
+                        }
+                    };
+
+            if (mLeftInsetView != null) {
+                mLeftInsetView.addOnLayoutChangeListener(layoutChangeListener);
+            }
+            if (mRightInsetView != null) {
+                mRightInsetView.addOnLayoutChangeListener(layoutChangeListener);
+            }
+            if (mTopInsetView != null) {
+                mTopInsetView.addOnLayoutChangeListener(layoutChangeListener);
+            }
+            if (mBottomInsetView != null) {
+                mBottomInsetView.addOnLayoutChangeListener(layoutChangeListener);
+            }
+            contentView.addOnLayoutChangeListener(layoutChangeListener);
+            mContentViewContainer.addOnLayoutChangeListener(layoutChangeListener);
+        }
+
+        @NonNull
+        Insets getInsets() {
+            return mInsets;
+        }
+
+        public void replaceInsetsChangedListenerWith(InsetsChangedListener listener) {
+            mInsetsChangedListenerDelegate = listener;
+        }
+
+        /**
+         * Recalculate the amount of insets we need, and then dispatch them.
+         */
+        public void recalcInsets() {
+
+            // Calculate how much each inset view overlays the content view
+
+            // These initial values are for Media Center's implementation of base layouts.
+            // They should evaluate to 0 in all other apps, because the content view and content
+            // view container have the same size and position there.
+            int top = Math.max(0,
+                    getTopOfView(mContentViewContainer) - getTopOfView(mContentView));
+            int left = Math.max(0,
+                    getLeftOfView(mContentViewContainer) - getLeftOfView(mContentView));
+            int right = Math.max(0,
+                    getRightOfView(mContentView) - getRightOfView(mContentViewContainer));
+            int bottom = Math.max(0,
+                    getBottomOfView(mContentView) - getBottomOfView(mContentViewContainer));
+            if (mTopInsetView != null) {
+                top += Math.max(0,
+                        getBottomOfView(mTopInsetView) - getTopOfView(mContentViewContainer));
+            }
+            if (mBottomInsetView != null) {
+                bottom += Math.max(0,
+                        getBottomOfView(mContentViewContainer) - getTopOfView(mBottomInsetView));
+            }
+            if (mLeftInsetView != null) {
+                left += Math.max(0,
+                        getRightOfView(mLeftInsetView) - getLeftOfView(mContentViewContainer));
+            }
+            if (mRightInsetView != null) {
+                right += Math.max(0,
+                        getRightOfView(mContentViewContainer) - getLeftOfView(mRightInsetView));
+            }
+            Insets insets = new Insets(left, top, right, bottom);
+
+            if (!insets.equals(mInsets)) {
+                mInsets = insets;
+                dispatchNewInsets(insets);
+            }
+        }
+
+        /**
+         * Dispatch the new {@link Insets} to the {@link InsetsChangedListener} IIF there is one,
+         * otherwise dispatch the new {@link Insets} to the {@link Activity} and all of its
+         * {@link Fragment Fragments}. If none of those implement {@link InsetsChangedListener},
+         * we will set the value of the insets as padding on the content view.
+         *
+         * @param insets The newly-changed insets.
+         */
+        /* package */ void dispatchNewInsets(Insets insets) {
+            mInsets = insets;
+
+            boolean handled = false;
+
+            if (mInsetsChangedListenerDelegate != null) {
+                mInsetsChangedListenerDelegate.onCarUiInsetsChanged(insets);
+                handled = true;
+            } else {
+                // If an explicit InsetsChangedListener is not provided,
+                // pass the insets to activities and fragments
+                if (mActivity instanceof InsetsChangedListener) {
+                    ((InsetsChangedListener) mActivity).onCarUiInsetsChanged(insets);
+                    handled = true;
+                }
+
+                if (mActivity instanceof FragmentActivity) {
+                    for (Fragment fragment : ((FragmentActivity) mActivity)
+                            .getSupportFragmentManager().getFragments()) {
+                        if (fragment instanceof InsetsChangedListener) {
+                            ((InsetsChangedListener) fragment).onCarUiInsetsChanged(insets);
+                            handled = true;
+                        }
+                    }
+                }
+            }
+
+            if (!handled) {
+                mContentView.setPadding(insets.getLeft(), insets.getTop(),
+                        insets.getRight(), insets.getBottom());
+            }
+        }
+
+        private static int getLeftOfView(View v) {
+            int[] position = new int[2];
+            v.getLocationOnScreen(position);
+            return position[0];
+        }
+
+        private static int getRightOfView(View v) {
+            int[] position = new int[2];
+            v.getLocationOnScreen(position);
+            return position[0] + v.getWidth();
+        }
+
+        private static int getTopOfView(View v) {
+            int[] position = new int[2];
+            v.getLocationOnScreen(position);
+            return position[1];
+        }
+
+        private static int getBottomOfView(View v) {
+            int[] position = new int[2];
+            v.getLocationOnScreen(position);
+            return position[1] + v.getHeight();
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CarUi.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CarUi.java
new file mode 100644
index 0000000..a645b98
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CarUi.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2020 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.car.ui.core;
+
+import android.app.Activity;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.util.Pair;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.BaseLayoutController.InsetsUpdater;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+/**
+ * Public interface for general CarUi static functions.
+ */
+public class CarUi {
+
+    /** Prevent instantiating this class */
+    private CarUi() {}
+
+    /**
+     * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses
+     * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true.
+     *
+     * See also: {@link #requireToolbar(Activity)}
+     */
+    @Nullable
+    public static ToolbarController getToolbar(Activity activity) {
+        BaseLayoutController controller = getBaseLayoutController(activity);
+        if (controller != null) {
+            return controller.getToolbarController();
+        }
+        return null;
+    }
+
+    /**
+     * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses
+     * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true.
+     *
+     * <p>See also: {@link #getToolbar(Activity)}
+     *
+     * @throws IllegalArgumentException When the CarUi Toolbar cannot be found.
+     */
+    @NonNull
+    public static ToolbarController requireToolbar(Activity activity) {
+        ToolbarController result = getToolbar(activity);
+        if (result == null) {
+            throw new IllegalArgumentException("Activity " + activity
+                    + " does not have a CarUi Toolbar!"
+                    + " Are you using Theme.CarUi.WithToolbar?");
+        }
+
+        return result;
+    }
+
+    /**
+     * Registering a listener to receive the InsetsChanged updates instead of the Activity.
+     */
+    public static void replaceInsetsChangedListenerWith(Activity activity,
+            InsetsChangedListener listener) {
+        BaseLayoutController controller = getBaseLayoutController(activity);
+        if (controller != null) {
+            controller.replaceInsetsChangedListenerWith(listener);
+        }
+    }
+
+    /**
+     * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities
+     * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true.
+     *
+     * <p>Note that you likely don't want to use this without also using
+     * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets
+     * will automatically be applied to your Activity's content view.
+     */
+    @Nullable
+    public static Insets getInsets(Activity activity) {
+        BaseLayoutController controller = getBaseLayoutController(activity);
+        if (controller != null) {
+            return controller.getInsets();
+        }
+        return null;
+    }
+
+    /**
+     * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities
+     * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true.
+     *
+     * <p>Note that you likely don't want to use this without also using
+     * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets
+     * will automatically be applied to your Activity's content view.
+     *
+     * @throws IllegalArgumentException When the activity is not using base layouts.
+     */
+    @NonNull
+    public static Insets requireInsets(Activity activity) {
+        Insets result = getInsets(activity);
+        if (result == null) {
+            throw new IllegalArgumentException("Activity " + activity
+                    + " does not have a base layout!"
+                    + " Are you using Theme.CarUi.WithToolbar or Theme.CarUi.NoToolbar?");
+        }
+
+        return result;
+    }
+
+    /**
+     * Most apps should not use this method, but instead rely on CarUi automatically
+     * installing the base layout into their activities. See {@link #requireToolbar(Activity)}.
+     *
+     * This method installs the base layout *around* the provided view. As a result, this view
+     * must have a parent ViewGroup.
+     *
+     * When using this method, you can't use the other activity-based methods.
+     * ({@link #requireToolbar(Activity)}, {@link #requireInsets(Activity)}, ect.)
+     *
+     * @param view The view to wrap inside a base layout.
+     * @param hasToolbar if there should be a toolbar in the base layout.
+     * @return The {@link ToolbarController}, which will be null if hasToolbar is false.
+     */
+    @Nullable
+    public static ToolbarController installBaseLayoutAround(
+            View view,
+            InsetsChangedListener insetsChangedListener,
+            boolean hasToolbar) {
+        Pair<ToolbarController, InsetsUpdater> results =
+                BaseLayoutController.installBaseLayoutAround(null, view, hasToolbar);
+
+        Objects.requireNonNull(results.second)
+                .replaceInsetsChangedListenerWith(insetsChangedListener);
+
+        return results.first;
+    }
+
+    /* package */ static BaseLayoutController getBaseLayoutController(Activity activity) {
+        if (activity.getClassLoader().equals(CarUi.class.getClassLoader())) {
+            return BaseLayoutController.getBaseLayout(activity);
+        } else {
+            // Note: (b/156532465)
+            // The usage of the alternate classloader is to accommodate GMSCore.
+            // Some activities are loaded dynamically from external modules.
+            try {
+                Class<?> baseLayoutControllerClass = activity.getClassLoader()
+                        .loadClass(BaseLayoutController.class.getName());
+                Method method = baseLayoutControllerClass
+                        .getDeclaredMethod("getBaseLayout", Activity.class);
+                return (BaseLayoutController) method.invoke(null, activity);
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CarUiInstaller.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CarUiInstaller.java
new file mode 100644
index 0000000..4693b18
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CarUiInstaller.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2020 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.car.ui.core;
+
+import static com.android.car.ui.core.CarUi.getBaseLayoutController;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.ui.baselayout.Insets;
+
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+/**
+ * {@link ContentProvider ContentProvider's} onCreate() methods are "called for all registered
+ * content providers on the application main thread at application launch time." This means we
+ * can use a content provider to register for Activity lifecycle callbacks before any activities
+ * have started, for installing the CarUi base layout into all activities.
+ */
+public class CarUiInstaller extends ContentProvider {
+
+    private static final String TAG = "CarUiInstaller";
+    private static final String CAR_UI_INSET_LEFT = "CAR_UI_INSET_LEFT";
+    private static final String CAR_UI_INSET_RIGHT = "CAR_UI_INSET_RIGHT";
+    private static final String CAR_UI_INSET_TOP = "CAR_UI_INSET_TOP";
+    private static final String CAR_UI_INSET_BOTTOM = "CAR_UI_INSET_BOTTOM";
+
+    private static final boolean IS_DEBUG_DEVICE =
+            Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
+                    || Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
+
+    @Override
+    public boolean onCreate() {
+        Context context = getContext();
+        if (context == null) {
+            Log.e(TAG, "CarUiInstaller had a null context!");
+            return false;
+        }
+        Log.i(TAG, "CarUiInstaller started for " + context.getPackageName());
+
+        Application application = (Application) context.getApplicationContext();
+        application.registerActivityLifecycleCallbacks(
+                new Application.ActivityLifecycleCallbacks() {
+                    private Insets mInsets = null;
+                    private boolean mIsActivityStartedForFirstTime = false;
+
+                    @Override
+                    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+                        if (activity.getClassLoader()
+                                .equals(CarUiInstaller.class.getClassLoader())) {
+                            BaseLayoutController.build(activity);
+                        } else {
+                            callBaseLayoutControllerMethod("build", activity);
+                        }
+
+                        if (savedInstanceState != null) {
+                            int inset_left = savedInstanceState.getInt(CAR_UI_INSET_LEFT);
+                            int inset_top = savedInstanceState.getInt(CAR_UI_INSET_TOP);
+                            int inset_right = savedInstanceState.getInt(CAR_UI_INSET_RIGHT);
+                            int inset_bottom = savedInstanceState.getInt(CAR_UI_INSET_BOTTOM);
+                            mInsets = new Insets(inset_left, inset_top, inset_right, inset_bottom);
+                        }
+
+                        mIsActivityStartedForFirstTime = true;
+                    }
+
+                    @Override
+                    public void onActivityPostStarted(Activity activity) {
+                        BaseLayoutController controller = getBaseLayoutController(activity);
+                        if (mInsets != null && controller != null
+                                && mIsActivityStartedForFirstTime) {
+                            controller.dispatchNewInsets(mInsets);
+                            mIsActivityStartedForFirstTime = false;
+                        }
+                    }
+
+                    @Override
+                    public void onActivityStarted(Activity activity) {
+                    }
+
+                    @Override
+                    public void onActivityResumed(Activity activity) {
+                    }
+
+                    @Override
+                    public void onActivityPaused(Activity activity) {
+                    }
+
+                    @Override
+                    public void onActivityStopped(Activity activity) {
+                    }
+
+                    @Override
+                    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+                        BaseLayoutController controller = getBaseLayoutController(activity);
+                        if (controller != null) {
+                            Insets insets = controller.getInsets();
+                            outState.putInt(CAR_UI_INSET_LEFT, insets.getLeft());
+                            outState.putInt(CAR_UI_INSET_TOP, insets.getTop());
+                            outState.putInt(CAR_UI_INSET_RIGHT, insets.getRight());
+                            outState.putInt(CAR_UI_INSET_BOTTOM, insets.getBottom());
+                        }
+                    }
+
+                    @Override
+                    public void onActivityDestroyed(Activity activity) {
+                        if (activity.getClassLoader()
+                                .equals(CarUiInstaller.class.getClassLoader())) {
+                            BaseLayoutController.destroy(activity);
+                        } else {
+                            callBaseLayoutControllerMethod("destroy", activity);
+                        }
+                    }
+                });
+
+        // Check only if we are in debug mode.
+        if (IS_DEBUG_DEVICE) {
+            CheckCarUiComponents checkCarUiComponents = new CheckCarUiComponents(application);
+            application.registerActivityLifecycleCallbacks(checkCarUiComponents);
+        }
+
+        return true;
+    }
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+        return null;
+    }
+
+    @Nullable
+    @Override
+    public String getType(@NonNull Uri uri) {
+        return null;
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+
+    private static void callBaseLayoutControllerMethod(String methodName, Activity activity) {
+        // Note: (b/156532465)
+        // The usage of the alternate classloader is to accommodate GMSCore.
+        // Some activities are loaded dynamically from external modules.
+        try {
+            Class<?> baseLayoutControllerClass =
+                    activity.getClassLoader()
+                            .loadClass(BaseLayoutController.class.getName());
+            Method method = baseLayoutControllerClass
+                    .getDeclaredMethod(methodName, Activity.class);
+            method.invoke(null, activity);
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CheckCarUiComponents.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CheckCarUiComponents.java
new file mode 100644
index 0000000..bd8462d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/core/CheckCarUiComponents.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2020 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.car.ui.core;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * Class used to traverse through the view hierarchy of the activity and check if carUI components
+ * are being used as expected.
+ *
+ * To check if the activity is using the CarUI components properly, navigate to the activity and
+ * run: adb shell am broadcast -a com.android.car.ui.intent.CHECK_CAR_UI_COMPONENTS. Filter
+ * the logs with "CheckCarUiComponents". This is ONLY available for debug and eng builds.
+ *
+ * Other than using the adb command you can also set a boolean resource
+ * "car_ui_escrow_check_components_automatically" to true. This will generate the logs 2 seconds
+ * after launching any activity.
+ */
+class CheckCarUiComponents implements Application.ActivityLifecycleCallbacks {
+    private static final String TAG = CheckCarUiComponents.class.getSimpleName();
+    private static final String INTENT_FILTER = "com.android.car.ui.intent.CHECK_CAR_UI_COMPONENTS";
+    private static final String NO_CAR_UI_RV = "CarUiRecyclerView not used:";
+    private static final String NO_CAR_UI_TOOLBAR = "CarUiToolbar is not used: ";
+    private static final String NO_CAR_UI_TOOLBAR_BL = "CarUiBaseLayoutToolbar is not used: ";
+    private static final String NO_CAR_UI_PREFERENCE = "CarUiPreference is not used: ";
+    private static final String NO_LIST_ITEM =
+            "CarUiListItem are not used within CarUiRecyclerView: ";
+    private View mRootView;
+    private boolean mIsScreenVisible;
+
+    private Handler mHandler = new Handler();
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            checkForComponents(context, true);
+        }
+    };
+
+    CheckCarUiComponents(Context context) {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_FILTER);
+        context.registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+    }
+
+    @Override
+    public void onActivityStarted(Activity activity) {
+    }
+
+    @Override
+    public void onActivityResumed(Activity activity) {
+    }
+
+    @Override
+    public void onActivityPostResumed(Activity activity) {
+        mRootView = activity.getWindow().getDecorView().getRootView();
+        mIsScreenVisible = true;
+        if (checkComponentsForAllActivities(activity)) {
+            // post a message after 2 seconds delay. This is an arbitrary number so that activity
+            // is ready with all its views rendered by this time.
+            mHandler.postDelayed(() -> checkForComponents(activity, false), 2000);
+        }
+    }
+
+    @Override
+    public void onActivityPaused(Activity activity) {
+        mIsScreenVisible = false;
+    }
+
+    @Override
+    public void onActivityStopped(Activity activity) {
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
+    @Override
+    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+    }
+
+    @Override
+    public void onActivityDestroyed(Activity activity) {
+        if (mRootView != null
+                && CarUiUtils.getActivity(mRootView.getContext()) == activity) {
+            mRootView = null;
+        }
+    }
+
+    private boolean checkComponentsForAllActivities(Context context) {
+        return context.getResources().getBoolean(
+                R.bool.car_ui_escrow_check_components_automatically);
+    }
+
+    private void checkForComponents(Context context, boolean showToast) {
+        if (!mIsScreenVisible) {
+            return;
+        }
+
+        CarUiComponents carUiComponents = new CarUiComponents();
+        checkForCarUiComponents(mRootView, carUiComponents);
+        if (carUiComponents.mIsUsingCarUiRecyclerView
+                && !carUiComponents.mIsCarUiRecyclerViewUsingListItem) {
+            Log.d(TAG, NO_LIST_ITEM);
+            mayShowToast(context, NO_LIST_ITEM, showToast);
+        }
+        if (carUiComponents.mIsUsingAndroidXRecyclerView) {
+            Log.d(TAG, NO_CAR_UI_RV);
+            mayShowToast(context, NO_CAR_UI_RV, showToast);
+        }
+        if (!carUiComponents.mIsUsingCarUiToolbar) {
+            Log.d(TAG, NO_CAR_UI_TOOLBAR);
+            mayShowToast(context, NO_CAR_UI_TOOLBAR, showToast);
+        }
+        if (!carUiComponents.mIsUsingCarUiBaseLayoutToolbar
+                && carUiComponents.mIsUsingCarUiToolbar) {
+            Log.d(TAG, NO_CAR_UI_TOOLBAR_BL);
+            mayShowToast(context, NO_CAR_UI_TOOLBAR_BL, showToast);
+        }
+        if (carUiComponents.mIsUsingCarUiRecyclerViewForPreference
+                && !carUiComponents.mIsUsingCarUiPreference) {
+            Log.d(TAG, NO_CAR_UI_PREFERENCE);
+            mayShowToast(context, NO_CAR_UI_PREFERENCE, showToast);
+        }
+    }
+
+    private void checkForCarUiComponents(View v, CarUiComponents carUiComponents) {
+        viewHasChildMatching(v, view -> {
+            if (isCarUiRecyclerView(view)) {
+                carUiComponents.mIsUsingCarUiRecyclerView = true;
+
+                if (viewHasChildMatching(view, CheckCarUiComponents::isCarUiPreference)) {
+                    carUiComponents.mIsUsingCarUiPreference = true;
+                    return false;
+                }
+
+                carUiComponents.mIsCarUiRecyclerViewUsingListItem = viewHasChildMatching(view,
+                        CheckCarUiComponents::isCarUiListItem);
+                return false;
+            }
+
+            if (isAndroidXRecyclerView(view)) {
+                carUiComponents.mIsUsingAndroidXRecyclerView = true;
+            }
+
+            if (isCarUiToolbar(view)) {
+                carUiComponents.mIsUsingCarUiToolbar = true;
+            }
+
+            if (isCarUiBaseLayoutToolbar(view)) {
+                carUiComponents.mIsUsingCarUiBaseLayoutToolbar = true;
+            }
+            return false;
+        });
+    }
+
+    private static boolean viewHasChildMatching(View view, Predicate<View> p) {
+        if (view == null) {
+            return false;
+        }
+        if (p.test(view)) {
+            return true;
+        }
+        if (view instanceof ViewGroup) {
+            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
+                if (viewHasChildMatching(((ViewGroup) view).getChildAt(i), p)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean isCarUiRecyclerView(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("carUiRecyclerView");
+    }
+
+    private static boolean isCarUiListItem(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("carUiListItem");
+    }
+
+    private static boolean isCarUiPreference(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("carUiPreference");
+    }
+
+    private static boolean isCarUiToolbar(View view) {
+        return view.getTag() != null && (view.getTag().toString().equals("carUiToolbar")
+                || view.getTag().toString().equals("CarUiBaseLayoutToolbar"));
+    }
+
+    private static boolean isCarUiBaseLayoutToolbar(View view) {
+        return view.getTag() != null && view.getTag().toString().equals("CarUiBaseLayoutToolbar");
+    }
+
+    private static boolean isAndroidXRecyclerView(View view) {
+        return view.getClass() == RecyclerView.class;
+    }
+
+    private static void mayShowToast(Context context, String message, boolean show) {
+        if (!show) {
+            return;
+        }
+        Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+    }
+
+    private static class CarUiComponents {
+        boolean mIsUsingCarUiRecyclerView;
+        boolean mIsUsingCarUiRecyclerViewForPreference;
+        boolean mIsCarUiRecyclerViewUsingListItem;
+        boolean mIsUsingCarUiToolbar;
+        boolean mIsUsingCarUiBaseLayoutToolbar;
+        boolean mIsUsingCarUiPreference;
+        boolean mIsUsingAndroidXRecyclerView;
+    }
+
+    /**
+     * Dump's the view hierarchy.
+     */
+    private static void printViewHierarchy(String indent, View view) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("\n ");
+        sb.append(indent);
+        sb.append('{');
+
+        if (view == null) {
+            sb.append("viewNode= NULL, ");
+            sb.append('}');
+            return;
+        }
+
+        sb.append("viewNode= ").append(view.toString()).append(", ");
+        sb.append("id= ").append(view.getId()).append(", ");
+        sb.append("name= ").append(view.getAccessibilityClassName()).append(", ");
+
+        sb.append('}');
+        System.out.println(sb.toString());
+
+        indent += "  ";
+        if (!(view instanceof ViewGroup)) {
+            return;
+        }
+        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
+            printViewHierarchy(indent, ((ViewGroup) view).getChildAt(i));
+        }
+    }
+
+    private interface Predicate<T> {
+        boolean test(T input);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiDialogFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiDialogFragment.java
new file mode 100644
index 0000000..5929e02
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiDialogFragment.java
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+import androidx.preference.DialogPreference;
+
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * Abstract base class which presents a dialog associated with a {@link
+ * androidx.preference.DialogPreference}. Since the preference object may not be available during
+ * fragment re-creation, the necessary information for displaying the dialog is read once during
+ * the initial call to {@link #onCreate(Bundle)} and saved/restored in the saved instance state.
+ * Custom subclasses should also follow this pattern.
+ *
+ * <p>Note: this is borrowed as-is from {@link androidx.preference.PreferenceDialogFragmentCompat}
+ * with updates to formatting to match the project style and the removal of the {@link
+ * DialogPreference.TargetFragment} interface requirement. See {@link PreferenceDialogFragment}
+ * for a version of this class with the check preserved. Automotive applications should use
+ * children of this fragment in order to launch the system themed platform {@link AlertDialog}
+ * instead of the one in the support library.
+ */
+
+public abstract class CarUiDialogFragment extends DialogFragment implements
+        DialogInterface.OnClickListener {
+
+    private static final String SAVE_STATE_TITLE = "CarUiDialogFragment.title";
+    private static final String SAVE_STATE_POSITIVE_TEXT = "CarUiDialogFragment.positiveText";
+    private static final String SAVE_STATE_NEGATIVE_TEXT = "CarUiDialogFragment.negativeText";
+    private static final String SAVE_STATE_MESSAGE = "CarUiDialogFragment.message";
+    private static final String SAVE_STATE_LAYOUT = "CarUiDialogFragment.layout";
+    private static final String SAVE_STATE_ICON = "CarUiDialogFragment.icon";
+
+    protected CharSequence mDialogTitle;
+    protected CharSequence mPositiveButtonText;
+    protected CharSequence mNegativeButtonText;
+    protected CharSequence mDialogMessage;
+    @LayoutRes
+    protected int mDialogLayoutRes;
+
+    protected BitmapDrawable mDialogIcon;
+
+    /** Which button was clicked. */
+    private int mWhichButtonClicked;
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (savedInstanceState != null) {
+            mDialogTitle = savedInstanceState.getCharSequence(SAVE_STATE_TITLE);
+            mPositiveButtonText = savedInstanceState.getCharSequence(SAVE_STATE_POSITIVE_TEXT);
+            mNegativeButtonText = savedInstanceState.getCharSequence(SAVE_STATE_NEGATIVE_TEXT);
+            mDialogMessage = savedInstanceState.getCharSequence(SAVE_STATE_MESSAGE);
+            mDialogLayoutRes = savedInstanceState.getInt(SAVE_STATE_LAYOUT, 0);
+            Bitmap bitmap = savedInstanceState.getParcelable(SAVE_STATE_ICON);
+            if (bitmap != null) {
+                mDialogIcon = new BitmapDrawable(getResources(), bitmap);
+            }
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(@NonNull Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putCharSequence(SAVE_STATE_TITLE, mDialogTitle);
+        outState.putCharSequence(SAVE_STATE_POSITIVE_TEXT, mPositiveButtonText);
+        outState.putCharSequence(SAVE_STATE_NEGATIVE_TEXT, mNegativeButtonText);
+        outState.putCharSequence(SAVE_STATE_MESSAGE, mDialogMessage);
+        outState.putInt(SAVE_STATE_LAYOUT, mDialogLayoutRes);
+        if (mDialogIcon != null) {
+            outState.putParcelable(SAVE_STATE_ICON, mDialogIcon.getBitmap());
+        }
+    }
+
+    @Override
+    @NonNull
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        Context context = getActivity();
+        mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(context)
+                .setTitle(mDialogTitle)
+                .setIcon(mDialogIcon)
+                .setPositiveButton(mPositiveButtonText, this)
+                .setNegativeButton(mNegativeButtonText, this);
+
+        View contentView = onCreateDialogView(context);
+        if (contentView != null) {
+            onBindDialogView(contentView);
+            builder.setView(contentView);
+        } else {
+            builder.setMessage(mDialogMessage);
+        }
+
+        onPrepareDialogBuilder(builder);
+
+        // Create the dialog
+        Dialog dialog = builder.create();
+        if (needInputMethod()) {
+            // Request input only after the dialog is shown. This is to prevent an issue where the
+            // dialog view collapsed the content on small displays.
+            dialog.setOnShowListener(d -> requestInputMethod(dialog));
+        }
+
+        return dialog;
+    }
+
+    /**
+     * Prepares the dialog builder to be shown when the preference is clicked. Use this to set
+     * custom properties on the dialog.
+     *
+     * <p>Do not {@link AlertDialog.Builder#create()} or {@link AlertDialog.Builder#show()}.
+     */
+    protected void onPrepareDialogBuilder(@NonNull AlertDialog.Builder builder) {
+    }
+
+    /**
+     * Returns whether the preference needs to display a soft input method when the dialog is
+     * displayed. Default is false. Subclasses should override this method if they need the soft
+     * input method brought up automatically.
+     *
+     * <p>Note: Ensure your subclass manually requests focus (ideally in {@link
+     * #onBindDialogView(View)}) for the input field in order to
+     * correctly attach the input method to the field.
+     */
+    protected boolean needInputMethod() {
+        return false;
+    }
+
+    /**
+     * Sets the required flags on the dialog window to enable input method window to show up.
+     */
+    private void requestInputMethod(Dialog dialog) {
+        Window window = dialog.getWindow();
+        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+    }
+
+    /**
+     * Creates the content view for the dialog (if a custom content view is required). By default,
+     * it inflates the dialog layout resource if it is set.
+     *
+     * @return the content View for the dialog.
+     * @see DialogPreference#setLayoutResource(int)
+     */
+    protected View onCreateDialogView(Context context) {
+        int resId = mDialogLayoutRes;
+        if (resId == 0) {
+            return null;
+        }
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        return inflater.inflate(resId, null);
+    }
+
+    /**
+     * Binds views in the content View of the dialog to data.
+     *
+     * <p>Make sure to call through to the superclass implementation.
+     *
+     * @param view the content View of the dialog, if it is custom.
+     */
+    @CallSuper
+    protected void onBindDialogView(@NonNull View view) {
+        View dialogMessageView = CarUiUtils.findViewByRefId(view, android.R.id.message);
+
+        if (dialogMessageView != null) {
+            CharSequence message = mDialogMessage;
+            int newVisibility = View.GONE;
+
+            if (!TextUtils.isEmpty(message)) {
+                if (dialogMessageView instanceof TextView) {
+                    ((TextView) dialogMessageView).setText(message);
+                }
+
+                newVisibility = View.VISIBLE;
+            }
+
+            if (dialogMessageView.getVisibility() != newVisibility) {
+                dialogMessageView.setVisibility(newVisibility);
+            }
+        }
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        mWhichButtonClicked = which;
+    }
+
+    @Override
+    public void onDismiss(@NonNull DialogInterface dialog) {
+        super.onDismiss(dialog);
+        onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
+    }
+
+    /**
+     * Called when the dialog is dismissed.
+     *
+     * @param positiveResult {@code true} if the dialog was dismissed with {@link
+     *                       DialogInterface#BUTTON_POSITIVE}.
+     */
+    protected abstract void onDialogClosed(boolean positiveResult);
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiDropDownPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiDropDownPreference.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/preference/CarUiDropDownPreference.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiDropDownPreference.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiEditTextPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiEditTextPreference.java
new file mode 100644
index 0000000..3882e03
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiEditTextPreference.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.EditTextPreference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * This class extends the base {@link EditTextPreference} class. Adds the drawable icon to
+ * the preference.
+ */
+public class CarUiEditTextPreference extends EditTextPreference {
+
+    private final Context mContext;
+    private boolean mShowChevron = true;
+
+    public CarUiEditTextPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mContext = context;
+    }
+
+    public CarUiEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mContext = context;
+    }
+
+    public CarUiEditTextPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+    }
+
+    public CarUiEditTextPreference(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    protected void setTwoActionLayout() {
+        setLayoutResource(R.layout.car_ui_two_action_preference);
+    }
+
+    /**
+     * Returns the widget container if {@link #setTwoActionLayout) was called, otherwise null.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    public View getWidgetActionContainer(PreferenceViewHolder holder) {
+        return CarUiUtils.findViewByRefId(holder.itemView, R.id.action_widget_container);
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+
+        boolean allowChevron = mContext.getResources().getBoolean(
+                R.bool.car_ui_preference_show_chevron);
+
+        if (!allowChevron || !mShowChevron) {
+            return;
+        }
+
+        setWidgetLayoutResource(R.layout.car_ui_preference_chevron);
+    }
+
+    public void setShowChevron(boolean showChevron) {
+        mShowChevron = showChevron;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiListPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiListPreference.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/preference/CarUiListPreference.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiListPreference.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiMultiSelectListPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiMultiSelectListPreference.java
new file mode 100644
index 0000000..bc626a0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiMultiSelectListPreference.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.preference.MultiSelectListPreference;
+
+import com.android.car.ui.R;
+
+/**
+ * This class extends the base {@link CarUiMultiSelectListPreference} class. Adds the drawable icon
+ * to the preference.
+ */
+public class CarUiMultiSelectListPreference extends MultiSelectListPreference {
+
+    private final Context mContext;
+
+    public CarUiMultiSelectListPreference(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    public CarUiMultiSelectListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+    }
+
+    public CarUiMultiSelectListPreference(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mContext = context;
+    }
+
+    public CarUiMultiSelectListPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mContext = context;
+    }
+
+    /**
+     * This is to make getSelectedItems() visible from other classes in
+     * com.android.car.ui.preference.
+     */
+    @Override
+    protected boolean[] getSelectedItems() {
+        return super.getSelectedItems();
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+
+        boolean showChevron = mContext.getResources().getBoolean(
+                R.bool.car_ui_preference_show_chevron);
+
+        if (!showChevron) {
+            return;
+        }
+
+        setWidgetLayoutResource(R.layout.car_ui_preference_chevron);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiPreference.java
new file mode 100644
index 0000000..8db5733
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiPreference.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * This class extends the base {@link Preference} class. Adds the support to add a drawable icon to
+ * the preference if there is one of fragment, intent or onPreferenceClickListener set.
+ */
+public class CarUiPreference extends Preference implements DisabledPreferenceCallback {
+
+    private Context mContext;
+    private boolean mShowChevron;
+    private String mMessageToShowWhenDisabledPreferenceClicked;
+
+    private boolean mShouldShowRippleOnDisabledPreference;
+    private Drawable mBackground;
+    private View mPreference;
+
+    public CarUiPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public CarUiPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, R.style.Preference_CarUi_Preference);
+    }
+
+    public CarUiPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.carUiPreferenceStyle);
+    }
+
+    public CarUiPreference(Context context) {
+        this(context, null);
+    }
+
+    public void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        mContext = context;
+
+        TypedArray a = getContext().obtainStyledAttributes(
+                attrs,
+                R.styleable.CarUiPreference,
+                defStyleAttr,
+                defStyleRes);
+
+        mShowChevron = a.getBoolean(R.styleable.CarUiPreference_showChevron, true);
+        mShouldShowRippleOnDisabledPreference = a.getBoolean(
+                R.styleable.CarUiPreference_showRippleOnDisabledPreference, false);
+
+        a.recycle();
+    }
+
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        boolean viewEnabled = isEnabled();
+        mPreference = holder.itemView;
+        mBackground = CarUiUtils.setPreferenceViewEnabled(viewEnabled, holder.itemView, mBackground,
+                mShouldShowRippleOnDisabledPreference);
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+
+        boolean allowChevron = mContext.getResources().getBoolean(
+                R.bool.car_ui_preference_show_chevron);
+
+        if (!allowChevron || !mShowChevron) {
+            return;
+        }
+
+        if (getOnPreferenceClickListener() != null || getIntent() != null
+                || getFragment() != null) {
+            setWidgetLayoutResource(R.layout.car_ui_preference_chevron);
+        }
+    }
+
+    /**
+     * An exact copy of {@link androidx.preference.Preference#performClick(View)}
+     * This method was added here because super.performClick(View) is not open
+     * for app usage.
+     */
+    @SuppressWarnings("RestrictTo")
+    void performClickUnrestricted(View v) {
+        performClick();
+    }
+
+    /**
+     * This is similar to {@link Preference#performClick()} with the only difference that we do not
+     * return when view is not enabled.
+     */
+    @Override
+    @SuppressWarnings("RestrictTo")
+    public void performClick() {
+        if (isEnabled()) {
+            super.performClick();
+        } else if (mMessageToShowWhenDisabledPreferenceClicked != null
+                && !mMessageToShowWhenDisabledPreferenceClicked.isEmpty()) {
+            Toast.makeText(mContext, mMessageToShowWhenDisabledPreferenceClicked,
+                    Toast.LENGTH_LONG).show();
+        }
+    }
+
+    public void setShowChevron(boolean showChevron) {
+        mShowChevron = showChevron;
+    }
+
+    /**
+     * Sets the ripple on the disabled preference.
+     */
+    @Override
+    public void setShouldShowRippleOnDisabledPreference(boolean showRipple) {
+        mShouldShowRippleOnDisabledPreference = showRipple;
+        CarUiUtils.updateRippleStateOnDisabledPreference(isEnabled(),
+                mShouldShowRippleOnDisabledPreference, mBackground, mPreference);
+    }
+
+    @Override
+    public void setMessageToShowWhenDisabledPreferenceClicked(@NonNull String message) {
+        mMessageToShowWhenDisabledPreferenceClicked = message;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiRadioButtonPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiRadioButtonPreference.java
new file mode 100644
index 0000000..f02f105
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiRadioButtonPreference.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.RadioButton;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.TwoStatePreference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/** A preference which shows a radio button at the start of the preference. */
+public class CarUiRadioButtonPreference extends TwoStatePreference {
+
+    public CarUiRadioButtonPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    public CarUiRadioButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public CarUiRadioButtonPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public CarUiRadioButtonPreference(Context context) {
+        super(context);
+        init();
+    }
+
+    private void init() {
+        setLayoutResource(R.layout.car_ui_preference);
+        setWidgetLayoutResource(R.layout.car_ui_radio_button_preference_widget);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        RadioButton radioButton = (RadioButton) CarUiUtils.findViewByRefId(holder.itemView,
+                R.id.radio_button);
+        radioButton.setChecked(isChecked());
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiSeekBarDialogPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiSeekBarDialogPreference.java
new file mode 100644
index 0000000..29e9e33
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiSeekBarDialogPreference.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2020 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.car.ui.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.DialogPreference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/** A class implements some basic methods of a seekbar dialog preference. */
+public class CarUiSeekBarDialogPreference extends DialogPreference
+        implements DialogFragmentCallbacks {
+
+    private int mSeekBarProgress;
+    private SeekBar mSeekBar;
+
+    private int mSeekBarTopTextViewVisibility;
+    private TextView mSeekBarTopTextView;
+    private String mSeekBarTopText;
+
+    private int mSeekBarLeftTextViewVisibility;
+    private TextView mSeekBarLeftTextView;
+    private String mSeekBarLeftText;
+
+    private int mSeekBarRightTextViewVisibility;
+    private TextView mSeekBarRightTextView;
+    private String mSeekBarRightText;
+
+    private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener;
+    private int mMaxProgress = 100;
+
+    public CarUiSeekBarDialogPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    public CarUiSeekBarDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public CarUiSeekBarDialogPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public CarUiSeekBarDialogPreference(Context context) {
+        super(context);
+        init();
+    }
+
+    private void init() {
+        setDialogLayoutResource(R.layout.car_ui_seekbar_dialog);
+        setPositiveButtonText(R.string.car_ui_dialog_preference_positive);
+        setNegativeButtonText(R.string.car_ui_dialog_preference_negative);
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+        mSeekBarProgress = getPersistedInt(0);
+    }
+
+    @Override
+    public void onBindDialogView(@NonNull View view) {
+        mSeekBar = CarUiUtils.findViewByRefId(view, R.id.seek_bar);
+        mSeekBarTopTextView = CarUiUtils.findViewByRefId(view, R.id.seek_bar_text_top);
+        mSeekBarLeftTextView = CarUiUtils.findViewByRefId(view, R.id.seek_bar_text_left);
+        mSeekBarRightTextView = CarUiUtils.findViewByRefId(view, R.id.seek_bar_text_right);
+
+        setProgress(mSeekBarProgress);
+
+        setSeekBarTopTextViewVisibility(mSeekBarTopTextViewVisibility);
+        setSeekBarTopTextViewText(mSeekBarTopText);
+
+        setSeekBarLeftTextViewVisibility(mSeekBarLeftTextViewVisibility);
+        setSeekBarLeftTextViewText(mSeekBarLeftText);
+
+        setSeekBarRightTextViewVisibility(mSeekBarRightTextViewVisibility);
+        setSeekBarRightTextViewText(mSeekBarRightText);
+
+        setMaxProgress(mMaxProgress);
+        setOnSeekBarChangeListener(mOnSeekBarChangeListener);
+    }
+
+    /**
+     * Get the progress bar's current level of progress. Return 0 when the progress bar is in
+     * indeterminate mode.
+     */
+    public int getProgress() {
+        if (mSeekBar != null) {
+            return mSeekBar.getProgress();
+        }
+        return mSeekBarProgress;
+    }
+
+    /**
+     * Sets the current progress to the specified value.
+     */
+    public void setProgress(int progress) {
+        if (mSeekBar != null) {
+            mSeekBar.setProgress(progress);
+        }
+        mSeekBarProgress = progress;
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+        if (positiveResult) {
+            mSeekBarProgress = mSeekBar.getProgress();
+            persistInt(mSeekBarProgress);
+            notifyChanged();
+        }
+
+        mSeekBarTopTextView = null;
+        mSeekBarRightTextView = null;
+        mSeekBarLeftTextView = null;
+        mSeekBar = null;
+    }
+
+    /**
+     * Sets the text view visibility on top of the seekbar.
+     */
+    public void setSeekBarTopTextViewVisibility(int visibility) {
+        if (mSeekBarTopTextView != null) {
+            mSeekBarTopTextView.setVisibility(visibility);
+        }
+        mSeekBarTopTextViewVisibility = visibility;
+    }
+
+    /**
+     * Gets the text on top of the seekbar.
+     */
+    @Nullable
+    public String getSeekBarTopTextViewText() {
+        if (mSeekBarTopTextView != null) {
+            return mSeekBarTopTextView.getText().toString();
+        }
+        return mSeekBarTopText;
+    }
+
+    /**
+     * Sets the text on top of the seekbar.
+     */
+    public void setSeekBarTopTextViewText(String text) {
+        if (mSeekBarTopTextView != null) {
+            mSeekBarTopTextView.setText(text);
+        }
+        mSeekBarTopText = text;
+    }
+
+    /**
+     * Sets the text view visibility on left of the seekbar.
+     */
+    public void setSeekBarLeftTextViewVisibility(int visibility) {
+        if (mSeekBarLeftTextView != null) {
+            mSeekBarLeftTextView.setVisibility(visibility);
+        }
+        mSeekBarLeftTextViewVisibility = visibility;
+    }
+
+    /**
+     * Gets the text on left of the seekbar.
+     */
+    @Nullable
+    public String getSeekBarLeftTextViewText() {
+        if (mSeekBarLeftTextView != null) {
+            return mSeekBarLeftTextView.getText().toString();
+        }
+        return mSeekBarLeftText;
+    }
+
+    /**
+     * Sets the text on Left of the seekbar.
+     */
+    public void setSeekBarLeftTextViewText(@Nullable String text) {
+        if (mSeekBarLeftTextView != null) {
+            mSeekBarLeftTextView.setText(text);
+        }
+        mSeekBarLeftText = text;
+    }
+
+
+    /**
+     * Sets the text view visibility on right of the seekbar.
+     */
+    public void setSeekBarRightTextViewVisibility(int visibility) {
+        if (mSeekBarRightTextView != null) {
+            mSeekBarRightTextView.setVisibility(visibility);
+        }
+        mSeekBarRightTextViewVisibility = visibility;
+    }
+
+    /**
+     * Gets the text on right of the seekbar.
+     */
+    @Nullable
+    public String getSeekBarRightTextViewText() {
+        if (mSeekBarRightTextView != null) {
+            return mSeekBarRightTextView.getText().toString();
+        }
+        return mSeekBarRightText;
+    }
+
+
+    /**
+     * Sets the text on right of the seekbar.
+     */
+    public void setSeekBarRightTextViewText(@Nullable String text) {
+        if (mSeekBarRightTextView != null) {
+            mSeekBarRightTextView.setText(text);
+        }
+        mSeekBarRightText = text;
+    }
+
+    /**
+     * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
+     * provides notifications of when the user starts and stops a touch gesture within the SeekBar.
+     *
+     * @param listener The seek bar notification listener
+     * @see SeekBar.OnSeekBarChangeListener
+     */
+    public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener listener) {
+        if (mSeekBar != null) {
+            mSeekBar.setOnSeekBarChangeListener(listener);
+        }
+        mOnSeekBarChangeListener = listener;
+    }
+
+    /** Get the upper range of the progress bar */
+    public int getMaxProgress() {
+        if (mSeekBar != null) {
+            return mSeekBar.getMax();
+        }
+        return mMaxProgress;
+    }
+
+    /** Set the upper range of the progress bar */
+    public void setMaxProgress(int maxProgress) {
+        if (mSeekBar != null) {
+            mSeekBar.setMax(maxProgress);
+        }
+        mMaxProgress = maxProgress;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiSwitchPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiSwitchPreference.java
new file mode 100644
index 0000000..e2b141d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiSwitchPreference.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2020 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.car.ui.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * This class extends the base {@link SwitchPreference} class. Adds the functionality to show
+ * message when preference is disabled.
+ */
+public class CarUiSwitchPreference extends SwitchPreference implements DisabledPreferenceCallback {
+
+    private String mMessageToShowWhenDisabledPreferenceClicked;
+
+    private boolean mShouldShowRippleOnDisabledPreference;
+    private Drawable mBackground;
+    private View mPreference;
+    private Context mContext;
+
+    public CarUiSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(context, attrs);
+    }
+
+    public CarUiSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs);
+    }
+
+    public CarUiSwitchPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs);
+    }
+
+    public CarUiSwitchPreference(Context context) {
+        super(context);
+        init(context, null);
+    }
+
+    private void init(Context context, AttributeSet attrs) {
+        mContext = context;
+        TypedArray preferenceAttributes = getContext().obtainStyledAttributes(attrs,
+                R.styleable.CarUiPreference);
+        mShouldShowRippleOnDisabledPreference = preferenceAttributes.getBoolean(
+                R.styleable.CarUiPreference_showRippleOnDisabledPreference, false);
+        preferenceAttributes.recycle();
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        mPreference = holder.itemView;
+        mBackground = CarUiUtils.setPreferenceViewEnabled(isEnabled(), holder.itemView, mBackground,
+                mShouldShowRippleOnDisabledPreference);
+    }
+
+    /**
+     * This is similar to {@link Preference#performClick()} with the only difference that we do not
+     * return when view is not enabled.
+     */
+    @Override
+    @SuppressWarnings("RestrictTo")
+    public void performClick() {
+        if (isEnabled()) {
+            super.performClick();
+        } else if (mMessageToShowWhenDisabledPreferenceClicked != null
+                && !mMessageToShowWhenDisabledPreferenceClicked.isEmpty()) {
+            Toast.makeText(mContext, mMessageToShowWhenDisabledPreferenceClicked,
+                    Toast.LENGTH_LONG).show();
+        }
+    }
+
+    /**
+     * Sets the ripple on the disabled preference.
+     */
+    @Override
+    public void setShouldShowRippleOnDisabledPreference(boolean showRipple) {
+        mShouldShowRippleOnDisabledPreference = showRipple;
+        CarUiUtils.updateRippleStateOnDisabledPreference(isEnabled(),
+                mShouldShowRippleOnDisabledPreference, mBackground, mPreference);
+    }
+
+    @Override
+    public void setMessageToShowWhenDisabledPreferenceClicked(@NonNull String message) {
+        mMessageToShowWhenDisabledPreferenceClicked = message;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiTwoActionPreference.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiTwoActionPreference.java
new file mode 100644
index 0000000..3b9693a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/CarUiTwoActionPreference.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 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.car.ui.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * A preference which can perform two actions. The secondary action is shown by default.
+ * {@link #showAction(boolean)} may be used to manually set the visibility of the action.
+ */
+public class CarUiTwoActionPreference extends CarUiPreference {
+
+    private boolean mIsActionShown;
+
+    public CarUiTwoActionPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init(attrs);
+    }
+
+    public CarUiTwoActionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(attrs);
+    }
+
+    public CarUiTwoActionPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs);
+    }
+
+    public CarUiTwoActionPreference(Context context) {
+        super(context);
+        init(/* attrs= */ null);
+    }
+
+    /**
+     * Sets the custom two action preference layout and attributes.
+     * Check {@link #setLayoutResource} for layout requirements.
+     */
+    private void init(AttributeSet attrs) {
+        setLayoutResource(R.layout.car_ui_two_action_preference);
+        TypedArray preferenceAttributes = getContext().obtainStyledAttributes(attrs,
+                R.styleable.CarUiTwoActionPreference);
+        mIsActionShown = preferenceAttributes.getBoolean(
+                R.styleable.CarUiTwoActionPreference_actionShown, true);
+        setShowChevron(false);
+        preferenceAttributes.recycle();
+    }
+
+    /**
+     * Sets whether the secondary action is visible in the preference.
+     *
+     * @param isShown {@code true} if the secondary action should be shown.
+     */
+    public void showAction(boolean isShown) {
+        mIsActionShown = isShown;
+        notifyChanged();
+    }
+
+    /** Returns {@code true} if action is shown. */
+    public boolean isActionShown() {
+        return mIsActionShown;
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        View containerWithoutWidget = CarUiUtils.findViewByRefId(holder.itemView,
+                R.id.car_ui_preference_container_without_widget);
+        View actionContainer = CarUiUtils.findViewByRefId(holder.itemView,
+                R.id.action_widget_container);
+        View widgetFrame = CarUiUtils.findViewByRefId(holder.itemView, android.R.id.widget_frame);
+        holder.itemView.setFocusable(!mIsActionShown);
+        containerWithoutWidget.setOnClickListener(
+                mIsActionShown ? this::performClickUnrestricted : null);
+        containerWithoutWidget.setClickable(mIsActionShown);
+        containerWithoutWidget.setFocusable(mIsActionShown);
+        actionContainer.setVisibility(mIsActionShown ? View.VISIBLE : View.GONE);
+        widgetFrame.setFocusable(mIsActionShown);
+        if (mIsActionShown) {
+            onBindWidgetFrame(widgetFrame);
+        }
+    }
+
+    /**
+     * Binds the created View for the second action.
+     *
+     * <p>This is a good place to set properties on any custom view.
+     *
+     * @param widgetFrame The widget frame which controls the 2nd action.
+     */
+    protected void onBindWidgetFrame(@NonNull View widgetFrame) {
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/DialogFragmentCallbacks.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/DialogFragmentCallbacks.java
new file mode 100644
index 0000000..ec92d9f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/DialogFragmentCallbacks.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 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.car.ui.preference;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.preference.DialogPreference;
+
+/**
+ * Interface for preferences to handle their own dialogs.
+ *
+ * A {@link androidx.preference.Preference} should implement this, and its {@link DialogPreference}
+ * will call these methods on the Preference.
+ */
+public interface DialogFragmentCallbacks extends DialogInterface.OnClickListener {
+
+    /** See {@link CarUiDialogFragment#onPrepareDialogBuilder(AlertDialog.Builder)}. */
+    default void onPrepareDialogBuilder(@NonNull AlertDialog.Builder builder) {}
+
+    @Override
+    default void onClick(@NonNull DialogInterface dialog, int which) {}
+
+    /** See {@link CarUiDialogFragment#onDialogClosed(boolean)}. */
+    default void onDialogClosed(boolean positiveResult) {}
+
+    /** See {@link CarUiDialogFragment#onBindDialogView(View)}. */
+    default void onBindDialogView(@NonNull View view) {}
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/DisabledPreferenceCallback.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/DisabledPreferenceCallback.java
new file mode 100644
index 0000000..ea3585b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/DisabledPreferenceCallback.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 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.car.ui.preference;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Interface for preferences to handle clicks when its disabled.
+ */
+public interface DisabledPreferenceCallback {
+
+    /**
+     * Sets if the ripple effect should be shown on disabled preference.
+     */
+    default void setShouldShowRippleOnDisabledPreference(boolean showRipple) {}
+
+    /**
+     * Sets the message to be displayed when the disabled preference is clicked.
+     */
+    default void setMessageToShowWhenDisabledPreferenceClicked(@NonNull String message) {}
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java
new file mode 100644
index 0000000..c40ba48
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.app.AlertDialog;
+import android.os.Bundle;
+import android.text.InputType;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.preference.EditTextPreference;
+
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * Presents a dialog with an {@link EditText} associated with an {@link EditTextPreference}.
+ *
+ * <p>Note: this is borrowed as-is from androidx.preference.EditTextPreferenceDialogFragmentCompat
+ * with updates to formatting to match the project style. Automotive applications should use this
+ * implementations in order to launch the system themed platform {@link AlertDialog} instead of the
+ * one in the support library.
+ */
+public class EditTextPreferenceDialogFragment extends PreferenceDialogFragment implements
+        TextView.OnEditorActionListener {
+
+    private static final String SAVE_STATE_TEXT = "EditTextPreferenceDialogFragment.text";
+
+    private EditText mEditText;
+    private CharSequence mText;
+    private boolean mAllowEnterToSubmit = true;
+
+    /**
+     * Returns a new instance of {@link EditTextPreferenceDialogFragment} for the {@link
+     * EditTextPreference} with the given {@code key}.
+     */
+    @NonNull
+    public static EditTextPreferenceDialogFragment newInstance(String key) {
+        EditTextPreferenceDialogFragment fragment =
+                new EditTextPreferenceDialogFragment();
+        Bundle b = new Bundle(/* capacity= */ 1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (savedInstanceState == null) {
+            mText = getEditTextPreference().getText();
+        } else {
+            mText = savedInstanceState.getCharSequence(SAVE_STATE_TEXT);
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(@NonNull Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putCharSequence(SAVE_STATE_TEXT, mText);
+    }
+
+    @Override
+    protected void onBindDialogView(@NonNull View view) {
+        super.onBindDialogView(view);
+
+        mEditText = CarUiUtils.findViewByRefId(view, android.R.id.edit);
+
+        if (mEditText == null) {
+            throw new IllegalStateException(
+                    "Dialog view must contain an EditText with id @android:id/edit");
+        }
+
+        mEditText.requestFocus();
+        mEditText.setText(mText);
+        mEditText.setInputType(InputType.TYPE_CLASS_TEXT);
+        mEditText.setImeOptions(EditorInfo.IME_ACTION_DONE);
+        mEditText.setOnEditorActionListener(this);
+
+        // Place cursor at the end
+        mEditText.setSelection(mEditText.getText().length());
+    }
+
+    private EditTextPreference getEditTextPreference() {
+        return (EditTextPreference) getPreference();
+    }
+
+    @Override
+    protected boolean needInputMethod() {
+        return true;
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        if (positiveResult) {
+            String value = mEditText.getText().toString();
+            if (getEditTextPreference().callChangeListener(value)) {
+                getEditTextPreference().setText(value);
+            }
+        }
+    }
+
+    /** Allows enabling and disabling the ability to press enter to dismiss the dialog. */
+    public void setAllowEnterToSubmit(boolean isAllowed) {
+        mAllowEnterToSubmit = isAllowed;
+    }
+
+    /** Allows verifying if enter to submit is currently enabled. */
+    public boolean getAllowEnterToSubmit() {
+        return mAllowEnterToSubmit;
+    }
+
+    @Override
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        if (actionId == EditorInfo.IME_ACTION_DONE && mAllowEnterToSubmit) {
+            CharSequence newValue = v.getText();
+
+            getEditTextPreference().callChangeListener(newValue);
+            dismiss();
+
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/ListPreferenceFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/ListPreferenceFragment.java
new file mode 100644
index 0000000..2f63fbf
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/ListPreferenceFragment.java
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import static com.android.car.ui.preference.PreferenceDialogFragment.ARG_KEY;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.preference.DialogPreference;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+import com.android.car.ui.utils.CarUiUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A fragment that provides a layout with a list of options associated with a {@link
+ * ListPreference}.
+ */
+public class ListPreferenceFragment extends Fragment implements InsetsChangedListener {
+
+    private static final String ARG_FULLSCREEN = "fullscreen";
+
+    private ListPreference mPreference;
+    private CarUiContentListItem mSelectedItem;
+    private int mSelectedIndex = -1;
+    private boolean mFullScreen;
+
+    /**
+     * Returns a new instance of {@link ListPreferenceFragment} for the {@link ListPreference} with
+     * the given {@code key}.
+     */
+    @NonNull
+    static ListPreferenceFragment newInstance(String key, boolean fullScreen) {
+        ListPreferenceFragment fragment = new ListPreferenceFragment();
+        Bundle b = new Bundle(/* capacity= */ 1);
+        b.putString(ARG_KEY, key);
+        b.putBoolean(ARG_FULLSCREEN, fullScreen);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(
+            @NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+            @Nullable Bundle savedInstanceState) {
+        if (CarUi.getToolbar(getActivity()) == null) {
+            return inflater.inflate(R.layout.car_ui_list_preference_with_toolbar, container, false);
+        } else {
+            return inflater.inflate(R.layout.car_ui_list_preference, container, false);
+        }
+    }
+
+    @Override
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        final CarUiRecyclerView carUiRecyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
+        mFullScreen = requireArguments().getBoolean(ARG_FULLSCREEN, true);
+        ToolbarController toolbar = mFullScreen ? CarUi.getToolbar(getActivity()) : null;
+
+        // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
+        if (toolbar == null) {
+            Toolbar toolbarView = CarUiUtils.findViewByRefId(view, R.id.toolbar);
+            toolbar = toolbarView;
+
+            if (toolbarView != null) {
+                carUiRecyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
+                toolbarView.registerToolbarHeightChangeListener(newHeight -> {
+                    if (carUiRecyclerView.getPaddingTop() == newHeight) {
+                        return;
+                    }
+
+                    int oldHeight = carUiRecyclerView.getPaddingTop();
+                    carUiRecyclerView.setPadding(0, newHeight, 0, 0);
+                    carUiRecyclerView.scrollBy(0, oldHeight - newHeight);
+                });
+            }
+        }
+
+        carUiRecyclerView.setClipToPadding(false);
+        mPreference = getListPreference();
+        if (toolbar != null) {
+            toolbar.setTitle(mPreference.getTitle());
+            toolbar.setState(Toolbar.State.SUBPAGE);
+        }
+
+        CharSequence[] entries = mPreference.getEntries();
+        CharSequence[] entryValues = mPreference.getEntryValues();
+
+        if (entries == null || entryValues == null) {
+            throw new IllegalStateException(
+                    "ListPreference requires an entries array and an entryValues array.");
+        }
+
+        if (entries.length != entryValues.length) {
+            throw new IllegalStateException(
+                    "ListPreference entries array length does not match entryValues array length.");
+        }
+
+        mSelectedIndex = mPreference.findIndexOfValue(mPreference.getValue());
+        List<CarUiListItem> listItems = new ArrayList<>();
+        CarUiListItemAdapter adapter = new CarUiListItemAdapter(listItems);
+
+        for (int i = 0; i < entries.length; i++) {
+            String entry = entries[i].toString();
+            CarUiContentListItem item = new CarUiContentListItem(
+                    CarUiContentListItem.Action.RADIO_BUTTON);
+            item.setTitle(entry);
+
+            if (i == mSelectedIndex) {
+                item.setChecked(true);
+                mSelectedItem = item;
+            }
+
+            item.setOnCheckedChangeListener((listItem, isChecked) -> {
+                if (mSelectedItem != null) {
+                    mSelectedItem.setChecked(false);
+                    adapter.notifyItemChanged(listItems.indexOf(mSelectedItem));
+                }
+                mSelectedItem = listItem;
+                mSelectedIndex = listItems.indexOf(mSelectedItem);
+            });
+
+            listItems.add(item);
+        }
+
+        carUiRecyclerView.setAdapter(adapter);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        Insets insets = CarUi.getInsets(getActivity());
+        if (insets != null) {
+            onCarUiInsetsChanged(insets);
+        }
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        updatePreference();
+    }
+
+    private void updatePreference() {
+        if (mSelectedIndex >= 0 && mPreference != null) {
+            String entryValue = mPreference.getEntryValues()[mSelectedIndex].toString();
+
+            if (mPreference.callChangeListener(entryValue)) {
+                mPreference.setValue(entryValue);
+            }
+        }
+    }
+
+    private ListPreference getListPreference() {
+        String key = requireArguments().getString(ARG_KEY);
+        DialogPreference.TargetFragment fragment =
+                (DialogPreference.TargetFragment) getTargetFragment();
+
+        if (key == null) {
+            throw new IllegalStateException(
+                    "ListPreference key not found in Fragment arguments");
+        }
+
+        if (fragment == null) {
+            throw new IllegalStateException(
+                    "Target fragment must be registered before displaying ListPreference "
+                            + "screen.");
+        }
+
+        Preference preference = fragment.findPreference(key);
+
+        if (!(preference instanceof ListPreference)) {
+            throw new IllegalStateException(
+                    "Cannot use ListPreferenceFragment with a preference that is not of type "
+                            + "ListPreference");
+        }
+
+        return (ListPreference) preference;
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        if (!mFullScreen) {
+            return;
+        }
+        View view = requireView();
+        CarUiUtils.requireViewByRefId(view, R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        view.setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
new file mode 100644
index 0000000..b1b8a28
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import static com.android.car.ui.preference.PreferenceDialogFragment.ARG_KEY;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.preference.DialogPreference;
+import androidx.preference.Preference;
+
+import com.android.car.ui.R;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+import com.android.car.ui.utils.CarUiUtils;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A fragment that provides a layout with a list of options associated with a {@link
+ * CarUiMultiSelectListPreference}.
+ */
+public class MultiSelectListPreferenceFragment extends Fragment implements InsetsChangedListener {
+
+    private static final String ARG_FULLSCREEN = "fullscreen";
+
+    private CarUiMultiSelectListPreference mPreference;
+    private Set<String> mNewValues;
+    private ToolbarController mToolbar;
+    private boolean mFullScreen;
+
+    /**
+     * Returns a new instance of {@link MultiSelectListPreferenceFragment} for the {@link
+     * CarUiMultiSelectListPreference} with the given {@code key}.
+     */
+    @NonNull
+    static MultiSelectListPreferenceFragment newInstance(String key, boolean fullScreen) {
+        MultiSelectListPreferenceFragment fragment = new MultiSelectListPreferenceFragment();
+        Bundle b = new Bundle(/* capacity= */ 1);
+        b.putString(ARG_KEY, key);
+        b.putBoolean(ARG_FULLSCREEN, fullScreen);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(
+            @NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+            @Nullable Bundle savedInstanceState) {
+        if (CarUi.getToolbar(getActivity()) == null) {
+            return inflater.inflate(R.layout.car_ui_list_preference_with_toolbar, container, false);
+        } else {
+            return inflater.inflate(R.layout.car_ui_list_preference, container, false);
+        }
+    }
+
+    @Override
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        final CarUiRecyclerView recyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
+        mFullScreen = requireArguments().getBoolean(ARG_FULLSCREEN, true);
+        mToolbar = mFullScreen ? CarUi.getToolbar(requireActivity()) : null;
+
+        // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
+        if (mToolbar == null) {
+            Toolbar toolbarView = CarUiUtils.findViewByRefId(view, R.id.toolbar);
+            mToolbar = toolbarView;
+
+            if (toolbarView != null) {
+                recyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
+                toolbarView.registerToolbarHeightChangeListener(newHeight -> {
+                    if (recyclerView.getPaddingTop() == newHeight) {
+                        return;
+                    }
+
+                    int oldHeight = recyclerView.getPaddingTop();
+                    recyclerView.setPadding(0, newHeight, 0, 0);
+                    recyclerView.scrollBy(0, oldHeight - newHeight);
+                });
+            }
+        }
+
+        mPreference = getPreference();
+
+        recyclerView.setClipToPadding(false);
+        if (mToolbar != null) {
+            mToolbar.setTitle(mPreference.getTitle());
+            mToolbar.setState(Toolbar.State.SUBPAGE);
+        }
+
+        mNewValues = new HashSet<>(mPreference.getValues());
+        CharSequence[] entries = mPreference.getEntries();
+        CharSequence[] entryValues = mPreference.getEntryValues();
+
+        if (entries == null || entryValues == null) {
+            throw new IllegalStateException(
+                    "MultiSelectListPreference requires an entries array and an entryValues array"
+                            + ".");
+        }
+
+        if (entries.length != entryValues.length) {
+            throw new IllegalStateException(
+                    "MultiSelectListPreference entries array length does not match entryValues "
+                            + "array length.");
+        }
+
+        List<CarUiListItem> listItems = new ArrayList<>();
+        boolean[] selectedItems = mPreference.getSelectedItems();
+
+        for (int i = 0; i < entries.length; i++) {
+            String entry = entries[i].toString();
+            String entryValue = entryValues[i].toString();
+            CarUiContentListItem item = new CarUiContentListItem(
+                    CarUiContentListItem.Action.CHECK_BOX);
+            item.setTitle(entry);
+            item.setChecked(selectedItems[i]);
+            item.setOnCheckedChangeListener((listItem, isChecked) -> {
+                if (isChecked) {
+                    mNewValues.add(entryValue);
+                } else {
+                    mNewValues.remove(entryValue);
+                }
+            });
+
+            listItems.add(item);
+        }
+
+        CarUiListItemAdapter adapter = new CarUiListItemAdapter(listItems);
+        recyclerView.setAdapter(adapter);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        Insets insets = CarUi.getInsets(getActivity());
+        if (insets != null) {
+            onCarUiInsetsChanged(insets);
+        }
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        updatePreference();
+    }
+
+    private void updatePreference() {
+        if (mPreference.callChangeListener(mNewValues)) {
+            mPreference.setValues(mNewValues);
+        }
+    }
+
+    private CarUiMultiSelectListPreference getPreference() {
+        if (getArguments() == null) {
+            throw new IllegalStateException("Preference arguments cannot be null");
+        }
+
+        String key = getArguments().getString(ARG_KEY);
+        DialogPreference.TargetFragment fragment =
+                (DialogPreference.TargetFragment) getTargetFragment();
+
+        if (key == null) {
+            throw new IllegalStateException(
+                    "MultiSelectListPreference key not found in Fragment arguments");
+        }
+
+        if (fragment == null) {
+            throw new IllegalStateException(
+                    "Target fragment must be registered before displaying "
+                            + "MultiSelectListPreference screen.");
+        }
+
+        Preference preference = fragment.findPreference(key);
+
+        if (!(preference instanceof CarUiMultiSelectListPreference)) {
+            throw new IllegalStateException(
+                    "Cannot use MultiSelectListPreferenceFragment with a preference that is "
+                            + "not of type CarUiMultiSelectListPreference");
+        }
+
+        return (CarUiMultiSelectListPreference) preference;
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        if (!mFullScreen) {
+            return;
+        }
+        View view = requireView();
+        CarUiUtils.requireViewByRefId(view, R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        view.setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceDialogFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceDialogFragment.java
new file mode 100644
index 0000000..bd2a113
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceDialogFragment.java
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.preference.DialogPreference;
+import androidx.preference.PreferenceFragmentCompat;
+
+/**
+ * Abstract base class which presents a dialog associated with a {@link
+ * androidx.preference.DialogPreference}. Since the preference object may not be available during
+ * fragment re-creation, the necessary information for displaying the dialog is read once during
+ * the initial call to {@link #onCreate(Bundle)} and saved/restored in the saved instance state.
+ * Custom subclasses should also follow this pattern.
+ *
+ * <p>Note: this has the same functionality and interface as {@link
+ * androidx.preference.PreferenceDialogFragmentCompat} with updates to formatting to match the
+ * project style. This class preserves the {@link DialogPreference.TargetFragment} interface
+ * requirement that was removed in {@link CarUiDialogFragment}. Automotive applications should use
+ * children of this fragment in order to launch the system themed platform {@link AlertDialog}
+ * instead of the one in the support library.
+ */
+public abstract class PreferenceDialogFragment extends CarUiDialogFragment implements
+        DialogInterface.OnClickListener {
+
+    protected static final String ARG_KEY = "key";
+
+    private DialogPreference mPreference;
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Fragment rawFragment = getTargetFragment();
+        if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
+            throw new IllegalStateException(
+                    "Target fragment must implement TargetFragment interface");
+        }
+
+        DialogPreference.TargetFragment fragment =
+                (DialogPreference.TargetFragment) rawFragment;
+
+        String key = getArguments().getString(ARG_KEY);
+        if (savedInstanceState == null) {
+            mPreference = (DialogPreference) fragment.findPreference(key);
+            mDialogTitle = mPreference.getDialogTitle();
+            mPositiveButtonText = mPreference.getPositiveButtonText();
+            mNegativeButtonText = mPreference.getNegativeButtonText();
+            mDialogMessage = mPreference.getDialogMessage();
+            mDialogLayoutRes = mPreference.getDialogLayoutResource();
+
+            Drawable icon = mPreference.getDialogIcon();
+            if (icon == null || icon instanceof BitmapDrawable) {
+                mDialogIcon = (BitmapDrawable) icon;
+            } else {
+                Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(),
+                        icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+                Canvas canvas = new Canvas(bitmap);
+                icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+                icon.draw(canvas);
+                mDialogIcon = new BitmapDrawable(getResources(), bitmap);
+            }
+        }
+    }
+
+    /**
+     * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has
+     * been called on the {@link PreferenceFragmentCompat} which launched this dialog.
+     *
+     * @return the {@link DialogPreference} associated with this dialog.
+     */
+    public DialogPreference getPreference() {
+        if (mPreference == null) {
+            String key = getArguments().getString(ARG_KEY);
+            DialogPreference.TargetFragment fragment =
+                    (DialogPreference.TargetFragment) getTargetFragment();
+            mPreference = (DialogPreference) fragment.findPreference(key);
+        }
+        return mPreference;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceFragment.java
new file mode 100644
index 0000000..3f5b5cb
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceFragment.java
@@ -0,0 +1,410 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.preference;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.Pair;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+import androidx.preference.DialogPreference;
+import androidx.preference.DropDownPreference;
+import androidx.preference.EditTextPreference;
+import androidx.preference.ListPreference;
+import androidx.preference.MultiSelectListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+import androidx.preference.TwoStatePreference;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.FocusArea;
+import com.android.car.ui.R;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+import com.android.car.ui.utils.CarUiUtils;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A PreferenceFragmentCompat is the entry point to using the Preference library.
+ *
+ * <p>Using this fragment will replace regular Preferences with CarUi equivalents. Because of this,
+ * certain properties that cannot be read out of Preferences will be lost upon calling
+ * {@link #setPreferenceScreen(PreferenceScreen)}. These include the preference viewId,
+ * defaultValue, and enabled state.
+ */
+public abstract class PreferenceFragment extends PreferenceFragmentCompat implements
+        InsetsChangedListener {
+
+    private static final String TAG = "CarUiPreferenceFragment";
+    private static final String DIALOG_FRAGMENT_TAG =
+            "com.android.car.ui.PreferenceFragment.DIALOG";
+
+    /**
+     * This method can be overridden to indicate whether or not this fragment covers the
+     * whole screen. When it returns false, the preference fragment will not attempt to change
+     * the CarUi base layout toolbar (but will still have its own toolbar and change it when using
+     * non-baselayout toolbars), and will also not take into account CarUi insets.
+     *
+     * @return Whether to PreferenceFragment takes up the whole app's space. Defaults to true.
+     */
+    protected boolean isFullScreenFragment() {
+        return true;
+    }
+
+    @Override
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        if (isFullScreenFragment()) {
+            ToolbarController baseLayoutToolbar = CarUi.getToolbar(getActivity());
+            if (baseLayoutToolbar != null) {
+                baseLayoutToolbar.setState(Toolbar.State.SUBPAGE);
+                if (getPreferenceScreen() != null) {
+                    baseLayoutToolbar.setTitle(getPreferenceScreen().getTitle());
+                }
+            }
+        }
+
+        // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
+        final RecyclerView recyclerView = CarUiUtils.findViewByRefId(view, R.id.recycler_view);
+        final Toolbar toolbar = CarUiUtils.findViewByRefId(view, R.id.toolbar);
+        if (recyclerView == null || toolbar == null) {
+            return;
+        }
+
+        recyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
+        toolbar.registerToolbarHeightChangeListener(newHeight -> {
+            if (recyclerView.getPaddingTop() == newHeight) {
+                return;
+            }
+
+            int oldHeight = recyclerView.getPaddingTop();
+            recyclerView.setPadding(0, newHeight, 0, 0);
+            recyclerView.scrollBy(0, oldHeight - newHeight);
+
+            FocusArea focusArea = CarUiUtils.requireViewByRefId(view, R.id.car_ui_focus_area);
+            focusArea.setHighlightPadding(0, newHeight, 0, 0);
+            focusArea.setBoundsOffset(0, newHeight, 0, 0);
+        });
+
+        recyclerView.setClipToPadding(false);
+        if (getPreferenceScreen() != null) {
+            toolbar.setTitle(getPreferenceScreen().getTitle());
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        Insets insets = CarUi.getInsets(getActivity());
+        if (insets != null) {
+            onCarUiInsetsChanged(insets);
+        }
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        if (!isFullScreenFragment()) {
+            return;
+        }
+
+        View view = requireView();
+        FocusArea focusArea = CarUiUtils.requireViewByRefId(view, R.id.car_ui_focus_area);
+        focusArea.setHighlightPadding(0, insets.getTop(), 0, insets.getBottom());
+        focusArea.setBoundsOffset(0, insets.getTop(), 0, insets.getBottom());
+        CarUiUtils.requireViewByRefId(view, R.id.recycler_view)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        view.setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+
+    /**
+     * Called when a preference in the tree requests to display a dialog. Subclasses should override
+     * this method to display custom dialogs or to handle dialogs for custom preference classes.
+     *
+     * <p>Note: this is borrowed as-is from androidx.preference.PreferenceFragmentCompat with
+     * updates to launch Car UI library {@link DialogFragment} instead of the ones in the
+     * support library.
+     *
+     * @param preference The {@link Preference} object requesting the dialog
+     */
+    @Override
+    public void onDisplayPreferenceDialog(Preference preference) {
+
+        if (getActivity() instanceof OnPreferenceDisplayDialogCallback
+                && ((OnPreferenceDisplayDialogCallback) getActivity())
+                .onPreferenceDisplayDialog(this, preference)) {
+            return;
+        }
+
+        // check if dialog is already showing
+        if (requireFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
+            return;
+        }
+
+        final Fragment f;
+        if (preference instanceof EditTextPreference) {
+            f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
+        } else if (preference instanceof ListPreference) {
+            f = ListPreferenceFragment.newInstance(preference.getKey(), isFullScreenFragment());
+        } else if (preference instanceof MultiSelectListPreference) {
+            f = MultiSelectListPreferenceFragment
+                    .newInstance(preference.getKey(), isFullScreenFragment());
+        } else if (preference instanceof CarUiSeekBarDialogPreference) {
+            f = SeekbarPreferenceDialogFragment.newInstance(preference.getKey());
+        } else {
+            throw new IllegalArgumentException(
+                    "Cannot display dialog for an unknown Preference type: "
+                            + preference.getClass().getSimpleName()
+                            + ". Make sure to implement onPreferenceDisplayDialog() to handle "
+                            + "displaying a custom dialog for this Preference.");
+        }
+
+        f.setTargetFragment(this, 0);
+
+        if (f instanceof DialogFragment) {
+            ((DialogFragment) f).show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
+        } else {
+            if (getActivity() == null) {
+                throw new IllegalStateException(
+                        "Preference fragment is not attached to an Activity.");
+            }
+
+            if (getView() == null) {
+                throw new IllegalStateException(
+                        "Preference fragment must have a layout.");
+            }
+
+            Context context = getContext();
+            getActivity().getSupportFragmentManager().beginTransaction()
+                    .setCustomAnimations(
+                            CarUiUtils.getAttrResourceId(context,
+                                    android.R.attr.fragmentOpenEnterAnimation),
+                            CarUiUtils.getAttrResourceId(context,
+                                    android.R.attr.fragmentOpenExitAnimation),
+                            CarUiUtils.getAttrResourceId(context,
+                                    android.R.attr.fragmentCloseEnterAnimation),
+                            CarUiUtils.getAttrResourceId(context,
+                                    android.R.attr.fragmentCloseExitAnimation))
+                    .replace(((ViewGroup) getView().getParent()).getId(), f)
+                    .addToBackStack(null)
+                    .commit();
+        }
+    }
+
+    /**
+     * This override of setPreferenceScreen replaces preferences with their CarUi versions first.
+     */
+    @Override
+    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+        // We do a search of the tree and every time we see a PreferenceGroup we remove
+        // all it's children, replace them with CarUi versions, and then re-add them
+
+        Map<Preference, String> dependencies = new HashMap<>();
+        List<Preference> children = new ArrayList<>();
+
+        // Stack of preferences to process
+        Deque<Preference> stack = new ArrayDeque<>();
+        stack.addFirst(preferenceScreen);
+
+        while (!stack.isEmpty()) {
+            Preference preference = stack.removeFirst();
+
+            if (preference instanceof PreferenceGroup) {
+                PreferenceGroup pg = (PreferenceGroup) preference;
+
+                children.clear();
+                for (int i = 0; i < pg.getPreferenceCount(); i++) {
+                    children.add(pg.getPreference(i));
+                }
+
+                pg.removeAll();
+
+                for (Preference child : children) {
+                    Preference replacement = getReplacementFor(child);
+
+                    dependencies.put(replacement, child.getDependency());
+                    pg.addPreference(replacement);
+                    stack.addFirst(replacement);
+                }
+            }
+        }
+
+        super.setPreferenceScreen(preferenceScreen);
+
+        // Set the dependencies after all the swapping has been done and they've been
+        // associated with this fragment, or we could potentially fail to find preferences
+        // or use the wrong preferenceManager
+        for (Map.Entry<Preference, String> entry : dependencies.entrySet()) {
+            entry.getKey().setDependency(entry.getValue());
+        }
+    }
+
+    // Mapping from regular preferences to CarUi preferences.
+    // Order is important, subclasses must come before their base classes
+    private static final List<Pair<Class<? extends Preference>, Class<? extends Preference>>>
+            sPreferenceMapping = Arrays.asList(
+            new Pair<>(DropDownPreference.class, CarUiDropDownPreference.class),
+            new Pair<>(ListPreference.class, CarUiListPreference.class),
+            new Pair<>(MultiSelectListPreference.class, CarUiMultiSelectListPreference.class),
+            new Pair<>(EditTextPreference.class, CarUiEditTextPreference.class),
+            new Pair<>(SwitchPreference.class, CarUiSwitchPreference.class),
+            new Pair<>(Preference.class, CarUiPreference.class)
+    );
+
+    /**
+     * Gets the CarUi version of the passed in preference. If there is no suitable replacement, this
+     * method will return it's input.
+     *
+     * <p>When given a Preference that extends a replaceable preference, we log a warning instead
+     * of replacing it so that we don't remove any functionality.
+     */
+    private static Preference getReplacementFor(Preference preference) {
+        Class<? extends Preference> clazz = preference.getClass();
+
+        for (Pair<Class<? extends Preference>, Class<? extends Preference>> replacement
+                : sPreferenceMapping) {
+            Class<? extends Preference> source = replacement.first;
+            Class<? extends Preference> target = replacement.second;
+            if (source.isAssignableFrom(clazz)) {
+                if (clazz == source) {
+                    try {
+                        return copyPreference(preference, (Preference) target
+                                .getDeclaredConstructor(Context.class)
+                                .newInstance(preference.getContext()));
+                    } catch (ReflectiveOperationException e) {
+                        throw new RuntimeException(e);
+                    }
+                } else if (clazz == target || source == Preference.class) {
+                    // Don't warn about subclasses of Preference because there are many legitimate
+                    // uses for non-carui Preference subclasses, like Preference groups.
+                    return preference;
+                } else {
+                    Log.w(TAG, "Subclass of " + source.getSimpleName() + " was used, "
+                            + "preventing us from substituting it with " + target.getSimpleName());
+                    return preference;
+                }
+            }
+        }
+
+        return preference;
+    }
+
+    /**
+     * Copies all the properties of one preference to another.
+     *
+     * @return the {@code to} parameter
+     */
+    private static Preference copyPreference(Preference from, Preference to) {
+        // viewId and defaultValue don't have getters
+        // isEnabled() is not completely symmetrical with setEnabled(), so we can't use it.
+        to.setTitle(from.getTitle());
+        to.setOnPreferenceClickListener(from.getOnPreferenceClickListener());
+        to.setOnPreferenceChangeListener(from.getOnPreferenceChangeListener());
+        to.setIcon(from.getIcon());
+        to.setFragment(from.getFragment());
+        to.setIntent(from.getIntent());
+        to.setKey(from.getKey());
+        to.setOrder(from.getOrder());
+        to.setSelectable(from.isSelectable());
+        to.setPersistent(from.isPersistent());
+        to.setIconSpaceReserved(from.isIconSpaceReserved());
+        to.setWidgetLayoutResource(from.getWidgetLayoutResource());
+        to.setPreferenceDataStore(from.getPreferenceDataStore());
+        to.setShouldDisableView(from.getShouldDisableView());
+        to.setSingleLineTitle(from.isSingleLineTitle());
+        to.setVisible(from.isVisible());
+        to.setLayoutResource(from.getLayoutResource());
+        to.setCopyingEnabled(from.isCopyingEnabled());
+
+        if (from.getSummaryProvider() != null) {
+            to.setSummaryProvider(from.getSummaryProvider());
+        } else {
+            to.setSummary(from.getSummary());
+        }
+
+        if (from.peekExtras() != null) {
+            to.getExtras().putAll(from.peekExtras());
+        }
+
+        if (from instanceof DialogPreference) {
+            DialogPreference fromDialog = (DialogPreference) from;
+            DialogPreference toDialog = (DialogPreference) to;
+            toDialog.setDialogTitle(fromDialog.getDialogTitle());
+            toDialog.setDialogIcon(fromDialog.getDialogIcon());
+            toDialog.setDialogMessage(fromDialog.getDialogMessage());
+            toDialog.setDialogLayoutResource(fromDialog.getDialogLayoutResource());
+            toDialog.setNegativeButtonText(fromDialog.getNegativeButtonText());
+            toDialog.setPositiveButtonText(fromDialog.getPositiveButtonText());
+        }
+
+        // DropDownPreference extends ListPreference and doesn't add any extra api surface,
+        // so we don't need a case for it
+        if (from instanceof ListPreference) {
+            ListPreference fromList = (ListPreference) from;
+            ListPreference toList = (ListPreference) to;
+            toList.setEntries(fromList.getEntries());
+            toList.setEntryValues(fromList.getEntryValues());
+            toList.setValue(fromList.getValue());
+        } else if (from instanceof EditTextPreference) {
+            EditTextPreference fromText = (EditTextPreference) from;
+            EditTextPreference toText = (EditTextPreference) to;
+            toText.setText(fromText.getText());
+        } else if (from instanceof MultiSelectListPreference) {
+            MultiSelectListPreference fromMulti = (MultiSelectListPreference) from;
+            MultiSelectListPreference toMulti = (MultiSelectListPreference) to;
+            toMulti.setEntries(fromMulti.getEntries());
+            toMulti.setEntryValues(fromMulti.getEntryValues());
+            toMulti.setValues(fromMulti.getValues());
+        } else if (from instanceof TwoStatePreference) {
+            TwoStatePreference fromTwoState = (TwoStatePreference) from;
+            TwoStatePreference toTwoState = (TwoStatePreference) to;
+            toTwoState.setSummaryOn(fromTwoState.getSummaryOn());
+            toTwoState.setSummaryOff(fromTwoState.getSummaryOff());
+
+            if (from instanceof SwitchPreference) {
+                SwitchPreference fromSwitch = (SwitchPreference) from;
+                SwitchPreference toSwitch = (SwitchPreference) to;
+                toSwitch.setSwitchTextOn(fromSwitch.getSwitchTextOn());
+                toSwitch.setSwitchTextOff(fromSwitch.getSwitchTextOff());
+            }
+        }
+
+        // We don't need to add checks for things that we will never replace,
+        // like PreferenceGroup or CheckBoxPreference
+
+        return to;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/SeekbarPreferenceDialogFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/SeekbarPreferenceDialogFragment.java
new file mode 100644
index 0000000..57d2e75
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/SeekbarPreferenceDialogFragment.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 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.car.ui.preference;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+/**
+ * A fragment that provides a layout with a seekbar within a dialog.
+ */
+public class SeekbarPreferenceDialogFragment extends PreferenceDialogFragment {
+
+    /**
+     * Returns a new instance of {@link SeekbarPreferenceDialogFragment} for the {@link
+     * CarUiSeekBarDialogPreference} with the given {@code key}.
+     */
+    public static SeekbarPreferenceDialogFragment newInstance(String key) {
+        SeekbarPreferenceDialogFragment fragment = new SeekbarPreferenceDialogFragment();
+        Bundle b = new Bundle(/* capacity= */ 1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    @Override
+    protected void onBindDialogView(@NonNull View view) {
+        super.onBindDialogView(view);
+
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onBindDialogView(view);
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        super.onClick(dialog, which);
+
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onClick(dialog, which);
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onDialogClosed(positiveResult);
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(@NonNull AlertDialog.Builder builder) {
+        DialogFragmentCallbacks dialogPreference = (DialogFragmentCallbacks) getPreference();
+        dialogPreference.onPrepareDialogBuilder(builder);
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiCheckBoxListItem.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiCheckBoxListItem.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/CarUiCheckBoxListItem.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiCheckBoxListItem.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiContentListItem.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiContentListItem.java
new file mode 100644
index 0000000..71f5d1a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiContentListItem.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Definition of list items that can be inserted into {@link CarUiListItemAdapter}.
+ */
+public class CarUiContentListItem extends CarUiListItem {
+
+    /**
+     * Callback to be invoked when the checked state of a list item changed.
+     */
+    public interface OnCheckedChangeListener {
+        /**
+         * Called when the checked state of a list item has changed.
+         *
+         * @param item      whose checked state changed.
+         * @param isChecked new checked state of list item.
+         */
+        void onCheckedChanged(@NonNull CarUiContentListItem item, boolean isChecked);
+    }
+
+    /**
+     * Callback to be invoked when an item is clicked.
+     */
+    public interface OnClickListener {
+        /**
+         * Called when the item has been clicked.
+         *
+         * @param item whose checked state changed.
+         */
+        void onClick(@NonNull CarUiContentListItem item);
+    }
+
+    public enum IconType {
+        /**
+         * For an icon type of CONTENT, the primary icon is a larger than {@code STANDARD}.
+         */
+        CONTENT,
+        /**
+         * For an icon type of STANDARD, the primary icon is the standard size.
+         */
+        STANDARD,
+        /**
+         * For an icon type of AVATAR, the primary icon is masked to provide an icon with a modified
+         * shape.
+         */
+        AVATAR
+    }
+
+    /**
+     * Enum of secondary action types of a list item.
+     */
+    public enum Action {
+        /**
+         * For an action value of NONE, no action element is shown for a list item.
+         */
+        NONE,
+        /**
+         * For an action value of SWITCH, a switch is shown for the action element of the list item.
+         */
+        SWITCH,
+        /**
+         * For an action value of CHECK_BOX, a checkbox is shown for the action element of the list
+         * item.
+         */
+        CHECK_BOX,
+        /**
+         * For an action value of RADIO_BUTTON, a radio button is shown for the action element of
+         * the list item.
+         */
+        RADIO_BUTTON,
+        /**
+         * For an action value of ICON, an icon is shown for the action element of the list item.
+         */
+        ICON,
+        /**
+         * For an action value CHEVRON, a chevron is shown for the action element of the list
+         * item.
+         */
+        CHEVRON
+    }
+
+    private Drawable mIcon;
+    @Nullable
+    private Drawable mSupplementalIcon;
+    private CharSequence mTitle;
+    private CharSequence mBody;
+    private final Action mAction;
+    private IconType mPrimaryIconType;
+    private boolean mIsActionDividerVisible;
+    private boolean mIsChecked;
+    private boolean mIsEnabled = true;
+    private boolean mIsActivated;
+    private OnClickListener mOnClickListener;
+    private OnCheckedChangeListener mOnCheckedChangeListener;
+    private View.OnClickListener mSupplementalIconOnClickListener;
+
+
+    public CarUiContentListItem(Action action) {
+        mAction = action;
+        mPrimaryIconType = IconType.STANDARD;
+    }
+
+    /**
+     * Returns the title of the item.
+     */
+    @Nullable
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Sets the title of the item.
+     *
+     * @param title text to display as title.
+     */
+    public void setTitle(@NonNull CharSequence title) {
+        mTitle = title;
+    }
+
+    /**
+     * Returns the body text of the item.
+     */
+    @Nullable
+    public CharSequence getBody() {
+        return mBody;
+    }
+
+    /**
+     * Sets the body of the item.
+     *
+     * @param body text to display as body text.
+     */
+    public void setBody(@NonNull CharSequence body) {
+        mBody = body;
+    }
+
+    /**
+     * Returns the icon of the item.
+     */
+    @Nullable
+    public Drawable getIcon() {
+        return mIcon;
+    }
+
+    /**
+     * Sets the icon of the item.
+     *
+     * @param icon the icon to display.
+     */
+    public void setIcon(@Nullable Drawable icon) {
+        mIcon = icon;
+    }
+
+    /**
+     * Returns the primary icon type for the item.
+     */
+    public IconType getPrimaryIconType() {
+        return mPrimaryIconType;
+    }
+
+    /**
+     * Sets the primary icon type for the item.
+     *
+     * @param icon the icon type for the item.
+     */
+    public void setPrimaryIconType(IconType icon) {
+        mPrimaryIconType = icon;
+    }
+
+    /**
+     * Returns {@code true} if the item is activated.
+     */
+    public boolean isActivated() {
+        return mIsActivated;
+    }
+
+    /**
+     * Sets the activated state of the item.
+     *
+     * @param activated the activated state for the item.
+     */
+    public void setActivated(boolean activated) {
+        mIsActivated = activated;
+    }
+
+    /**
+     * Returns {@code true} if the item is enabled.
+     */
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    /**
+     * Sets the enabled state of the item.
+     *
+     * @param enabled the enabled state for the item.
+     */
+    public void setEnabled(boolean enabled) {
+        mIsEnabled = enabled;
+    }
+
+    /**
+     * Returns {@code true} if the item is checked. Will always return {@code false} when the action
+     * type for the item is {@code Action.NONE}.
+     */
+    public boolean isChecked() {
+        return mIsChecked;
+    }
+
+    /**
+     * Sets the checked state of the item.
+     *
+     * @param checked the checked state for the item.
+     */
+    public void setChecked(boolean checked) {
+        if (checked == mIsChecked) {
+            return;
+        }
+
+        // Checked state can only be set when action type is checkbox, radio button or switch.
+        if (mAction == Action.CHECK_BOX || mAction == Action.SWITCH
+                || mAction == Action.RADIO_BUTTON) {
+            mIsChecked = checked;
+
+            if (mOnCheckedChangeListener != null) {
+                mOnCheckedChangeListener.onCheckedChanged(this, mIsChecked);
+            }
+        }
+    }
+
+    /**
+     * Sets the visibility of the action divider.
+     *
+     * @param visible visibility of the action divider.
+     */
+    public void setActionDividerVisible(boolean visible) {
+        mIsActionDividerVisible = visible;
+    }
+
+    /**
+     * Returns {@code true} if the action divider is visible.
+     */
+    public boolean isActionDividerVisible() {
+        return mIsActionDividerVisible;
+    }
+
+    /**
+     * Returns the action type for the item.
+     */
+    public Action getAction() {
+        return mAction;
+    }
+
+    /**
+     * Returns the supplemental icon for the item.
+     */
+    @Nullable
+    public Drawable getSupplementalIcon() {
+        if (mAction != Action.ICON) {
+            return null;
+        }
+
+        return mSupplementalIcon;
+    }
+
+    /**
+     * Sets supplemental icon to be displayed in a list item.
+     *
+     * @param icon the Drawable to set as the icon, or null to clear the content.
+     */
+    public void setSupplementalIcon(@Nullable Drawable icon) {
+        setSupplementalIcon(icon, null);
+    }
+
+    /**
+     * Sets supplemental icon to be displayed in a list item.
+     *
+     * @param icon     the Drawable to set as the icon, or null to clear the content.
+     * @param listener the callback that is invoked when the icon is clicked.
+     */
+    public void setSupplementalIcon(@Nullable Drawable icon,
+            @Nullable View.OnClickListener listener) {
+        if (mAction != Action.ICON) {
+            throw new IllegalStateException(
+                    "Cannot set supplemental icon on list item that does not have an action of "
+                            + "type ICON");
+        }
+
+        mSupplementalIcon = icon;
+        mSupplementalIconOnClickListener = listener;
+    }
+
+    @Nullable
+    public View.OnClickListener getSupplementalIconOnClickListener() {
+        return mSupplementalIconOnClickListener;
+    }
+
+    /**
+     * Registers a callback to be invoked when the item is clicked.
+     *
+     * @param listener callback to be invoked when item is clicked.
+     */
+    public void setOnItemClickedListener(@Nullable OnClickListener listener) {
+        mOnClickListener = listener;
+    }
+
+    /**
+     * Returns the {@link OnClickListener} registered for this item.
+     */
+    @Nullable
+    public OnClickListener getOnClickListener() {
+        return mOnClickListener;
+    }
+
+    /**
+     * Registers a callback to be invoked when the checked state of list item changes.
+     *
+     * <p>Checked state changes can take place when the action type is {@code Action.SWITCH} or
+     * {@code Action.CHECK_BOX}.
+     *
+     * @param listener callback to be invoked when the checked state shown in the UI changes.
+     */
+    public void setOnCheckedChangeListener(
+            @Nullable OnCheckedChangeListener listener) {
+        mOnCheckedChangeListener = listener;
+    }
+
+    /**
+     * Returns the {@link OnCheckedChangeListener} registered for this item.
+     */
+    @Nullable
+    public OnCheckedChangeListener getOnCheckedChangeListener() {
+        return mOnCheckedChangeListener;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiHeaderListItem.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiHeaderListItem.java
new file mode 100644
index 0000000..81dfa19
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiHeaderListItem.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Definition of list item header that can be inserted into {@link CarUiListItemAdapter}.
+ */
+public class CarUiHeaderListItem extends CarUiListItem {
+
+    private final CharSequence mTitle;
+    private final CharSequence mBody;
+
+    public CarUiHeaderListItem(@NonNull CharSequence title) {
+        this(title, "");
+    }
+
+    public CarUiHeaderListItem(@NonNull CharSequence title, @NonNull CharSequence body) {
+        mTitle = title;
+        mBody = body;
+    }
+
+    /**
+     * Returns the title text for the header.
+     */
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns the body text for the header.
+     */
+    public CharSequence getBody() {
+        return mBody;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItem.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItem.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItem.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItem.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItemAdapter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
new file mode 100644
index 0000000..8bc39eb
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+
+import java.util.List;
+
+/**
+ * Adapter for {@link CarUiRecyclerView} to display {@link CarUiContentListItem} and {@link
+ * CarUiHeaderListItem}.
+ *
+ * <ul>
+ * <li> Implements {@link CarUiRecyclerView.ItemCap} - defaults to unlimited item count.
+ * </ul>
+ */
+public class CarUiListItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements
+        CarUiRecyclerView.ItemCap {
+
+    static final int VIEW_TYPE_LIST_ITEM = 1;
+    static final int VIEW_TYPE_LIST_HEADER = 2;
+
+    private final List<? extends CarUiListItem> mItems;
+    private int mMaxItems = CarUiRecyclerView.ItemCap.UNLIMITED;
+
+    public CarUiListItemAdapter(List<? extends CarUiListItem> items) {
+        this.mItems = items;
+    }
+
+    @NonNull
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(
+            @NonNull ViewGroup parent, int viewType) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+
+        switch (viewType) {
+            case VIEW_TYPE_LIST_ITEM:
+                return new ListItemViewHolder(
+                        inflater.inflate(R.layout.car_ui_list_item, parent, false));
+            case VIEW_TYPE_LIST_HEADER:
+                return new HeaderViewHolder(
+                        inflater.inflate(R.layout.car_ui_header_list_item, parent, false));
+            default:
+                throw new IllegalStateException("Unknown item type.");
+        }
+    }
+
+    /**
+     * Returns the data set held by the adapter.
+     *
+     * <p>Any changes performed to this mutable list must be followed with an invocation of the
+     * appropriate notify method for the adapter.
+     */
+    @NonNull
+    public List<? extends CarUiListItem> getItems() {
+        return mItems;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (mItems.get(position) instanceof CarUiContentListItem) {
+            return VIEW_TYPE_LIST_ITEM;
+        } else if (mItems.get(position) instanceof CarUiHeaderListItem) {
+            return VIEW_TYPE_LIST_HEADER;
+        }
+
+        throw new IllegalStateException("Unknown view type.");
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+        switch (holder.getItemViewType()) {
+            case VIEW_TYPE_LIST_ITEM:
+                if (!(holder instanceof ListItemViewHolder)) {
+                    throw new IllegalStateException("Incorrect view holder type for list item.");
+                }
+
+                CarUiListItem item = mItems.get(position);
+                if (!(item instanceof CarUiContentListItem)) {
+                    throw new IllegalStateException(
+                            "Expected item to be bound to viewHolder to be instance of "
+                                    + "CarUiContentListItem.");
+                }
+
+                ((ListItemViewHolder) holder).bind((CarUiContentListItem) item);
+                break;
+            case VIEW_TYPE_LIST_HEADER:
+                if (!(holder instanceof HeaderViewHolder)) {
+                    throw new IllegalStateException("Incorrect view holder type for list item.");
+                }
+
+                CarUiListItem header = mItems.get(position);
+                if (!(header instanceof CarUiHeaderListItem)) {
+                    throw new IllegalStateException(
+                            "Expected item to be bound to viewHolder to be instance of "
+                                    + "CarUiHeaderListItem.");
+                }
+
+                ((HeaderViewHolder) holder).bind((CarUiHeaderListItem) header);
+                break;
+            default:
+                throw new IllegalStateException("Unknown item view type.");
+        }
+    }
+
+    @Override
+    public int getItemCount() {
+        return mMaxItems == CarUiRecyclerView.ItemCap.UNLIMITED
+                ? mItems.size()
+                : Math.min(mItems.size(), mMaxItems);
+    }
+
+    @Override
+    public void setMaxItems(int maxItems) {
+        mMaxItems = maxItems;
+    }
+
+    /**
+     * Holds views of {@link CarUiContentListItem}.
+     */
+    static class ListItemViewHolder extends RecyclerView.ViewHolder {
+
+        final TextView mTitle;
+        final TextView mBody;
+        final ImageView mIcon;
+        final ImageView mContentIcon;
+        final ImageView mAvatarIcon;
+        final ViewGroup mIconContainer;
+        final ViewGroup mActionContainer;
+        final View mActionDivider;
+        final Switch mSwitch;
+        final CheckBox mCheckBox;
+        final RadioButton mRadioButton;
+        final ImageView mSupplementalIcon;
+        final View mTouchInterceptor;
+        final View mReducedTouchInterceptor;
+        final View mActionContainerTouchInterceptor;
+
+        ListItemViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mTitle = requireViewByRefId(itemView, R.id.title);
+            mBody = requireViewByRefId(itemView, R.id.body);
+            mIcon = requireViewByRefId(itemView, R.id.icon);
+            mContentIcon = requireViewByRefId(itemView, R.id.content_icon);
+            mAvatarIcon = requireViewByRefId(itemView, R.id.avatar_icon);
+            mIconContainer = requireViewByRefId(itemView, R.id.icon_container);
+            mActionContainer = requireViewByRefId(itemView, R.id.action_container);
+            mActionDivider = requireViewByRefId(itemView, R.id.action_divider);
+            mSwitch = requireViewByRefId(itemView, R.id.switch_widget);
+            mCheckBox = requireViewByRefId(itemView, R.id.checkbox_widget);
+            mRadioButton = requireViewByRefId(itemView, R.id.radio_button_widget);
+            mSupplementalIcon = requireViewByRefId(itemView, R.id.supplemental_icon);
+            mReducedTouchInterceptor = requireViewByRefId(itemView, R.id.reduced_touch_interceptor);
+            mTouchInterceptor = requireViewByRefId(itemView, R.id.touch_interceptor);
+            mActionContainerTouchInterceptor = requireViewByRefId(itemView,
+                    R.id.action_container_touch_interceptor);
+        }
+
+        void bind(@NonNull CarUiContentListItem item) {
+            CharSequence title = item.getTitle();
+            CharSequence body = item.getBody();
+            Drawable icon = item.getIcon();
+
+            if (!TextUtils.isEmpty(title)) {
+                mTitle.setText(title);
+                mTitle.setVisibility(View.VISIBLE);
+            } else {
+                mTitle.setVisibility(View.GONE);
+            }
+
+            if (!TextUtils.isEmpty(body)) {
+                mBody.setText(body);
+                mBody.setVisibility(View.VISIBLE);
+            } else {
+                mBody.setVisibility(View.GONE);
+            }
+
+            mIcon.setVisibility(View.GONE);
+            mContentIcon.setVisibility(View.GONE);
+            mAvatarIcon.setVisibility(View.GONE);
+
+            if (icon != null) {
+                mIconContainer.setVisibility(View.VISIBLE);
+
+                switch (item.getPrimaryIconType()) {
+                    case CONTENT:
+                        mContentIcon.setVisibility(View.VISIBLE);
+                        mContentIcon.setImageDrawable(icon);
+                        break;
+                    case STANDARD:
+                        mIcon.setVisibility(View.VISIBLE);
+                        mIcon.setImageDrawable(icon);
+                        break;
+                    case AVATAR:
+                        mAvatarIcon.setVisibility(View.VISIBLE);
+                        mAvatarIcon.setImageDrawable(icon);
+                        mAvatarIcon.setClipToOutline(true);
+                        break;
+                }
+            } else {
+                mIconContainer.setVisibility(View.GONE);
+            }
+
+            mActionDivider.setVisibility(
+                    item.isActionDividerVisible() ? View.VISIBLE : View.GONE);
+            mSwitch.setVisibility(View.GONE);
+            mCheckBox.setVisibility(View.GONE);
+            mRadioButton.setVisibility(View.GONE);
+            mSupplementalIcon.setVisibility(View.GONE);
+
+            CarUiContentListItem.OnClickListener itemOnClickListener = item.getOnClickListener();
+
+            switch (item.getAction()) {
+                case NONE:
+                    mActionContainer.setVisibility(View.GONE);
+
+                    // Display ripple effects across entire item when clicked by using full-sized
+                    // touch interceptor.
+                    mTouchInterceptor.setVisibility(View.VISIBLE);
+                    mTouchInterceptor.setOnClickListener(v -> {
+                        if (itemOnClickListener != null) {
+                            itemOnClickListener.onClick(item);
+                        }
+                    });
+                    mReducedTouchInterceptor.setVisibility(View.GONE);
+                    mActionContainerTouchInterceptor.setVisibility(View.GONE);
+                    break;
+                case SWITCH:
+                    bindCompoundButton(item, mSwitch, itemOnClickListener);
+                    break;
+                case CHECK_BOX:
+                    bindCompoundButton(item, mCheckBox, itemOnClickListener);
+                    break;
+                case RADIO_BUTTON:
+                    bindCompoundButton(item, mRadioButton, itemOnClickListener);
+                    break;
+                case CHEVRON:
+                    mSupplementalIcon.setVisibility(View.VISIBLE);
+                    mSupplementalIcon.setImageDrawable(itemView.getContext().getDrawable(
+                            R.drawable.car_ui_preference_icon_chevron));
+                    mActionContainer.setVisibility(View.VISIBLE);
+                    mTouchInterceptor.setVisibility(View.VISIBLE);
+                    mTouchInterceptor.setOnClickListener(v -> {
+                        if (itemOnClickListener != null) {
+                            itemOnClickListener.onClick(item);
+                        }
+                    });
+                    mReducedTouchInterceptor.setVisibility(View.GONE);
+                    mActionContainerTouchInterceptor.setVisibility(View.GONE);
+                    break;
+                case ICON:
+                    mSupplementalIcon.setVisibility(View.VISIBLE);
+                    mSupplementalIcon.setImageDrawable(item.getSupplementalIcon());
+                    mActionContainer.setVisibility(View.VISIBLE);
+
+                    // If the icon has a click listener, use a reduced touch interceptor to create
+                    // two distinct touch area; the action container and the remainder of the list
+                    // item. Each touch area will have its own ripple effect. If the icon has no
+                    // click listener, it shouldn't be clickable.
+                    if (item.getSupplementalIconOnClickListener() == null) {
+                        mTouchInterceptor.setVisibility(View.VISIBLE);
+                        mTouchInterceptor.setOnClickListener(v -> {
+                            if (itemOnClickListener != null) {
+                                itemOnClickListener.onClick(item);
+                            }
+                        });
+                        mReducedTouchInterceptor.setVisibility(View.GONE);
+                        mActionContainerTouchInterceptor.setVisibility(View.GONE);
+                    } else {
+                        mReducedTouchInterceptor.setVisibility(View.VISIBLE);
+                        mReducedTouchInterceptor.setOnClickListener(v -> {
+                            if (itemOnClickListener != null) {
+                                itemOnClickListener.onClick(item);
+                            }
+                        });
+                        mActionContainerTouchInterceptor.setVisibility(View.VISIBLE);
+                        mActionContainerTouchInterceptor.setOnClickListener(
+                                (container) -> {
+                                    if (item.getSupplementalIconOnClickListener() != null) {
+                                        item.getSupplementalIconOnClickListener().onClick(
+                                                mSupplementalIcon);
+                                    }
+                                });
+                        mTouchInterceptor.setVisibility(View.GONE);
+                    }
+                    break;
+                default:
+                    throw new IllegalStateException("Unknown secondary action type.");
+            }
+
+            itemView.setActivated(item.isActivated());
+            setEnabled(itemView, item.isEnabled());
+        }
+
+        void setEnabled(View view, boolean enabled) {
+            view.setEnabled(enabled);
+            if (view instanceof ViewGroup) {
+                ViewGroup group = (ViewGroup) view;
+
+                for (int i = 0; i < group.getChildCount(); i++) {
+                    setEnabled(group.getChildAt(i), enabled);
+                }
+            }
+        }
+
+        void bindCompoundButton(@NonNull CarUiContentListItem item,
+                @NonNull CompoundButton compoundButton,
+                @Nullable CarUiContentListItem.OnClickListener itemOnClickListener) {
+            compoundButton.setVisibility(View.VISIBLE);
+            compoundButton.setOnCheckedChangeListener(null);
+            compoundButton.setChecked(item.isChecked());
+            compoundButton.setOnCheckedChangeListener(
+                    (buttonView, isChecked) -> item.setChecked(isChecked));
+
+            // Clicks anywhere on the item should toggle the checkbox state. Use full touch
+            // interceptor.
+            mTouchInterceptor.setVisibility(View.VISIBLE);
+            mTouchInterceptor.setOnClickListener(v -> {
+                compoundButton.toggle();
+                if (itemOnClickListener != null) {
+                    itemOnClickListener.onClick(item);
+                }
+            });
+            mReducedTouchInterceptor.setVisibility(View.GONE);
+            mActionContainerTouchInterceptor.setVisibility(View.GONE);
+
+            mActionContainer.setVisibility(View.VISIBLE);
+            mActionContainer.setClickable(false);
+        }
+    }
+
+    /**
+     * Holds views of {@link CarUiHeaderListItem}.
+     */
+    static class HeaderViewHolder extends RecyclerView.ViewHolder {
+
+        private final TextView mTitle;
+        private final TextView mBody;
+
+        HeaderViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mTitle = requireViewByRefId(itemView, R.id.title);
+            mBody = requireViewByRefId(itemView, R.id.body);
+        }
+
+        private void bind(@NonNull CarUiHeaderListItem item) {
+            mTitle.setText(item.getTitle());
+
+            CharSequence body = item.getBody();
+            if (!TextUtils.isEmpty(body)) {
+                mBody.setText(body);
+            } else {
+                mBody.setVisibility(View.GONE);
+            }
+        }
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItem.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRadioButtonListItem.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItem.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRadioButtonListItem.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java
new file mode 100644
index 0000000..80d763e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2020 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.car.ui.recyclerview;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+
+import java.util.List;
+
+/**
+ * Adapter for {@link CarUiRecyclerView} to display {@link CarUiRadioButtonListItem}. This adapter
+ * allows for at most one item to be selected at a time.
+ *
+ * <ul>
+ * <li> Implements {@link CarUiRecyclerView.ItemCap} - defaults to unlimited item count.
+ * </ul>
+ */
+public class CarUiRadioButtonListItemAdapter extends CarUiListItemAdapter {
+
+    private int mSelectedIndex = -1;
+
+    public CarUiRadioButtonListItemAdapter(List<CarUiRadioButtonListItem> items) {
+        super(items);
+        for (int i = 0; i < items.size(); i++) {
+            CarUiRadioButtonListItem item = items.get(i);
+            if (item.isChecked() && mSelectedIndex >= 0) {
+                throw new IllegalStateException(
+                        "At most one item in a CarUiRadioButtonListItemAdapter can be checked");
+            }
+
+            if (item.isChecked()) {
+                mSelectedIndex = i;
+            }
+        }
+    }
+
+    @NonNull
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(
+            @NonNull ViewGroup parent, int viewType) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+
+        if (viewType == VIEW_TYPE_LIST_ITEM) {
+            return new RadioButtonListItemViewHolder(
+                    inflater.inflate(R.layout.car_ui_list_item, parent, false));
+        }
+        return super.onCreateViewHolder(parent, viewType);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+        if (holder.getItemViewType() == VIEW_TYPE_LIST_ITEM) {
+            if (!(holder instanceof RadioButtonListItemViewHolder)) {
+                throw new IllegalStateException("Incorrect view holder type for list item.");
+            }
+
+            CarUiListItem item = getItems().get(position);
+            if (!(item instanceof CarUiRadioButtonListItem)) {
+                throw new IllegalStateException(
+                        "Expected item to be bound to viewHolder to be instance of "
+                                + "CarUiRadioButtonListItem.");
+            }
+
+            RadioButtonListItemViewHolder actualHolder = ((RadioButtonListItemViewHolder) holder);
+            actualHolder.bind((CarUiRadioButtonListItem) item);
+            actualHolder.setOnCheckedChangeListener(isChecked -> {
+                if (isChecked && mSelectedIndex >= 0) {
+                    CarUiRadioButtonListItem previousSelectedItem =
+                            (CarUiRadioButtonListItem) getItems().get(mSelectedIndex);
+                    previousSelectedItem.setChecked(false);
+                    notifyItemChanged(mSelectedIndex);
+                }
+
+                if (isChecked) {
+                    mSelectedIndex = position;
+                    CarUiRadioButtonListItem currentSelectedItem =
+                            (CarUiRadioButtonListItem) getItems().get(mSelectedIndex);
+                    currentSelectedItem.setChecked(true);
+                    notifyItemChanged(mSelectedIndex);
+                }
+            });
+
+        } else {
+            super.onBindViewHolder(holder, position);
+        }
+    }
+
+    /*
+     * @return the position of the currently selected item, -1 if no item is selected.
+     */
+    public int getSelectedItemPosition() {
+        return mSelectedIndex;
+    }
+
+    static class RadioButtonListItemViewHolder extends ListItemViewHolder {
+        /**
+         * Callback to be invoked when the checked state of a {@link RadioButtonListItemViewHolder}
+         * changed.
+         */
+        public interface OnCheckedChangeListener {
+            /**
+             * Called when the checked state of a {@link RadioButtonListItemViewHolder} has changed.
+             *
+             * @param isChecked new checked state of list item.
+             */
+            void onCheckedChanged(boolean isChecked);
+        }
+
+        @Nullable
+        private OnCheckedChangeListener mListener;
+
+        RadioButtonListItemViewHolder(@NonNull View itemView) {
+            super(itemView);
+        }
+
+        void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) {
+            mListener = listener;
+        }
+
+        @Override
+        void bind(@NonNull CarUiContentListItem item) {
+            super.bind(item);
+            mRadioButton.setOnCheckedChangeListener(
+                    (buttonView, isChecked) -> {
+                        item.setChecked(isChecked);
+                        if (mListener != null) {
+                            mListener.onCheckedChanged(isChecked);
+                        }
+                    });
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerView.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerView.java
new file mode 100644
index 0000000..e9e5b3c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerView.java
@@ -0,0 +1,600 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview;
+
+import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_CONTAINER;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_HORIZONTALLY_SCROLLABLE;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_VERTICALLY_SCROLLABLE;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.InputDevice;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+import com.android.car.ui.recyclerview.decorations.grid.GridDividerItemDecoration;
+import com.android.car.ui.recyclerview.decorations.grid.GridOffsetItemDecoration;
+import com.android.car.ui.recyclerview.decorations.linear.LinearDividerItemDecoration;
+import com.android.car.ui.recyclerview.decorations.linear.LinearOffsetItemDecoration;
+import com.android.car.ui.recyclerview.decorations.linear.LinearOffsetItemDecoration.OffsetPosition;
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+
+import java.lang.annotation.Retention;
+import java.util.Objects;
+
+/**
+ * View that extends a {@link RecyclerView} and wraps itself into a {@link LinearLayout} which could
+ * potentially include a scrollbar that has page up and down arrows. Interaction with this view is
+ * similar to a {@code RecyclerView} as it takes the same adapter and the layout manager.
+ */
+public final class CarUiRecyclerView extends RecyclerView {
+
+    private static final String TAG = "CarUiRecyclerView";
+
+    private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener mListener =
+            new UxRestrictionChangedListener();
+
+    @NonNull
+    private final CarUxRestrictionsUtil mCarUxRestrictionsUtil;
+    private boolean mScrollBarEnabled;
+    @Nullable
+    private String mScrollBarClass;
+    private int mScrollBarPaddingTop;
+    private int mScrollBarPaddingBottom;
+
+    @Nullable
+    private ScrollBar mScrollBar;
+
+    @Nullable
+    private GridOffsetItemDecoration mTopOffsetItemDecorationGrid;
+    @Nullable
+    private GridOffsetItemDecoration mBottomOffsetItemDecorationGrid;
+    @Nullable
+    private RecyclerView.ItemDecoration mTopOffsetItemDecorationLinear;
+    @Nullable
+    private RecyclerView.ItemDecoration mBottomOffsetItemDecorationLinear;
+    @Nullable
+    private GridDividerItemDecoration mDividerItemDecorationGrid;
+    @Nullable
+    private RecyclerView.ItemDecoration mDividerItemDecorationLinear;
+    private int mNumOfColumns;
+    private boolean mInstallingExtScrollBar = false;
+    private int mContainerVisibility = View.VISIBLE;
+    @Nullable
+    private Rect mContainerPadding;
+    @Nullable
+    private Rect mContainerPaddingRelative;
+    @Nullable
+    private LinearLayout mContainer;
+
+    // Set to true when when styled attributes are read and initialized.
+    private boolean mIsInitialized;
+    private boolean mEnableDividers;
+    private int mTopOffset;
+    private int mBottomOffset;
+
+    private boolean mHasScrolled = false;
+
+    private OnScrollListener mOnScrollListener = new OnScrollListener() {
+        @Override
+        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+            if (dx > 0 || dy > 0) {
+                mHasScrolled = true;
+                removeOnScrollListener(this);
+            }
+        }
+    };
+
+    /**
+     * The possible values for setScrollBarPosition. The default value is actually {@link
+     * CarUiRecyclerViewLayout#LINEAR}.
+     */
+    @IntDef({
+            CarUiRecyclerViewLayout.LINEAR,
+            CarUiRecyclerViewLayout.GRID,
+    })
+    @Retention(SOURCE)
+    public @interface CarUiRecyclerViewLayout {
+        /**
+         * Arranges items either horizontally in a single row or vertically in a single column. This
+         * is default.
+         */
+        int LINEAR = 0;
+
+        /**
+         * Arranges items in a Grid.
+         */
+        int GRID = 1;
+    }
+
+    /**
+     * Interface for a {@link RecyclerView.Adapter} to cap the number of items.
+     *
+     * <p>NOTE: it is still up to the adapter to use maxItems in {@link
+     * RecyclerView.Adapter#getItemCount()}.
+     *
+     * <p>the recommended way would be with:
+     *
+     * <pre>{@code
+     * {@literal@}Override
+     * public int getItemCount() {
+     *   return Math.min(super.getItemCount(), mMaxItems);
+     * }
+     * }</pre>
+     */
+    public interface ItemCap {
+
+        /**
+         * A value to pass to {@link #setMaxItems(int)} that indicates there should be no limit.
+         */
+        int UNLIMITED = -1;
+
+        /**
+         * Sets the maximum number of items available in the adapter. A value less than '0' means
+         * the list should not be capped.
+         */
+        void setMaxItems(int maxItems);
+    }
+
+    public CarUiRecyclerView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CarUiRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, R.attr.carUiRecyclerViewStyle);
+    }
+
+    public CarUiRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs,
+            int defStyle) {
+        super(context, attrs, defStyle);
+        mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
+        init(context, attrs, defStyle);
+    }
+
+    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
+        initRotaryScroll();
+        setClipToPadding(false);
+        TypedArray a = context.obtainStyledAttributes(
+                attrs,
+                R.styleable.CarUiRecyclerView,
+                defStyleAttr,
+                R.style.Widget_CarUi_CarUiRecyclerView);
+
+        mScrollBarEnabled = context.getResources().getBoolean(R.bool.car_ui_scrollbar_enable);
+
+        mScrollBarPaddingTop = context.getResources()
+                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_padding_top);
+        mScrollBarPaddingBottom = context.getResources()
+                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_padding_bottom);
+
+        @CarUiRecyclerViewLayout int carUiRecyclerViewLayout =
+                a.getInt(R.styleable.CarUiRecyclerView_layoutStyle, CarUiRecyclerViewLayout.LINEAR);
+        mNumOfColumns = a.getInt(R.styleable.CarUiRecyclerView_numOfColumns, /* defValue= */ 2);
+        mEnableDividers =
+                a.getBoolean(R.styleable.CarUiRecyclerView_enableDivider, /* defValue= */ false);
+
+        mDividerItemDecorationLinear = new LinearDividerItemDecoration(
+                context.getDrawable(R.drawable.car_ui_recyclerview_divider));
+
+        mDividerItemDecorationGrid =
+                new GridDividerItemDecoration(
+                        context.getDrawable(R.drawable.car_ui_divider),
+                        context.getDrawable(R.drawable.car_ui_divider),
+                        mNumOfColumns);
+
+        mTopOffset = a.getInteger(R.styleable.CarUiRecyclerView_topOffset, /* defValue= */0);
+        mBottomOffset = a.getInteger(
+                R.styleable.CarUiRecyclerView_bottomOffset, /* defValue= */0);
+        mTopOffsetItemDecorationLinear =
+                new LinearOffsetItemDecoration(mTopOffset, OffsetPosition.START);
+        mBottomOffsetItemDecorationLinear =
+                new LinearOffsetItemDecoration(mBottomOffset, OffsetPosition.END);
+        mTopOffsetItemDecorationGrid =
+                new GridOffsetItemDecoration(mTopOffset, mNumOfColumns,
+                        OffsetPosition.START);
+        mBottomOffsetItemDecorationGrid =
+                new GridOffsetItemDecoration(mBottomOffset, mNumOfColumns,
+                        OffsetPosition.END);
+
+        mIsInitialized = true;
+
+        // Check if a layout manager has already been set via XML
+        boolean isLayoutMangerSet = getLayoutManager() != null;
+        if (!isLayoutMangerSet && carUiRecyclerViewLayout == CarUiRecyclerViewLayout.LINEAR) {
+            setLayoutManager(new LinearLayoutManager(getContext()));
+        } else if (!isLayoutMangerSet && carUiRecyclerViewLayout == CarUiRecyclerViewLayout.GRID) {
+            setLayoutManager(new GridLayoutManager(getContext(), mNumOfColumns));
+        }
+        addOnScrollListener(mOnScrollListener);
+
+        a.recycle();
+
+        if (!mScrollBarEnabled) {
+            return;
+        }
+
+        mContainer = new LinearLayout(getContext());
+
+        setVerticalScrollBarEnabled(false);
+        setHorizontalScrollBarEnabled(false);
+
+        mScrollBarClass = context.getResources().getString(R.string.car_ui_scrollbar_component);
+    }
+
+    @Override
+    public void setLayoutManager(@Nullable LayoutManager layoutManager) {
+        // Cannot setup item decorations before stylized attributes have been read.
+        if (mIsInitialized) {
+            addItemDecorations(layoutManager);
+        }
+        super.setLayoutManager(layoutManager);
+    }
+
+    // This method should not be invoked before item decorations are initialized by the #init()
+    // method.
+    private void addItemDecorations(LayoutManager layoutManager) {
+        // remove existing Item decorations.
+        removeItemDecoration(Objects.requireNonNull(mDividerItemDecorationGrid));
+        removeItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationGrid));
+        removeItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationGrid));
+        removeItemDecoration(Objects.requireNonNull(mDividerItemDecorationLinear));
+        removeItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationLinear));
+        removeItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationLinear));
+
+        if (layoutManager instanceof GridLayoutManager) {
+            if (mEnableDividers) {
+                addItemDecoration(Objects.requireNonNull(mDividerItemDecorationGrid));
+            }
+            addItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationGrid));
+            addItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationGrid));
+            setNumOfColumns(((GridLayoutManager) layoutManager).getSpanCount());
+        } else {
+            if (mEnableDividers) {
+                addItemDecoration(Objects.requireNonNull(mDividerItemDecorationLinear));
+            }
+            addItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationLinear));
+            addItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationLinear));
+        }
+    }
+
+    /**
+     * If this view's content description is set to opt into scrolling via the rotary controller,
+     * initialize it accordingly.
+     */
+    private void initRotaryScroll() {
+        CharSequence contentDescription = getContentDescription();
+        boolean rotaryScrollEnabled = contentDescription != null
+                && (ROTARY_HORIZONTALLY_SCROLLABLE.contentEquals(contentDescription)
+                || ROTARY_VERTICALLY_SCROLLABLE.contentEquals(contentDescription));
+
+        // If rotary scrolling is enabled, set a generic motion event listener to convert
+        // SOURCE_ROTARY_ENCODER scroll events into SOURCE_MOUSE scroll events that RecyclerView
+        // knows how to handle.
+        setOnGenericMotionListener(rotaryScrollEnabled ? (v, event) -> {
+            if (event.getAction() == MotionEvent.ACTION_SCROLL) {
+                if (event.getSource() == InputDevice.SOURCE_ROTARY_ENCODER) {
+                    MotionEvent mouseEvent = MotionEvent.obtain(event);
+                    mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
+                    CarUiRecyclerView.super.onGenericMotionEvent(mouseEvent);
+                    return true;
+                }
+            }
+            return false;
+        } : null);
+
+        // If rotary scrolling is enabled, mark this view as focusable. This view will be focused
+        // when no focusable elements are visible.
+        setFocusable(rotaryScrollEnabled);
+
+        // Focus this view before descendants so that the RotaryService can focus this view when it
+        // wants to.
+        setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+
+        // Disable the default focus highlight. No highlight should appear when this view is
+        // focused.
+        setDefaultFocusHighlightEnabled(false);
+
+        // This view is a rotary container if it's not a scrollable container.
+        if (!rotaryScrollEnabled) {
+            super.setContentDescription(ROTARY_CONTAINER);
+        }
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        super.onRestoreInstanceState(state);
+
+        // If we're restoring an existing RecyclerView, consider
+        // it as having already scrolled some.
+        mHasScrolled = true;
+    }
+
+    @Override
+    public void requestLayout() {
+        super.requestLayout();
+        if (mScrollBar != null) {
+            mScrollBar.requestLayout();
+        }
+    }
+
+    /**
+     * Sets the number of columns in which grid needs to be divided.
+     */
+    public void setNumOfColumns(int numberOfColumns) {
+        mNumOfColumns = numberOfColumns;
+        if (mTopOffsetItemDecorationGrid != null) {
+            mTopOffsetItemDecorationGrid.setNumOfColumns(mNumOfColumns);
+        }
+        if (mDividerItemDecorationGrid != null) {
+            mDividerItemDecorationGrid.setNumOfColumns(mNumOfColumns);
+        }
+    }
+
+    @Override
+    public void setVisibility(int visibility) {
+        super.setVisibility(visibility);
+        mContainerVisibility = visibility;
+        if (mContainer != null) {
+            mContainer.setVisibility(visibility);
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mCarUxRestrictionsUtil.register(mListener);
+        if (mInstallingExtScrollBar || !mScrollBarEnabled) {
+            return;
+        }
+        // When CarUiRV is detached from the current parent and attached to the container with
+        // the scrollBar, onAttachedToWindow() will get called immediately when attaching the
+        // CarUiRV to the container. This flag will help us keep track of this state and avoid
+        // recursion. We also want to reset the state of this flag as soon as the container is
+        // successfully attached to the CarUiRV's original parent.
+        mInstallingExtScrollBar = true;
+        installExternalScrollBar();
+        mInstallingExtScrollBar = false;
+    }
+
+    /**
+     * This method will detach the current recycler view from its parent and attach it to the
+     * container which is a LinearLayout. Later the entire container is attached to the parent where
+     * the recycler view was set with the same layout params.
+     */
+    private void installExternalScrollBar() {
+        LayoutInflater inflater = LayoutInflater.from(getContext());
+        inflater.inflate(R.layout.car_ui_recycler_view, mContainer, true);
+        mContainer.setVisibility(mContainerVisibility);
+
+        if (mContainerPadding != null) {
+            mContainer.setPadding(mContainerPadding.left, mContainerPadding.top,
+                    mContainerPadding.right, mContainerPadding.bottom);
+        } else if (mContainerPaddingRelative != null) {
+            mContainer.setPaddingRelative(mContainerPaddingRelative.left,
+                    mContainerPaddingRelative.top, mContainerPaddingRelative.right,
+                    mContainerPaddingRelative.bottom);
+        } else {
+            mContainer.setPadding(getPaddingLeft(), /* top= */ 0,
+                    getPaddingRight(), /* bottom= */ 0);
+            setPadding(/* left= */ 0, getPaddingTop(),
+                    /* right= */ 0, getPaddingBottom());
+        }
+
+        mContainer.setLayoutParams(getLayoutParams());
+        ViewGroup parent = (ViewGroup) getParent();
+        int index = parent.indexOfChild(this);
+        parent.removeViewInLayout(this);
+
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        ((CarUiRecyclerViewContainer) Objects.requireNonNull(
+                findViewByRefId(mContainer, R.id.car_ui_recycler_view)))
+                .addRecyclerView(this, params);
+        parent.addView(mContainer, index);
+
+        createScrollBarFromConfig(findViewByRefId(mContainer, R.id.car_ui_scroll_bar));
+    }
+
+    private void createScrollBarFromConfig(View scrollView) {
+        Class<?> cls;
+        try {
+            cls = !TextUtils.isEmpty(mScrollBarClass)
+                    ? getContext().getClassLoader().loadClass(mScrollBarClass)
+                    : DefaultScrollBar.class;
+        } catch (Throwable t) {
+            throw andLog("Error loading scroll bar component: " + mScrollBarClass, t);
+        }
+        try {
+            mScrollBar = (ScrollBar) cls.getDeclaredConstructor().newInstance();
+        } catch (Throwable t) {
+            throw andLog("Error creating scroll bar component: " + mScrollBarClass, t);
+        }
+
+        mScrollBar.initialize(this, scrollView);
+
+        setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
+    }
+
+    @Override
+    public void setAlpha(float value) {
+        if (mScrollBarEnabled) {
+            mContainer.setAlpha(value);
+        } else {
+            super.setAlpha(value);
+        }
+    }
+
+    @Override
+    public ViewPropertyAnimator animate() {
+        return mScrollBarEnabled ? mContainer.animate() : super.animate();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mCarUxRestrictionsUtil.unregister(mListener);
+    }
+
+    @Override
+    public void setPadding(int left, int top, int right, int bottom) {
+        mContainerPaddingRelative = null;
+        if (mScrollBarEnabled) {
+            super.setPadding(0, top, 0, bottom);
+            if (!mHasScrolled) {
+                // If we haven't scrolled, and thus are still at the top of the screen,
+                // we should stay scrolled to the top after applying padding. Without this
+                // scroll, the padding will start scrolled offscreen. We need the padding
+                // to be onscreen to shift the content into a good visible range.
+                scrollToPosition(0);
+            }
+            mContainerPadding = new Rect(left, 0, right, 0);
+            if (mContainer != null) {
+                mContainer.setPadding(left, 0, right, 0);
+            }
+            setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
+        } else {
+            super.setPadding(left, top, right, bottom);
+        }
+    }
+
+    @Override
+    public void setPaddingRelative(int start, int top, int end, int bottom) {
+        mContainerPadding = null;
+        if (mScrollBarEnabled) {
+            super.setPaddingRelative(0, top, 0, bottom);
+            if (!mHasScrolled) {
+                // If we haven't scrolled, and thus are still at the top of the screen,
+                // we should stay scrolled to the top after applying padding. Without this
+                // scroll, the padding will start scrolled offscreen. We need the padding
+                // to be onscreen to shift the content into a good visible range.
+                scrollToPosition(0);
+            }
+            mContainerPaddingRelative = new Rect(start, 0, end, 0);
+            if (mContainer != null) {
+                mContainer.setPaddingRelative(start, 0, end, 0);
+            }
+            setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
+        } else {
+            super.setPaddingRelative(start, top, end, bottom);
+        }
+    }
+
+    /**
+     * Sets the scrollbar's padding top and bottom. This padding is applied in addition to the
+     * padding of the RecyclerView.
+     */
+    public void setScrollBarPadding(int paddingTop, int paddingBottom) {
+        if (mScrollBarEnabled) {
+            mScrollBarPaddingTop = paddingTop;
+            mScrollBarPaddingBottom = paddingBottom;
+
+            if (mScrollBar != null) {
+                mScrollBar.setPadding(paddingTop + getPaddingTop(),
+                        paddingBottom + getPaddingBottom());
+            }
+        }
+    }
+
+    /**
+     * Sets divider item decoration for linear layout.
+     */
+    public void setLinearDividerItemDecoration(boolean enableDividers) {
+        if (enableDividers) {
+            addItemDecoration(mDividerItemDecorationLinear);
+            return;
+        }
+        removeItemDecoration(mDividerItemDecorationLinear);
+    }
+
+    /**
+     * Sets divider item decoration for grid layout.
+     */
+    public void setGridDividerItemDecoration(boolean enableDividers) {
+        if (enableDividers) {
+            addItemDecoration(mDividerItemDecorationGrid);
+            return;
+        }
+        removeItemDecoration(mDividerItemDecorationGrid);
+    }
+
+    @Override
+    public void setContentDescription(CharSequence contentDescription) {
+        super.setContentDescription(contentDescription);
+        initRotaryScroll();
+    }
+
+    private static RuntimeException andLog(String msg, Throwable t) {
+        Log.e(TAG, msg, t);
+        throw new RuntimeException(msg, t);
+    }
+
+    private class UxRestrictionChangedListener implements
+            CarUxRestrictionsUtil.OnUxRestrictionsChangedListener {
+
+        @Override
+        public void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions) {
+            Adapter<?> adapter = getAdapter();
+            // If the adapter does not implement ItemCap, then the max items on it cannot be
+            // updated.
+            if (!(adapter instanceof ItemCap)) {
+                return;
+            }
+
+            int maxItems = ItemCap.UNLIMITED;
+            if ((carUxRestrictions.getActiveRestrictions()
+                    & CarUxRestrictions.UX_RESTRICTIONS_LIMIT_CONTENT)
+                    != 0) {
+                maxItems = carUxRestrictions.getMaxCumulativeContentItems();
+            }
+
+            int originalCount = adapter.getItemCount();
+            ((ItemCap) adapter).setMaxItems(maxItems);
+            int newCount = adapter.getItemCount();
+
+            if (newCount == originalCount) {
+                return;
+            }
+
+            if (newCount < originalCount) {
+                adapter.notifyItemRangeRemoved(newCount, originalCount - newCount);
+            } else {
+                adapter.notifyItemRangeInserted(originalCount, newCount - originalCount);
+            }
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java
new file mode 100644
index 0000000..2f2a5b1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview;
+
+import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+
+/** The adapter for the parent recyclerview in {@link CarUiRecyclerView} widget. */
+final class CarUiRecyclerViewAdapter
+        extends RecyclerView.Adapter<CarUiRecyclerViewAdapter.NestedRowViewHolder> {
+
+    @Override
+    public CarUiRecyclerViewAdapter.NestedRowViewHolder onCreateViewHolder(
+            ViewGroup parent, int viewType) {
+        View v =
+                LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.car_ui_recycler_view_item, parent, false);
+        return new NestedRowViewHolder(v);
+    }
+
+    // Replace the contents of a view (invoked by the layout manager). Intentionally left empty
+    // since this adapter is an empty shell for the nested recyclerview.
+    @Override
+    public void onBindViewHolder(@NonNull NestedRowViewHolder holder, int position) {
+    }
+
+    // Return the size of your data set (invoked by the layout manager)
+    @Override
+    public int getItemCount() {
+        return 1;
+    }
+
+    /** The viewHolder class for the parent recyclerview. */
+    static class NestedRowViewHolder extends RecyclerView.ViewHolder {
+        public final FrameLayout frameLayout;
+
+        NestedRowViewHolder(View view) {
+            super(view);
+            frameLayout = findViewByRefId(view, R.id.nested_recycler_view_layout);
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java
new file mode 100644
index 0000000..4e9dc55
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+/**
+ * Container that contains the scrollbar and RecyclerView when scrollbar is enabled.
+ *
+ * This container is required to expose addViewInLayout such that the scrollbar and be added without
+ * triggering multiple invalidate and relayout calls.
+ */
+public class CarUiRecyclerViewContainer extends FrameLayout {
+
+    public CarUiRecyclerViewContainer(Context context) {
+        super(context);
+    }
+
+    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    /**
+     * Adds the recyclerview using addViewInLayout so that invalidate and relayout calls are not
+     * triggered.
+     */
+    void addRecyclerView(View view, LayoutParams layoutParams) {
+        addViewInLayout(view, 0, layoutParams);
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSmoothScroller.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiSmoothScroller.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSmoothScroller.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiSmoothScroller.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiSnapHelper.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiSnapHelper.java
new file mode 100644
index 0000000..fd532b5
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiSnapHelper.java
@@ -0,0 +1,499 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview;
+
+import android.content.Context;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearSnapHelper;
+import androidx.recyclerview.widget.OrientationHelper;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.LayoutManager;
+
+import java.util.Objects;
+
+/**
+ * Inspired by {@link androidx.car.widget.PagedSnapHelper}
+ *
+ * <p>Extension of a {@link LinearSnapHelper} that will snap to the start of the target child view
+ * to the start of the attached {@link RecyclerView}. The start of the view is defined as the top if
+ * the RecyclerView is scrolling vertically; it is defined as the left (or right if RTL) if the
+ * RecyclerView is scrolling horizontally.
+ */
+public class CarUiSnapHelper extends LinearSnapHelper {
+    /**
+     * The percentage of a View that needs to be completely visible for it to be a viable snap
+     * target.
+     */
+    private static final float VIEW_VISIBLE_THRESHOLD = 0.5f;
+
+    /**
+     * When a View is longer than containing RecyclerView, the percentage of the end of this View
+     * that needs to be completely visible to prevent the rest of views to be a viable snap target.
+     *
+     * <p>In other words, if a longer-than-screen View takes more than threshold screen space on its
+     * end, do not snap to any View.
+     */
+    private static final float LONG_ITEM_END_VISIBLE_THRESHOLD = 0.3f;
+
+    private final Context mContext;
+    private RecyclerView mRecyclerView;
+
+    public CarUiSnapHelper(Context context) {
+        mContext = context;
+    }
+
+    // Orientation helpers are lazily created per LayoutManager.
+    @Nullable
+    private OrientationHelper mVerticalHelper;
+    @Nullable
+    private OrientationHelper mHorizontalHelper;
+
+    @Override
+    public int[] calculateDistanceToFinalSnap(
+            @NonNull LayoutManager layoutManager, @NonNull View targetView) {
+        int[] out = new int[2];
+
+        // Don't snap when not in touch mode, i.e. when using rotary.
+        if (!mRecyclerView.isInTouchMode()) {
+            return out;
+        }
+
+        if (layoutManager.canScrollHorizontally()) {
+            out[0] = distanceToTopMargin(targetView, getHorizontalHelper(layoutManager));
+        }
+
+        if (layoutManager.canScrollVertically()) {
+            out[1] = distanceToTopMargin(targetView, getVerticalHelper(layoutManager));
+        }
+
+        return out;
+    }
+
+    /**
+     * Finds the view to snap to. The view to snap to is the child of the LayoutManager that is
+     * closest to the start of the RecyclerView. The "start" depends on if the LayoutManager
+     * is scrolling horizontally or vertically. If it is horizontally scrolling, then the
+     * start is the view on the left (right if RTL). Otherwise, it is the top-most view.
+     *
+     * @param layoutManager The current {@link LayoutManager} for the attached RecyclerView.
+     * @return The View closest to the start of the RecyclerView. Returns {@code null}when:
+     * <ul>
+     *     <li>there is no item; or
+     *     <li>no visible item can fully fit in the containing RecyclerView; or
+     *     <li>an item longer than containing RecyclerView is about to scroll out.
+     * </ul>
+     */
+    @Override
+    @Nullable
+    public View findSnapView(LayoutManager layoutManager) {
+        int childCount = layoutManager.getChildCount();
+        if (childCount == 0) {
+            return null;
+        }
+
+        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
+
+        // If there's only one child, then that will be the snap target.
+        if (childCount == 1) {
+            View firstChild = layoutManager.getChildAt(0);
+            return isValidSnapView(firstChild, orientationHelper) ? firstChild : null;
+        }
+
+        if (mRecyclerView == null) {
+            return null;
+        }
+
+        // If the top child view is longer than the RecyclerView (long item), and it's not yet
+        // scrolled out - meaning the screen it takes up is more than threshold,
+        // do not snap to any view.
+        // This way avoids next View snapping to top "pushes" out the end of a long item.
+        View firstChild = mRecyclerView.getChildAt(0);
+        if (firstChild.getHeight() > mRecyclerView.getHeight()
+                // Long item start is scrolled past screen;
+                && orientationHelper.getDecoratedStart(firstChild) < 0
+                // and it takes up more than threshold screen size.
+                && orientationHelper.getDecoratedEnd(firstChild) > (
+                mRecyclerView.getHeight() * LONG_ITEM_END_VISIBLE_THRESHOLD)) {
+            return null;
+        }
+
+        @NonNull View lastVisibleChild = Objects.requireNonNull(
+                layoutManager.getChildAt(childCount - 1));
+
+        // Check if the last child visible is the last item in the list.
+        boolean lastItemVisible =
+                layoutManager.getPosition(lastVisibleChild) == layoutManager.getItemCount() - 1;
+
+        // If it is, then check how much of that view is visible.
+        float lastItemPercentageVisible = lastItemVisible
+                ? getPercentageVisible(lastVisibleChild, orientationHelper) : 0;
+
+        View closestChild = null;
+        int closestDistanceToStart = Integer.MAX_VALUE;
+        float closestPercentageVisible = 0.f;
+
+        // Iterate to find the child closest to the top and more than half way visible.
+        for (int i = 0; i < childCount; i++) {
+            View child = layoutManager.getChildAt(i);
+            int startOffset = orientationHelper.getDecoratedStart(child);
+
+            if (Math.abs(startOffset) < closestDistanceToStart) {
+                float percentageVisible = getPercentageVisible(child, orientationHelper);
+
+                if (percentageVisible > VIEW_VISIBLE_THRESHOLD
+                        && percentageVisible > closestPercentageVisible) {
+                    closestDistanceToStart = startOffset;
+                    closestChild = child;
+                    closestPercentageVisible = percentageVisible;
+                }
+            }
+        }
+
+        View childToReturn = closestChild;
+
+        // If closestChild is null, then that means we were unable to find a closest child that
+        // is over the VIEW_VISIBLE_THRESHOLD. This could happen if the views are larger than
+        // the given area. In this case, consider returning the lastVisibleChild so that the screen
+        // scrolls. Also, check if the last item should be displayed anyway if it is mostly visible.
+        if ((childToReturn == null
+                || (lastItemVisible && lastItemPercentageVisible > closestPercentageVisible))) {
+            childToReturn = lastVisibleChild;
+        }
+
+        // Return null if the childToReturn is not valid. This allows the user to scroll freely
+        // with no snapping. This can allow them to see the entire view.
+        return isValidSnapView(childToReturn, orientationHelper) ? childToReturn : null;
+    }
+
+    private static int distanceToTopMargin(@NonNull View targetView, OrientationHelper helper) {
+        final int childTop = helper.getDecoratedStart(targetView);
+        final int containerTop = helper.getStartAfterPadding();
+        return childTop - containerTop;
+    }
+
+    /**
+     * Finds the view to snap to. The view to snap to is the child of the LayoutManager that is
+     * closest to the start of the RecyclerView. The "start" depends on if the LayoutManager is
+     * scrolling horizontally or vertically. If it is horizontally scrolling, then the start is the
+     * view on the left (right if RTL). Otherwise, it is the top-most view.
+     *
+     * @param layoutManager The current {@link RecyclerView.LayoutManager} for the attached
+     *                      RecyclerView.
+     * @return The View closest to the start of the RecyclerView.
+     */
+    private static View findTopView(LayoutManager layoutManager, OrientationHelper helper) {
+        int childCount = layoutManager.getChildCount();
+        if (childCount == 0) {
+            return null;
+        }
+
+        View closestChild = null;
+        int absClosest = Integer.MAX_VALUE;
+
+        for (int i = 0; i < childCount; i++) {
+            View child = layoutManager.getChildAt(i);
+            if (child == null) {
+                continue;
+            }
+            int absDistance = Math.abs(distanceToTopMargin(child, helper));
+
+            /* if child top is closer than previous closest, set it as closest */
+            if (absDistance < absClosest) {
+                absClosest = absDistance;
+                closestChild = child;
+            }
+        }
+        return closestChild;
+    }
+
+    /**
+     * Returns whether or not the given View is a valid snapping view. A view is considered valid
+     * for snapping if it can fit entirely within the height of the RecyclerView it is contained
+     * within.
+     *
+     * <p>If the view is larger than the RecyclerView, then it might not want to be snapped to
+     * to allow the user to scroll and see the rest of the View.
+     *
+     * @param view   The view to determine the snapping potential.
+     * @param helper The {@link OrientationHelper} associated with the current RecyclerView.
+     * @return {@code true} if the given view is a valid snapping view; {@code false} otherwise.
+     */
+    private static boolean isValidSnapView(View view, OrientationHelper helper) {
+        return helper.getDecoratedMeasurement(view) <= helper.getTotalSpace();
+    }
+
+    /**
+     * Returns the percentage of the given view that is visible, relative to its containing
+     * RecyclerView.
+     *
+     * @param view   The View to get the percentage visible of.
+     * @param helper An {@link OrientationHelper} to aid with calculation.
+     * @return A float indicating the percentage of the given view that is visible.
+     */
+    static float getPercentageVisible(View view, OrientationHelper helper) {
+        int start = helper.getStartAfterPadding();
+        int end = helper.getEndAfterPadding();
+
+        int viewStart = helper.getDecoratedStart(view);
+        int viewEnd = helper.getDecoratedEnd(view);
+
+        if (viewStart >= start && viewEnd <= end) {
+            // The view is within the bounds of the RecyclerView, so it's fully visible.
+            return 1.f;
+        } else if (viewEnd <= start) {
+            // The view is above the visible area of the RecyclerView.
+            return 0;
+        } else if (viewStart >= end) {
+            // The view is below the visible area of the RecyclerView.
+            return 0;
+        } else if (viewStart <= start && viewEnd >= end) {
+            // The view is larger than the height of the RecyclerView.
+            return ((float) end - start) / helper.getDecoratedMeasurement(view);
+        } else if (viewStart < start) {
+            // The view is above the start of the RecyclerView.
+            return ((float) viewEnd - start) / helper.getDecoratedMeasurement(view);
+        } else {
+            // The view is below the end of the RecyclerView.
+            return ((float) end - viewStart) / helper.getDecoratedMeasurement(view);
+        }
+    }
+
+    @Override
+    public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
+        super.attachToRecyclerView(recyclerView);
+        mRecyclerView = recyclerView;
+    }
+
+    /**
+     * Returns a scroller specific to this {@code PagedSnapHelper}. This scroller is used for all
+     * smooth scrolling operations, including flings.
+     *
+     * @param layoutManager The {@link LayoutManager} associated with the attached
+     *                      {@link RecyclerView}.
+     * @return a {@link RecyclerView.SmoothScroller} which will handle the scrolling.
+     */
+    @Override
+    protected RecyclerView.SmoothScroller createScroller(@NonNull LayoutManager layoutManager) {
+        return new CarUiSmoothScroller(mContext);
+    }
+
+    /**
+     * Calculate the estimated scroll distance in each direction given velocities on both axes.
+     * This method will clamp the maximum scroll distance so that a single fling will never scroll
+     * more than one page.
+     *
+     * @param velocityX Fling velocity on the horizontal axis.
+     * @param velocityY Fling velocity on the vertical axis.
+     * @return An array holding the calculated distances in x and y directions respectively.
+     */
+    @Override
+    public int[] calculateScrollDistance(int velocityX, int velocityY) {
+        int[] outDist = super.calculateScrollDistance(velocityX, velocityY);
+
+        if (mRecyclerView == null) {
+            return outDist;
+        }
+
+        LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+        if (layoutManager == null || layoutManager.getChildCount() == 0) {
+            return outDist;
+        }
+
+        int lastChildPosition = isAtEnd(layoutManager) ? 0 : layoutManager.getChildCount() - 1;
+
+        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
+        @NonNull View lastChild = Objects.requireNonNull(
+                layoutManager.getChildAt(lastChildPosition));
+        float percentageVisible = getPercentageVisible(lastChild, orientationHelper);
+
+        int maxDistance = layoutManager.getHeight();
+        if (percentageVisible > 0.f) {
+            // The max and min distance is the total height of the RecyclerView minus the height of
+            // the last child. This ensures that each scroll will never scroll more than a single
+            // page on the RecyclerView. That is, the max scroll will make the last child the
+            // first child and vice versa when scrolling the opposite way.
+            maxDistance -= layoutManager.getDecoratedMeasuredHeight(lastChild);
+        }
+
+        int minDistance = -maxDistance;
+
+        outDist[0] = clamp(outDist[0], minDistance, maxDistance);
+        outDist[1] = clamp(outDist[1], minDistance, maxDistance);
+
+        return outDist;
+    }
+
+    /**
+     * Estimates a position to which CarUiSnapHelper will try to snap to for a requested scroll
+     * distance.
+     *
+     * @param helper         The {@link OrientationHelper} that is created from the LayoutManager.
+     * @param scrollDistance The intended scroll distance.
+     *
+     * @return The diff between the target snap position and the current position.
+     */
+    public int estimateNextPositionDiffForScrollDistance(OrientationHelper helper,
+            int scrollDistance) {
+        float distancePerChild = computeDistancePerChild(helper.getLayoutManager(), helper);
+        if (distancePerChild <= 0) {
+            return 0;
+        }
+        return (int) Math.round(scrollDistance / distancePerChild);
+    }
+
+    /**
+     * This method is taken verbatim from the [androidx] {@link LinearSnapHelper} private method
+     * implementation.
+     *
+     * Computes an average pixel value to pass a single child.
+     * <p>
+     * Returns a negative value if it cannot be calculated.
+     *
+     * @param layoutManager The {@link RecyclerView.LayoutManager} associated with the attached
+     *                      {@link RecyclerView}.
+     * @param helper        The relevant {@link OrientationHelper} for the attached
+     *                      {@link RecyclerView.LayoutManager}.
+     *
+     * @return A float value that is the average number of pixels needed to scroll by one view in
+     * the relevant direction.
+     */
+    float computeDistancePerChild(RecyclerView.LayoutManager layoutManager,
+            OrientationHelper helper) {
+        View minPosView = null;
+        View maxPosView = null;
+        int minPos = Integer.MAX_VALUE;
+        int maxPos = Integer.MIN_VALUE;
+        int childCount = layoutManager.getChildCount();
+        if (childCount == 0) {
+            return 1;
+        }
+
+        for (int i = 0; i < childCount; i++) {
+            View child = layoutManager.getChildAt(i);
+            final int pos = layoutManager.getPosition(child);
+            if (pos == RecyclerView.NO_POSITION) {
+                continue;
+            }
+            if (pos < minPos) {
+                minPos = pos;
+                minPosView = child;
+            }
+            if (pos > maxPos) {
+                maxPos = pos;
+                maxPosView = child;
+            }
+        }
+        if (minPosView == null || maxPosView == null) {
+            return 1;
+        }
+        int start = Math.min(helper.getDecoratedStart(minPosView),
+                helper.getDecoratedStart(maxPosView));
+        int end = Math.max(helper.getDecoratedEnd(minPosView),
+                helper.getDecoratedEnd(maxPosView));
+        int distance = end - start;
+        if (distance == 0) {
+            return 0;
+        }
+        return 1f * distance / ((maxPos - minPos) + 1);
+    }
+
+    /**
+     * Returns {@code true} if the RecyclerView is completely displaying the first item.
+     */
+    public boolean isAtStart(@Nullable LayoutManager layoutManager) {
+        if (layoutManager == null || layoutManager.getChildCount() == 0) {
+            return true;
+        }
+
+        @NonNull View firstChild = Objects.requireNonNull(layoutManager.getChildAt(0));
+        OrientationHelper orientationHelper =
+                layoutManager.canScrollVertically() ? getVerticalHelper(layoutManager)
+                        : getHorizontalHelper(layoutManager);
+
+        // Check that the first child is completely visible and is the first item in the list.
+        return orientationHelper.getDecoratedStart(firstChild)
+                >= orientationHelper.getStartAfterPadding() && layoutManager.getPosition(firstChild)
+                == 0;
+    }
+
+    /**
+     * Returns {@code true} if the RecyclerView is completely displaying the last item.
+     */
+    public boolean isAtEnd(@Nullable LayoutManager layoutManager) {
+        if (layoutManager == null || layoutManager.getChildCount() == 0) {
+            return true;
+        }
+
+        int childCount = layoutManager.getChildCount();
+        OrientationHelper orientationHelper =
+                layoutManager.canScrollVertically() ? getVerticalHelper(layoutManager)
+                        : getHorizontalHelper(layoutManager);
+
+        @NonNull View lastVisibleChild = Objects.requireNonNull(
+                layoutManager.getChildAt(childCount - 1));
+
+        // The list has reached the bottom if the last child that is visible is the last item
+        // in the list and it's fully shown.
+        return layoutManager.getPosition(lastVisibleChild) == (layoutManager.getItemCount() - 1)
+                && layoutManager.getDecoratedBottom(lastVisibleChild)
+                <= orientationHelper.getEndAfterPadding();
+    }
+
+    /**
+     * Returns an {@link OrientationHelper} that corresponds to the current scroll direction of the
+     * given {@link LayoutManager}.
+     */
+    @NonNull
+    private OrientationHelper getOrientationHelper(@NonNull LayoutManager layoutManager) {
+        return layoutManager.canScrollVertically()
+                ? getVerticalHelper(layoutManager)
+                : getHorizontalHelper(layoutManager);
+    }
+
+    @NonNull
+    private OrientationHelper getVerticalHelper(@NonNull LayoutManager layoutManager) {
+        if (mVerticalHelper == null || mVerticalHelper.getLayoutManager() != layoutManager) {
+            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
+        }
+        return mVerticalHelper;
+    }
+
+    @NonNull
+    private OrientationHelper getHorizontalHelper(@NonNull LayoutManager layoutManager) {
+        if (mHorizontalHelper == null || mHorizontalHelper.getLayoutManager() != layoutManager) {
+            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
+        }
+        return mHorizontalHelper;
+    }
+
+    /**
+     * Ensures that the given value falls between the range given by the min and max values. This
+     * method does not check that the min value is greater than or equal to the max value. If the
+     * parameters are not well-formed, this method's behavior is undefined.
+     *
+     * @param value The value to clamp.
+     * @param min   The minimum value the given value can be.
+     * @param max   The maximum value the given value can be.
+     * @return A number that falls between {@code min} or {@code max} or one of those values if the
+     * given value is less than or greater than {@code min} and {@code max} respectively.
+     */
+    private static int clamp(int value, int min, int max) {
+        return Math.max(min, Math.min(max, value));
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/ContentLimiting.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ContentLimiting.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/ContentLimiting.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ContentLimiting.java
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/ContentLimitingAdapter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ContentLimitingAdapter.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/ContentLimitingAdapter.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ContentLimitingAdapter.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DefaultScrollBar.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DefaultScrollBar.java
new file mode 100644
index 0000000..d44274c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DefaultScrollBar.java
@@ -0,0 +1,463 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview;
+
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+
+import android.content.res.Resources;
+import android.os.Handler;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.OrientationHelper;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+
+/**
+ * The default scroll bar widget for the {@link CarUiRecyclerView}.
+ *
+ * <p>Inspired by {@link androidx.car.widget.PagedListView}. Most pagination and scrolling logic
+ * has been ported from the PLV with minor updates.
+ */
+class DefaultScrollBar implements ScrollBar {
+
+
+    private float mButtonDisabledAlpha;
+    private CarUiSnapHelper mSnapHelper;
+
+    private View mScrollView;
+    private View mScrollTrack;
+    private View mScrollThumb;
+    private View mUpButton;
+    private View mDownButton;
+    private int mScrollbarThumbMinHeight;
+
+    private RecyclerView mRecyclerView;
+
+    private final Interpolator mPaginationInterpolator = new AccelerateDecelerateInterpolator();
+
+    private final Handler mHandler = new Handler();
+
+    private OrientationHelper mOrientationHelper;
+
+    private OnContinuousScrollListener mPageUpOnContinuousScrollListener;
+    private OnContinuousScrollListener mPageDownOnContinuousScrollListener;
+
+    @Override
+    public void initialize(RecyclerView rv, View scrollView) {
+        mRecyclerView = rv;
+
+        mScrollView = scrollView;
+
+        Resources res = rv.getContext().getResources();
+
+        mButtonDisabledAlpha = CarUiUtils.getFloat(res, R.dimen.car_ui_button_disabled_alpha);
+        mScrollbarThumbMinHeight = rv.getContext().getResources()
+                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_min_thumb_height);
+
+        getRecyclerView().addOnScrollListener(mRecyclerViewOnScrollListener);
+        getRecyclerView().getRecycledViewPool().setMaxRecycledViews(0, 12);
+
+        mUpButton = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_page_up);
+        View.OnClickListener paginateUpButtonOnClickListener = v -> pageUp();
+        mUpButton.setOnClickListener(paginateUpButtonOnClickListener);
+        mPageUpOnContinuousScrollListener = new OnContinuousScrollListener(rv.getContext(),
+                paginateUpButtonOnClickListener);
+        mUpButton.setOnTouchListener(mPageUpOnContinuousScrollListener);
+
+
+        mDownButton = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_page_down);
+        View.OnClickListener paginateDownButtonOnClickListener = v -> pageDown();
+        mDownButton.setOnClickListener(paginateDownButtonOnClickListener);
+        mPageDownOnContinuousScrollListener = new OnContinuousScrollListener(rv.getContext(),
+                paginateDownButtonOnClickListener);
+        mDownButton.setOnTouchListener(mPageDownOnContinuousScrollListener);
+
+        mScrollTrack = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_track);
+        mScrollThumb = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_thumb);
+
+        mSnapHelper = new CarUiSnapHelper(rv.getContext());
+        getRecyclerView().setOnFlingListener(null);
+        mSnapHelper.attachToRecyclerView(getRecyclerView());
+
+        // enables fast scrolling.
+        FastScroller fastScroller = new FastScroller(mRecyclerView, mScrollTrack, mScrollView);
+        fastScroller.enable();
+
+        mScrollView.setVisibility(View.INVISIBLE);
+        mScrollView.addOnLayoutChangeListener(
+                (View v,
+                        int left,
+                        int top,
+                        int right,
+                        int bottom,
+                        int oldLeft,
+                        int oldTop,
+                        int oldRight,
+                        int oldBottom) -> mHandler.post(this::updatePaginationButtons));
+    }
+
+    public RecyclerView getRecyclerView() {
+        return mRecyclerView;
+    }
+
+    @Override
+    public void requestLayout() {
+        mScrollView.requestLayout();
+    }
+
+    @Override
+    public void setPadding(int paddingStart, int paddingEnd) {
+        mScrollView.setPadding(mScrollView.getPaddingLeft(), paddingStart,
+                mScrollView.getPaddingRight(), paddingEnd);
+    }
+
+    /**
+     * Sets whether or not the up button on the scroll bar is clickable.
+     *
+     * @param enabled {@code true} if the up button is enabled.
+     */
+    private void setUpEnabled(boolean enabled) {
+        // If the button is held down the button is disabled, the MotionEvent.ACTION_UP event on
+        // button release will not be sent to cancel pending scrolls. Manually cancel any pending
+        // scroll.
+        if (!enabled) {
+            mPageUpOnContinuousScrollListener.cancelPendingScroll();
+        }
+
+        mUpButton.setEnabled(enabled);
+        mUpButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
+    }
+
+    /**
+     * Sets whether or not the down button on the scroll bar is clickable.
+     *
+     * @param enabled {@code true} if the down button is enabled.
+     */
+    private void setDownEnabled(boolean enabled) {
+        // If the button is held down the button is disabled, the MotionEvent.ACTION_UP event on
+        // button release will not be sent to cancel pending scrolls. Manually cancel any pending
+        // scroll.
+        if (!enabled) {
+            mPageDownOnContinuousScrollListener.cancelPendingScroll();
+        }
+
+        mDownButton.setEnabled(enabled);
+        mDownButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
+    }
+
+    /**
+     * Returns whether or not the down button on the scroll bar is clickable.
+     *
+     * @return {@code true} if the down button is enabled. {@code false} otherwise.
+     */
+    private boolean isDownEnabled() {
+        return mDownButton.isEnabled();
+    }
+
+    /**
+     * Sets the range, offset and extent of the scroll bar. The range represents the size of a
+     * container for the scrollbar thumb; offset is the distance from the start of the container to
+     * where the thumb should be; and finally, extent is the size of the thumb.
+     *
+     * <p>These values can be expressed in arbitrary units, so long as they share the same units.
+     * The values should also be positive.
+     *
+     * @param range  The range of the scrollbar's thumb
+     * @param offset The offset of the scrollbar's thumb
+     * @param extent The extent of the scrollbar's thumb
+     */
+    private void setParameters(
+            @IntRange(from = 0) int range,
+            @IntRange(from = 0) int offset,
+            @IntRange(from = 0) int extent) {
+        // Not laid out yet, so values cannot be calculated.
+        if (!mScrollView.isLaidOut()) {
+            return;
+        }
+
+        // If the scroll bars aren't visible, then no need to update.
+        if (mScrollView.getVisibility() == View.GONE || range == 0) {
+            return;
+        }
+
+        int thumbLength = calculateScrollThumbLength(range, extent);
+        int thumbOffset = calculateScrollThumbOffset(range, offset, thumbLength);
+
+        // Sets the size of the thumb and request a redraw if needed.
+        ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
+
+        if (lp.height != thumbLength) {
+            lp.height = thumbLength;
+            mScrollThumb.requestLayout();
+        }
+
+        moveY(mScrollThumb, thumbOffset);
+    }
+
+    /**
+     * Calculates and returns how big the scroll bar thumb should be based on the given range and
+     * extent.
+     *
+     * @param range  The total amount of space the scroll bar is allowed to roam over.
+     * @param extent The amount of space that the scroll bar takes up relative to the range.
+     * @return The height of the scroll bar thumb in pixels.
+     */
+    private int calculateScrollThumbLength(int range, int extent) {
+        // Scale the length by the available space that the thumb can fill.
+        return Math.max(Math.round(((float) extent / range) * mScrollTrack.getHeight()),
+                mScrollbarThumbMinHeight);
+    }
+
+    /**
+     * Calculates and returns how much the scroll thumb should be offset from the top of where it
+     * has been laid out.
+     *
+     * @param range       The total amount of space the scroll bar is allowed to roam over.
+     * @param offset      The amount the scroll bar should be offset, expressed in the same units as
+     *                    the given range.
+     * @param thumbLength The current length of the thumb in pixels.
+     * @return The amount the thumb should be offset in pixels.
+     */
+    private int calculateScrollThumbOffset(int range, int offset, int thumbLength) {
+        // Ensure that if the user has reached the bottom of the list, then the scroll bar is
+        // aligned to the bottom as well. Otherwise, scale the offset appropriately.
+        // This offset will be a value relative to the parent of this scrollbar, so start by where
+        // the top of scrollbar track is.
+        return mScrollTrack.getTop()
+                + (isDownEnabled()
+                ? Math.round(((float) offset / range) * (mScrollTrack.getHeight() - thumbLength))
+                : mScrollTrack.getHeight() - thumbLength);
+    }
+
+    /**
+     * Moves the given view to the specified 'y' position.
+     */
+    private void moveY(final View view, float newPosition) {
+        view.animate()
+                .y(newPosition)
+                .setDuration(/* duration= */ 0)
+                .setInterpolator(mPaginationInterpolator)
+                .start();
+    }
+
+    private final RecyclerView.OnScrollListener mRecyclerViewOnScrollListener =
+            new RecyclerView.OnScrollListener() {
+                @Override
+                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+                    updatePaginationButtons();
+                }
+            };
+
+    private OrientationHelper getOrientationHelper(RecyclerView.LayoutManager layoutManager) {
+        if (mOrientationHelper == null || mOrientationHelper.getLayoutManager() != layoutManager) {
+            // CarUiRecyclerView is assumed to be a list that always vertically scrolls.
+            mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
+        }
+        return mOrientationHelper;
+    }
+
+    /**
+     * Scrolls the contents of the RecyclerView up a page. A page is defined as the height of the
+     * {@code CarUiRecyclerView}.
+     *
+     * <p>The resulting first item in the list will be snapped to so that it is completely visible.
+     * If this is not possible due to the first item being taller than the containing {@code
+     * CarUiRecyclerView}, then the snapping will not occur.
+     */
+    void pageUp() {
+        int currentOffset = getRecyclerView().computeVerticalScrollOffset();
+        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
+        if (layoutManager == null || layoutManager.getChildCount() == 0 || currentOffset == 0) {
+            return;
+        }
+
+        // Use OrientationHelper to calculate scroll distance in order to match snapping behavior.
+        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
+        int screenSize = orientationHelper.getTotalSpace();
+        int scrollDistance = screenSize;
+        boolean isPageUpOverLongItem;
+        // The iteration order matters. In case where there are 2 items longer than screen size, we
+        // want to focus on upcoming view.
+        for (int i = 0; i < layoutManager.getChildCount(); i++) {
+            /*
+             * We treat child View longer than screen size differently:
+             * 1) When it enters screen, next pageUp will align its bottom with parent bottom;
+             * 2) When it leaves screen, next pageUp will align its top with parent top.
+             */
+            View child = layoutManager.getChildAt(i);
+            if (child.getHeight() > screenSize) {
+                if (orientationHelper.getDecoratedEnd(child) < screenSize) {
+                    // Child view bottom is entering screen. Align its bottom with parent bottom.
+                    scrollDistance = screenSize - orientationHelper.getDecoratedEnd(child);
+                } else if (-screenSize < orientationHelper.getDecoratedStart(child)
+                        && orientationHelper.getDecoratedStart(child) < 0) {
+                    // Child view top is about to enter screen - its distance to parent top
+                    // is less than a full scroll. Align child top with parent top.
+                    scrollDistance = Math.abs(orientationHelper.getDecoratedStart(child));
+                }
+
+                // There can be two items that are longer than the screen. We stop at the first one.
+                // This is affected by the iteration order.
+                // Distance should always be positive. Negate its value to scroll up.
+                mRecyclerView.smoothScrollBy(0, -scrollDistance);
+                return;
+            }
+        }
+
+        int nextPos = mSnapHelper.estimateNextPositionDiffForScrollDistance(orientationHelper,
+                -scrollDistance);
+        View currentPosView = getFirstFullyVisibleChild(orientationHelper);
+        int currentPos = currentPosView != null ? mRecyclerView.getLayoutManager().getPosition(
+                currentPosView) : 0;
+        mRecyclerView.smoothScrollToPosition(Math.max(0, currentPos + nextPos));
+    }
+
+    private View getFirstFullyVisibleChild(OrientationHelper helper) {
+        for (int i = 0; i < getRecyclerView().getChildCount(); i++) {
+            View child = getRecyclerView().getChildAt(i);
+            if (CarUiSnapHelper.getPercentageVisible(child, helper) == 1f) {
+                return getRecyclerView().getChildAt(i);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Scrolls the contents of the RecyclerView down a page. A page is defined as the height of the
+     * {@code CarUiRecyclerView}.
+     *
+     * <p>This method will attempt to bring the last item in the list as the first item. If the
+     * current first item in the list is taller than the {@code CarUiRecyclerView}, then it will be
+     * scrolled the length of a page, but not snapped to.
+     */
+    void pageDown() {
+        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
+        if (layoutManager == null || layoutManager.getChildCount() == 0) {
+            return;
+        }
+
+        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
+        int screenSize = orientationHelper.getTotalSpace();
+        int scrollDistance = screenSize;
+
+        // If the last item is partially visible, page down should bring it to the top.
+        View lastChild = layoutManager.getChildAt(layoutManager.getChildCount() - 1);
+        if (layoutManager.isViewPartiallyVisible(lastChild,
+                /* completelyVisible= */ false, /* acceptEndPointInclusion= */ false)) {
+            scrollDistance = orientationHelper.getDecoratedStart(lastChild)
+                    - orientationHelper.getStartAfterPadding();
+            if (scrollDistance <= 0) {
+                // - Scroll value is zero if the top of last item is aligned with top of the screen;
+                // - Scroll value can be negative if the child is longer than the screen size and
+                //   the visible area of the screen does not show the start of the child.
+                // Scroll to the next screen in both cases.
+                scrollDistance = screenSize;
+            }
+        }
+
+        // The iteration order matters. In case where there are 2 items longer than screen size, we
+        // want to focus on upcoming view (the one at the bottom of screen).
+        for (int i = layoutManager.getChildCount() - 1; i >= 0; i--) {
+            /* We treat child View longer than screen size differently:
+             * 1) When it enters screen, next pageDown will align its top with parent top;
+             * 2) When it leaves screen, next pageDown will align its bottom with parent bottom.
+             */
+            View child = layoutManager.getChildAt(i);
+            if (child.getHeight() > screenSize) {
+                if (orientationHelper.getDecoratedStart(child)
+                        - orientationHelper.getStartAfterPadding() > 0) {
+                    // Child view top is entering screen. Align its top with parent top.
+                    scrollDistance = orientationHelper.getDecoratedStart(lastChild)
+                            - orientationHelper.getStartAfterPadding();
+                } else if (screenSize < orientationHelper.getDecoratedEnd(child)
+                        && orientationHelper.getDecoratedEnd(child) < 2 * screenSize) {
+                    // Child view bottom is about to enter screen - its distance to parent bottom
+                    // is less than a full scroll. Align child bottom with parent bottom.
+                    scrollDistance = orientationHelper.getDecoratedEnd(child) - screenSize;
+                }
+                // There can be two items that are longer than the screen. We stop at the first one.
+                // This is affected by the iteration order.
+                break;
+            }
+        }
+
+        mRecyclerView.smoothScrollBy(0, scrollDistance);
+    }
+
+    /**
+     * Determines if scrollbar should be visible or not and shows/hides it accordingly. If this is
+     * being called as a result of adapter changes, it should be called after the new layout has
+     * been calculated because the method of determining scrollbar visibility uses the current
+     * layout. If this is called after an adapter change but before the new layout, the visibility
+     * determination may not be correct.
+     */
+    private void updatePaginationButtons() {
+
+        boolean isAtStart = isAtStart();
+        boolean isAtEnd = isAtEnd();
+        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
+
+        // enable/disable the button before the view is shown. So there is no flicker.
+        setUpEnabled(!isAtStart);
+        setDownEnabled(!isAtEnd);
+
+        if ((isAtStart && isAtEnd) || layoutManager == null || layoutManager.getItemCount() == 0) {
+            mScrollView.setVisibility(View.INVISIBLE);
+        } else {
+            mScrollView.setVisibility(View.VISIBLE);
+        }
+
+        if (layoutManager == null) {
+            return;
+        }
+
+        if (layoutManager.canScrollVertically()) {
+            setParameters(
+                    getRecyclerView().computeVerticalScrollRange(),
+                    getRecyclerView().computeVerticalScrollOffset(),
+                    getRecyclerView().computeVerticalScrollExtent());
+        } else {
+            setParameters(
+                    getRecyclerView().computeHorizontalScrollRange(),
+                    getRecyclerView().computeHorizontalScrollOffset(),
+                    getRecyclerView().computeHorizontalScrollExtent());
+        }
+
+        mScrollView.invalidate();
+    }
+
+    /**
+     * Returns {@code true} if the RecyclerView is completely displaying the first item.
+     */
+    boolean isAtStart() {
+        return mSnapHelper.isAtStart(getRecyclerView().getLayoutManager());
+    }
+
+    /**
+     * Returns {@code true} if the RecyclerView is completely displaying the last item.
+     */
+    boolean isAtEnd() {
+        return mSnapHelper.isAtEnd(getRecyclerView().getLayoutManager());
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/FastScroller.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/FastScroller.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/FastScroller.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/FastScroller.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/OnContinuousScrollListener.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/OnContinuousScrollListener.java
new file mode 100644
index 0000000..48570c6
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/OnContinuousScrollListener.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 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.car.ui.recyclerview;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnTouchListener;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.ui.R;
+
+/**
+ * A class, that can be used as a TouchListener on any view (e.g. a Button). It periodically calls
+ * the provided clickListener. The first callback is fired after the initial Delay, and subsequent
+ * ones after the defined interval.
+ */
+public class OnContinuousScrollListener implements OnTouchListener {
+
+    private final Handler mHandler = new Handler();
+    private final int mInitialDelay;
+    private final int mRepeatInterval;
+    private final OnClickListener mOnClickListener;
+    private View mTouchedView;
+    private boolean mIsLongPressed;
+
+    /**
+     * Notifies listener and self schedules to be re-run at next callback interval.
+     */
+    private final Runnable mPeriodicRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mTouchedView.isEnabled()) {
+                mHandler.postDelayed(this, mRepeatInterval);
+                mOnClickListener.onClick(mTouchedView);
+                mIsLongPressed = true;
+            } else {
+                mIsLongPressed = false;
+            }
+        }
+    };
+
+    /**
+     * @param clickListener The OnClickListener, that will be called periodically
+     */
+    public OnContinuousScrollListener(@NonNull Context context,
+            @NonNull OnClickListener clickListener) {
+        this.mInitialDelay = context.getResources().getInteger(
+                R.integer.car_ui_scrollbar_longpress_initial_delay);
+        this.mRepeatInterval = context.getResources().getInteger(
+                R.integer.car_ui_scrollbar_longpress_repeat_interval);
+
+        if (mInitialDelay < 0 || mRepeatInterval < 0) {
+            throw new IllegalArgumentException("negative intervals are not allowed");
+        }
+        this.mOnClickListener = clickListener;
+    }
+
+    /**
+     * Cancel pending scroll operations. Any scroll operations that were scheduled to possibly be
+     * performed, as part of a continuous scroll, will be cancelled.
+     */
+    public void cancelPendingScroll() {
+        mHandler.removeCallbacks(mPeriodicRunnable);
+        mIsLongPressed = false;
+    }
+
+    @Override
+    public boolean onTouch(View view, MotionEvent motionEvent) {
+        mTouchedView = view;
+        switch (motionEvent.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mHandler.removeCallbacks(mPeriodicRunnable);
+                mHandler.postDelayed(mPeriodicRunnable, mInitialDelay);
+                mTouchedView.setPressed(true);
+                return true;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                if (!mIsLongPressed) {
+                    mOnClickListener.onClick(view);
+                }
+                mHandler.removeCallbacks(mPeriodicRunnable);
+                mTouchedView.setPressed(false);
+                mIsLongPressed = false;
+                return true;
+        }
+        return false;
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/PassThroughFilter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/PassThroughFilter.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/PassThroughFilter.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/PassThroughFilter.java
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/RangeFilter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/RangeFilter.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/RangeFilter.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/RangeFilter.java
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/RangeFilterImpl.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/RangeFilterImpl.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/RangeFilterImpl.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/RangeFilterImpl.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ScrollBar.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ScrollBar.java
new file mode 100644
index 0000000..8e127f0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ScrollBar.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview;
+
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * An abstract class that defines required contract for a custom scroll bar for the {@link
+ * CarUiRecyclerView}. All custom scroll bar must inherit from this class.
+ */
+public interface ScrollBar {
+    /**
+     * The concrete class should implement this method to initialize configuration of a scrollbar
+     * view.
+     */
+    void initialize(RecyclerView recyclerView, View scrollView);
+
+    /**
+     * Requests layout of the scrollbar. Should be called when there's been a change that will
+     * affect
+     * the size of the scrollbar view.
+     */
+    void requestLayout();
+
+    /** Sets the padding of the scrollbar, relative to the padding of the RecyclerView. */
+    void setPadding(int paddingStart, int paddingEnd);
+}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollingLimitedViewHolder.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ScrollingLimitedViewHolder.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/recyclerview/ScrollingLimitedViewHolder.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/ScrollingLimitedViewHolder.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java
new file mode 100644
index 0000000..5eb090a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview.decorations.grid;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+
+import java.util.Objects;
+
+/** Adds interior dividers to a RecyclerView with a GridLayoutManager. */
+public class GridDividerItemDecoration extends RecyclerView.ItemDecoration {
+
+    private final Drawable mHorizontalDivider;
+    private final Drawable mVerticalDivider;
+    private int mNumColumns;
+
+    /**
+     * Sole constructor. Takes in {@link Drawable} objects to be used as horizontal and vertical
+     * dividers.
+     *
+     * @param horizontalDivider A divider {@code Drawable} to be drawn on the rows of the grid of
+     *                          the
+     *                          RecyclerView
+     * @param verticalDivider   A divider {@code Drawable} to be drawn on the columns of the grid of
+     *                          the
+     *                          RecyclerView
+     * @param numColumns        The number of columns in the grid of the RecyclerView
+     */
+    public GridDividerItemDecoration(
+            Drawable horizontalDivider, Drawable verticalDivider, int numColumns) {
+        this.mHorizontalDivider = horizontalDivider;
+        this.mVerticalDivider = verticalDivider;
+        this.mNumColumns = numColumns;
+    }
+
+    /**
+     * Draws horizontal and/or vertical dividers onto the parent RecyclerView.
+     *
+     * @param canvas The {@link Canvas} onto which dividers will be drawn
+     * @param parent The RecyclerView onto which dividers are being added
+     * @param state  The current RecyclerView.State of the RecyclerView
+     */
+    @Override
+    public void onDrawOver(@NonNull Canvas canvas, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        drawVerticalDividers(canvas, parent);
+        drawHorizontalDividers(canvas, parent);
+    }
+
+    /**
+     * Determines the size and location of offsets between items in the parent RecyclerView.
+     *
+     * @param outRect The {@link Rect} of offsets to be added around the child view
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
+     */
+    @Override
+    public void getItemOffsets(
+            Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        outRect.set(
+                0, 0, mHorizontalDivider.getIntrinsicWidth(),
+                mHorizontalDivider.getIntrinsicHeight());
+    }
+
+    /**
+     * Adds horizontal dividers to a RecyclerView with a GridLayoutManager or its subclass.
+     *
+     * @param canvas The {@link Canvas} onto which dividers will be drawn
+     * @param parent The RecyclerView onto which dividers are being added
+     */
+    private void drawHorizontalDividers(Canvas canvas, RecyclerView parent) {
+        RecyclerView.LayoutManager layoutManager = Objects.requireNonNull(
+                parent.getLayoutManager());
+        int childCount = layoutManager.getChildCount();
+        int rowCount = childCount / mNumColumns;
+        int lastRowChildCount = childCount % mNumColumns;
+        int lastColumn = Math.min(childCount, mNumColumns);
+
+        for (int i = 1; i < lastColumn; i++) {
+            int lastRowChildIndex;
+            if (i < lastRowChildCount) {
+                lastRowChildIndex = i + (rowCount * mNumColumns);
+            } else {
+                lastRowChildIndex = i + ((rowCount - 1) * mNumColumns);
+            }
+
+
+            View firstRowChild = layoutManager.getChildAt(i);
+            View lastRowChild = layoutManager.getChildAt(lastRowChildIndex);
+
+            int dividerTop =
+                    firstRowChild.getTop() + (int) parent.getContext().getResources().getDimension(
+                            R.dimen.car_ui_recyclerview_divider_top_margin);
+            int dividerRight = firstRowChild.getLeft();
+            int dividerLeft = dividerRight - mHorizontalDivider.getIntrinsicWidth();
+            int dividerBottom = lastRowChild.getBottom()
+                    - (int) parent.getContext().getResources().getDimension(
+                    R.dimen.car_ui_recyclerview_divider_bottom_margin);
+
+            mHorizontalDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
+            mHorizontalDivider.draw(canvas);
+        }
+    }
+
+    public void setNumOfColumns(int numberOfColumns) {
+        mNumColumns = numberOfColumns;
+    }
+
+    /**
+     * Adds vertical dividers to a RecyclerView with a GridLayoutManager or its subclass.
+     *
+     * @param canvas The {@link Canvas} onto which dividers will be drawn
+     * @param parent The RecyclerView onto which dividers are being added
+     */
+    private void drawVerticalDividers(Canvas canvas, RecyclerView parent) {
+        RecyclerView.LayoutManager layoutManager = Objects.requireNonNull(
+                parent.getLayoutManager());
+        double childCount = layoutManager.getChildCount();
+        double rowCount = Math.ceil(childCount / mNumColumns);
+        int rightmostChildIndex;
+        for (int i = 1; i <= rowCount; i++) {
+            // we don't want the divider on top of first row.
+            if (i == 1) {
+                continue;
+            }
+            if (i == rowCount) {
+                rightmostChildIndex = ((i - 1) * mNumColumns) - 1;
+            } else {
+                rightmostChildIndex = (i * mNumColumns) - 1;
+            }
+
+            View leftmostChild = layoutManager.getChildAt(mNumColumns * (i - 1));
+            View rightmostChild = layoutManager.getChildAt(rightmostChildIndex);
+
+            // draws on top of each row.
+            int dividerLeft =
+                    leftmostChild.getLeft() + (int) parent.getContext().getResources().getDimension(
+                            R.dimen.car_ui_recyclerview_divider_start_margin);
+            int dividerBottom = leftmostChild.getTop();
+            int dividerTop = dividerBottom - mVerticalDivider.getIntrinsicHeight();
+            int dividerRight = rightmostChild.getRight()
+                    - (int) parent.getContext().getResources().getDimension(
+                    R.dimen.car_ui_recyclerview_divider_end_margin);
+
+            mVerticalDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
+            mVerticalDivider.draw(canvas);
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java
new file mode 100644
index 0000000..f1085c2
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview.decorations.grid;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.lang.annotation.Retention;
+
+/** Adds an offset to the top of a RecyclerView with a GridLayoutManager or its subclass. */
+public class GridOffsetItemDecoration extends RecyclerView.ItemDecoration {
+
+    private int mOffsetPx;
+    private Drawable mOffsetDrawable;
+    private int mNumColumns;
+    @OffsetPosition
+    private final int mOffsetPosition;
+
+    /** The possible values for setScrollbarPosition. */
+    @IntDef({
+            OffsetPosition.START,
+            OffsetPosition.END,
+    })
+    @Retention(SOURCE)
+    public @interface OffsetPosition {
+        /** Position the offset to the start of the screen. */
+        int START = 0;
+
+        /** Position offset to the end of the screen. */
+        int END = 1;
+    }
+
+    /**
+     * Constructor that takes in the size of the offset to be added to the top of the RecyclerView.
+     *
+     * @param offsetPx       The size of the offset to be added to the top of the RecyclerView in
+     *                       pixels
+     * @param numColumns     The number of columns in the grid of the RecyclerView
+     * @param offsetPosition Position where offset needs to be applied.
+     */
+    public GridOffsetItemDecoration(int offsetPx, int numColumns, int offsetPosition) {
+        this.mOffsetPx = offsetPx;
+        this.mNumColumns = numColumns;
+        this.mOffsetPosition = offsetPosition;
+    }
+
+    /**
+     * Constructor that takes in a {@link Drawable} to be drawn at the top of the RecyclerView.
+     *
+     * @param offsetDrawable The {@code Drawable} to be added to the top of the RecyclerView
+     * @param numColumns     The number of columns in the grid of the RecyclerView
+     */
+    public GridOffsetItemDecoration(Drawable offsetDrawable, int numColumns, int offsetPosition) {
+        this.mOffsetDrawable = offsetDrawable;
+        this.mNumColumns = numColumns;
+        this.mOffsetPosition = offsetPosition;
+    }
+
+    public void setNumOfColumns(int numberOfColumns) {
+        mNumColumns = numberOfColumns;
+    }
+
+    /**
+     * Determines the size and the location of the offset to be added to the top of the
+     * RecyclerView.
+     *
+     * @param outRect The {@link Rect} of offsets to be added around the child view
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
+     */
+    @Override
+    public void getItemOffsets(
+            @NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        super.getItemOffsets(outRect, view, parent, state);
+
+        if (mOffsetPosition == OffsetPosition.START) {
+            boolean childIsInTopRow = parent.getChildAdapterPosition(view) < mNumColumns;
+            if (childIsInTopRow) {
+                if (mOffsetPx > 0) {
+                    outRect.top = mOffsetPx;
+                } else if (mOffsetDrawable != null) {
+                    outRect.top = mOffsetDrawable.getIntrinsicHeight();
+                }
+            }
+            return;
+        }
+
+        int childCount = state.getItemCount();
+        int lastRowChildCount = getLastRowChildCount(childCount);
+
+        boolean childIsInBottomRow =
+                parent.getChildAdapterPosition(view) >= childCount - lastRowChildCount;
+        if (childIsInBottomRow) {
+            if (mOffsetPx > 0) {
+                outRect.bottom = mOffsetPx;
+            } else if (mOffsetDrawable != null) {
+                outRect.bottom = mOffsetDrawable.getIntrinsicHeight();
+            }
+        }
+    }
+
+    @Override
+    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        super.onDraw(c, parent, state);
+        if (mOffsetDrawable == null) {
+            return;
+        }
+
+        int parentLeft = parent.getPaddingLeft();
+        int parentRight = parent.getWidth() - parent.getPaddingRight();
+
+        if (mOffsetPosition == OffsetPosition.START) {
+
+            int parentTop = parent.getPaddingTop();
+            int offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
+
+            mOffsetDrawable.setBounds(parentLeft, parentTop, parentRight, offsetDrawableBottom);
+            mOffsetDrawable.draw(c);
+            return;
+        }
+
+        int childCount = state.getItemCount();
+        int lastRowChildCount = getLastRowChildCount(childCount);
+
+        int offsetDrawableTop = 0;
+        int offsetDrawableBottom = 0;
+
+        for (int i = childCount - lastRowChildCount; i < childCount; i++) {
+            View child = parent.getChildAt(i);
+            offsetDrawableTop = child.getBottom();
+            offsetDrawableBottom = offsetDrawableTop + mOffsetDrawable.getIntrinsicHeight();
+        }
+
+        mOffsetDrawable.setBounds(parentLeft, offsetDrawableTop, parentRight, offsetDrawableBottom);
+        mOffsetDrawable.draw(c);
+    }
+
+    private int getLastRowChildCount(int itemCount) {
+        int lastRowChildCount = itemCount % mNumColumns;
+        if (lastRowChildCount == 0) {
+            lastRowChildCount = mNumColumns;
+        }
+
+        return lastRowChildCount;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java
new file mode 100644
index 0000000..3ab24aa
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview.decorations.linear;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+
+import java.util.Objects;
+
+/** Adds interior dividers to a RecyclerView with a LinearLayoutManager or its subclass. */
+public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration {
+
+    private final Drawable mDivider;
+    private int mOrientation;
+
+    /**
+     * Sole constructor. Takes in a {@link Drawable} to be used as the interior
+     * car_ui_recyclerview_divider.
+     *
+     * @param divider A car_ui_recyclerview_divider {@code Drawable} to be drawn on the
+     *                RecyclerView
+     */
+    public LinearDividerItemDecoration(Drawable divider) {
+        this.mDivider = divider;
+    }
+
+    /**
+     * Draws horizontal or vertical dividers onto the parent RecyclerView.
+     *
+     * @param canvas The {@link Canvas} onto which dividers will be drawn
+     * @param parent The RecyclerView onto which dividers are being added
+     * @param state  The current RecyclerView.State of the RecyclerView
+     */
+    @Override
+    public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
+            drawHorizontalDividers(canvas, parent);
+        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
+            drawVerticalDividers(canvas, parent);
+        }
+    }
+
+    /**
+     * Determines the size and location of offsets between items in the parent RecyclerView.
+     *
+     * @param outRect The {@link Rect} of offsets to be added around the child view
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
+     */
+    @Override
+    public void getItemOffsets(
+            @NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        super.getItemOffsets(outRect, view, parent, state);
+
+        if (parent.getChildAdapterPosition(view) == 0) {
+            return;
+        }
+
+        mOrientation = ((LinearLayoutManager) Objects.requireNonNull(
+                parent.getLayoutManager())).getOrientation();
+        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
+            outRect.left = mDivider.getIntrinsicWidth();
+        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
+            outRect.top = mDivider.getIntrinsicHeight();
+        }
+    }
+
+    /**
+     * Adds dividers to a RecyclerView with a LinearLayoutManager or its subclass oriented
+     * horizontally.
+     *
+     * @param canvas The {@link Canvas} onto which horizontal dividers will be drawn
+     * @param parent The RecyclerView onto which horizontal dividers are being added
+     */
+    private void drawHorizontalDividers(Canvas canvas, RecyclerView parent) {
+        int parentTop =
+                parent.getPaddingTop() + (int) parent.getContext().getResources().getDimension(
+                        R.dimen.car_ui_recyclerview_divider_top_margin);
+        int parentBottom = parent.getHeight() - parent.getPaddingBottom()
+                - (int) parent.getContext().getResources().getDimension(
+                R.dimen.car_ui_recyclerview_divider_bottom_margin);
+
+        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
+        int childCount = layoutManager.getChildCount();
+        for (int i = 0; i < childCount - 1; i++) {
+            View child = layoutManager.getChildAt(i);
+
+            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+
+            int parentLeft = child.getRight() + params.rightMargin;
+            int parentRight = parentLeft + mDivider.getIntrinsicWidth();
+
+            mDivider.setBounds(parentLeft, parentTop, parentRight, parentBottom);
+            mDivider.draw(canvas);
+        }
+    }
+
+    /**
+     * Adds dividers to a RecyclerView with a LinearLayoutManager or its subclass oriented
+     * vertically.
+     *
+     * @param canvas The {@link Canvas} onto which vertical dividers will be drawn
+     * @param parent The RecyclerView onto which vertical dividers are being added
+     */
+    private void drawVerticalDividers(Canvas canvas, RecyclerView parent) {
+        int parentLeft =
+                parent.getPaddingLeft() + (int) parent.getContext().getResources().getDimension(
+                        R.dimen.car_ui_recyclerview_divider_start_margin);
+        int parentRight = parent.getWidth() - parent.getPaddingRight()
+                - (int) parent.getContext().getResources().getDimension(
+                R.dimen.car_ui_recyclerview_divider_end_margin);
+
+        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
+        int childCount = layoutManager.getChildCount();
+        for (int i = 0; i < childCount - 1; i++) {
+            View child = layoutManager.getChildAt(i);
+
+            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+
+            int parentTop = child.getBottom() + params.bottomMargin;
+            int parentBottom = parentTop + mDivider.getIntrinsicHeight();
+
+            mDivider.setBounds(parentLeft, parentTop, parentRight, parentBottom);
+            mDivider.draw(canvas);
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java
new file mode 100644
index 0000000..62d361e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.recyclerview.decorations.linear;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.lang.annotation.Retention;
+import java.util.Objects;
+
+/**
+ * Adds an offset to the start of a RecyclerView using a LinearLayoutManager or its subclass.
+ *
+ * <p>If the RecyclerView.LayoutManager is oriented vertically, the offset will be added to the top
+ * of the RecyclerView. If the LayoutManager is oriented horizontally, the offset will be added to
+ * the left of the RecyclerView.
+ */
+public class LinearOffsetItemDecoration extends RecyclerView.ItemDecoration {
+
+    private int mOffsetPx;
+    private Drawable mOffsetDrawable;
+    private int mOrientation;
+    @OffsetPosition
+    private int mOffsetPosition;
+
+    /** The possible values for setScrollbarPosition. */
+    @IntDef({
+            OffsetPosition.START,
+            OffsetPosition.END,
+    })
+    @Retention(SOURCE)
+    public @interface OffsetPosition {
+        /** Position the offset to the start of the screen. */
+        int START = 0;
+
+        /** Position offset to the end of the screen. */
+        int END = 1;
+    }
+
+    /**
+     * Constructor that takes in the size of the offset to be added to the start of the
+     * RecyclerView.
+     *
+     * @param offsetPx       The size of the offset to be added to the start of the RecyclerView in
+     *                       pixels
+     * @param offsetPosition Position where offset needs to be applied.
+     */
+    public LinearOffsetItemDecoration(int offsetPx, int offsetPosition) {
+        this.mOffsetPx = offsetPx;
+        this.mOffsetPosition = offsetPosition;
+    }
+
+    /**
+     * Constructor that takes in a {@link Drawable} to be drawn at the start of the RecyclerView.
+     *
+     * @param offsetDrawable The {@code Drawable} to be added to the start of the RecyclerView
+     */
+    public LinearOffsetItemDecoration(Drawable offsetDrawable) {
+        this.mOffsetDrawable = offsetDrawable;
+    }
+
+    /**
+     * Determines the size and location of the offset to be added to the start of the RecyclerView.
+     *
+     * @param outRect The {@link Rect} of offsets to be added around the child view
+     * @param view    The child view to be decorated with an offset
+     * @param parent  The RecyclerView onto which dividers are being added
+     * @param state   The current RecyclerView.State of the RecyclerView
+     */
+    @Override
+    public void getItemOffsets(
+            @NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        super.getItemOffsets(outRect, view, parent, state);
+
+        if (mOffsetPosition == OffsetPosition.START && parent.getChildAdapterPosition(view) > 0) {
+            return;
+        }
+
+        int itemCount = state.getItemCount();
+        if (mOffsetPosition == OffsetPosition.END
+                && parent.getChildAdapterPosition(view) != itemCount - 1) {
+            return;
+        }
+
+        mOrientation = ((LinearLayoutManager) Objects.requireNonNull(
+                parent.getLayoutManager())).getOrientation();
+        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
+            if (mOffsetPx > 0) {
+                if (mOffsetPosition == OffsetPosition.START) {
+                    outRect.left = mOffsetPx;
+                } else {
+                    outRect.right = mOffsetPx;
+                }
+            } else if (mOffsetDrawable != null) {
+                if (mOffsetPosition == OffsetPosition.START) {
+                    outRect.left = mOffsetDrawable.getIntrinsicWidth();
+                } else {
+                    outRect.right = mOffsetDrawable.getIntrinsicWidth();
+                }
+            }
+        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
+            if (mOffsetPx > 0) {
+                if (mOffsetPosition == OffsetPosition.START) {
+                    outRect.top = mOffsetPx;
+                } else {
+                    outRect.bottom = mOffsetPx;
+                }
+            } else if (mOffsetDrawable != null) {
+                if (mOffsetPosition == OffsetPosition.START) {
+                    outRect.top = mOffsetDrawable.getIntrinsicHeight();
+                } else {
+                    outRect.bottom = mOffsetDrawable.getIntrinsicHeight();
+                }
+            }
+        }
+    }
+
+    /**
+     * Draws horizontal or vertical offset onto the start of the parent RecyclerView.
+     *
+     * @param c      The {@link Canvas} onto which an offset will be drawn
+     * @param parent The RecyclerView onto which an offset is being added
+     * @param state  The current RecyclerView.State of the RecyclerView
+     */
+    @Override
+    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
+            @NonNull RecyclerView.State state) {
+        super.onDraw(c, parent, state);
+        if (mOffsetDrawable == null) {
+            return;
+        }
+
+        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
+            drawOffsetHorizontal(c, parent);
+        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
+            drawOffsetVertical(c, parent);
+        }
+    }
+
+    private void drawOffsetHorizontal(Canvas canvas, RecyclerView parent) {
+        int parentTop = parent.getPaddingTop();
+        int parentBottom = parent.getHeight() - parent.getPaddingBottom();
+        int parentLeft;
+        int offsetDrawableRight;
+
+        if (mOffsetPosition == OffsetPosition.START) {
+            parentLeft = parent.getPaddingLeft();
+        } else {
+            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
+            View lastChild = layoutManager.getChildAt(layoutManager.getChildCount() - 1);
+            RecyclerView.LayoutParams lastChildLayoutParams =
+                    (RecyclerView.LayoutParams) lastChild.getLayoutParams();
+            parentLeft = lastChild.getRight() + lastChildLayoutParams.rightMargin;
+        }
+        offsetDrawableRight = parentLeft + mOffsetDrawable.getIntrinsicWidth();
+
+        mOffsetDrawable.setBounds(parentLeft, parentTop, offsetDrawableRight, parentBottom);
+        mOffsetDrawable.draw(canvas);
+    }
+
+    private void drawOffsetVertical(Canvas canvas, RecyclerView parent) {
+        int parentLeft = parent.getPaddingLeft();
+        int parentRight = parent.getWidth() - parent.getPaddingRight();
+
+        int parentTop;
+        int offsetDrawableBottom;
+
+        if (mOffsetPosition == OffsetPosition.START) {
+            parentTop = parent.getPaddingTop();
+        } else {
+            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
+            View lastChild = layoutManager.getChildAt(layoutManager.getChildCount() - 1);
+            RecyclerView.LayoutParams lastChildLayoutParams =
+                    (RecyclerView.LayoutParams) lastChild.getLayoutParams();
+            parentTop = lastChild.getBottom() + lastChildLayoutParams.bottomMargin;
+        }
+        offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
+
+        mOffsetDrawable.setBounds(parentLeft, parentTop, parentRight, offsetDrawableBottom);
+        mOffsetDrawable.draw(canvas);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/MenuItem.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/MenuItem.java
new file mode 100644
index 0000000..6ee35d3
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/MenuItem.java
@@ -0,0 +1,613 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.toolbar;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Represents a button to display in the {@link Toolbar}.
+ *
+ * <p>There are currently 3 types of buttons: icon, text, and switch. Using
+ * {@link Builder#setCheckable()} will ensure that you get a switch, after that
+ * {@link Builder#setIcon(int)} will ensure an icon, and anything left just requires
+ * {@link Builder#setTitle(int)}.
+ *
+ * <p>Each MenuItem has a {@link DisplayBehavior} that controls if it appears on the {@link Toolbar}
+ * itself, or it's overflow menu.
+ *
+ * <p>If you require a search or settings button, you should use
+ * {@link Builder#setToSearch()} or
+ * {@link Builder#setToSettings()}.
+ *
+ * <p>Some properties can be changed after the creating a MenuItem, but others require being set
+ * with a {@link Builder}.
+ */
+public class MenuItem {
+
+    private final Context mContext;
+    private final boolean mIsCheckable;
+    private final boolean mIsActivatable;
+    private final boolean mIsSearch;
+    private final boolean mShowIconAndTitle;
+    private final boolean mIsTinted;
+    @CarUxRestrictions.CarUxRestrictionsInfo
+
+    private int mId;
+    private CarUxRestrictions mCurrentRestrictions;
+    // This is a WeakReference to allow the Toolbar (and by extension, the whole screen
+    // the toolbar is on) to be garbage-collected if the MenuItem is held past the
+    // lifecycle of the toolbar.
+    private WeakReference<Listener> mListener = new WeakReference<>(null);
+    private CharSequence mTitle;
+    private Drawable mIcon;
+    private OnClickListener mOnClickListener;
+    private DisplayBehavior mDisplayBehavior;
+    private int mUxRestrictions;
+    private boolean mIsEnabled;
+    private boolean mIsChecked;
+    private boolean mIsVisible;
+    private boolean mIsActivated;
+
+    private MenuItem(Builder builder) {
+        mContext = builder.mContext;
+        mId = builder.mId;
+        mIsCheckable = builder.mIsCheckable;
+        mIsActivatable = builder.mIsActivatable;
+        mTitle = builder.mTitle;
+        mIcon = builder.mIcon;
+        mOnClickListener = builder.mOnClickListener;
+        mDisplayBehavior = builder.mDisplayBehavior;
+        mIsEnabled = builder.mIsEnabled;
+        mIsChecked = builder.mIsChecked;
+        mIsVisible = builder.mIsVisible;
+        mIsActivated = builder.mIsActivated;
+        mIsSearch = builder.mIsSearch;
+        mShowIconAndTitle = builder.mShowIconAndTitle;
+        mIsTinted = builder.mIsTinted;
+        mUxRestrictions = builder.mUxRestrictions;
+
+        mCurrentRestrictions = CarUxRestrictionsUtil.getInstance(mContext).getCurrentRestrictions();
+    }
+
+    private void update() {
+        Listener listener = mListener.get();
+        if (listener != null) {
+            listener.onMenuItemChanged(this);
+        }
+    }
+
+    /** Sets the id, which is purely for the client to distinguish MenuItems with.  */
+    public void setId(int id) {
+        mId = id;
+        update();
+    }
+
+    /** Gets the id, which is purely for the client to distinguish MenuItems with. */
+    public int getId() {
+        return mId;
+    }
+
+    /** Returns whether the MenuItem is enabled */
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    /** Sets whether the MenuItem is enabled */
+    public void setEnabled(boolean enabled) {
+        mIsEnabled = enabled;
+
+        update();
+    }
+
+    /** Returns whether the MenuItem is checkable. If it is, it will be displayed as a switch. */
+    public boolean isCheckable() {
+        return mIsCheckable;
+    }
+
+    /**
+     * Returns whether the MenuItem is currently checked. Only valid if {@link #isCheckable()}
+     * is true.
+     */
+    public boolean isChecked() {
+        return mIsChecked;
+    }
+
+    /**
+     * Sets whether or not the MenuItem is checked.
+     * @throws IllegalStateException When {@link #isCheckable()} is false.
+     */
+    public void setChecked(boolean checked) {
+        if (!isCheckable()) {
+            throw new IllegalStateException("Cannot call setChecked() on a non-checkable MenuItem");
+        }
+
+        mIsChecked = checked;
+
+        update();
+    }
+
+    public boolean isTinted() {
+        return mIsTinted;
+    }
+
+    /** Returns whether or not the MenuItem is visible */
+    public boolean isVisible() {
+        return mIsVisible;
+    }
+
+    /** Sets whether or not the MenuItem is visible */
+    public void setVisible(boolean visible) {
+        mIsVisible = visible;
+
+        update();
+    }
+
+    /**
+     * Returns whether the MenuItem is activatable. If it is, it's every click will toggle
+     * the MenuItem's View to appear activated or not.
+     */
+    public boolean isActivatable() {
+        return mIsActivatable;
+    }
+
+    /** Returns whether or not this view is selected. Toggles after every click */
+    public boolean isActivated() {
+        return mIsActivated;
+    }
+
+    /** Sets the MenuItem as activated and updates it's View to the activated state */
+    public void setActivated(boolean activated) {
+        if (!isActivatable()) {
+            throw new IllegalStateException(
+                    "Cannot call setActivated() on a non-activatable MenuItem");
+        }
+
+        mIsActivated = activated;
+
+        update();
+    }
+
+    /** Gets the title of this MenuItem. */
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /** Sets the title of this MenuItem. */
+    public void setTitle(CharSequence title) {
+        mTitle = title;
+
+        update();
+    }
+
+    /** Sets the title of this MenuItem to a string resource. */
+    public void setTitle(int resId) {
+        setTitle(mContext.getString(resId));
+    }
+
+    /** Sets the UxRestrictions of this MenuItem. */
+    public void setUxRestrictions(@CarUxRestrictions.CarUxRestrictionsInfo int uxRestrictions) {
+        if (mUxRestrictions != uxRestrictions) {
+            mUxRestrictions = uxRestrictions;
+            update();
+        }
+    }
+
+    @CarUxRestrictions.CarUxRestrictionsInfo
+    public int getUxRestrictions() {
+        return mUxRestrictions;
+    }
+
+    /** Gets the current {@link OnClickListener} */
+    public OnClickListener getOnClickListener() {
+        return mOnClickListener;
+    }
+
+    public boolean isShowingIconAndTitle() {
+        return mShowIconAndTitle;
+    }
+
+    /** Sets the {@link OnClickListener} */
+    public void setOnClickListener(OnClickListener listener) {
+        mOnClickListener = listener;
+
+        update();
+    }
+
+    /* package */ void setCarUxRestrictions(CarUxRestrictions restrictions) {
+        boolean wasRestricted = isRestricted();
+        mCurrentRestrictions = restrictions;
+
+        if (isRestricted() != wasRestricted) {
+            update();
+        }
+    }
+
+    /* package */ boolean isRestricted() {
+        return CarUxRestrictionsUtil.isRestricted(mUxRestrictions, mCurrentRestrictions);
+    }
+
+    /** Calls the {@link OnClickListener}. */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public void performClick() {
+        if (!isEnabled() || !isVisible()) {
+            return;
+        }
+
+        if (isRestricted()) {
+            Toast.makeText(mContext,
+                    R.string.car_ui_restricted_while_driving, Toast.LENGTH_LONG).show();
+            return;
+        }
+
+        if (isActivatable()) {
+            setActivated(!isActivated());
+        }
+
+        if (isCheckable()) {
+            setChecked(!isChecked());
+        }
+
+        if (mOnClickListener != null) {
+            mOnClickListener.onClick(this);
+        }
+    }
+
+    /** Gets the current {@link DisplayBehavior} */
+    public DisplayBehavior getDisplayBehavior() {
+        return mDisplayBehavior;
+    }
+
+    /** Gets the current Icon */
+    public Drawable getIcon() {
+        return mIcon;
+    }
+
+    /** Sets the Icon of this MenuItem. */
+    public void setIcon(Drawable icon) {
+        mIcon = icon;
+
+        update();
+    }
+
+    /** Sets the Icon of this MenuItem to a drawable resource. */
+    public void setIcon(int resId) {
+        setIcon(resId == 0
+                ? null
+                : mContext.getDrawable(resId));
+    }
+
+    /** Returns if this is the search MenuItem, which has special behavior when searching */
+    boolean isSearch() {
+        return mIsSearch;
+    }
+
+    /** Builder class */
+    public static final class Builder {
+        private final Context mContext;
+
+        private String mSearchTitle;
+        private String mSettingsTitle;
+        private Drawable mSearchIcon;
+        private Drawable mSettingsIcon;
+
+        private int mId = View.NO_ID;
+        private CharSequence mTitle;
+        private Drawable mIcon;
+        private OnClickListener mOnClickListener;
+        private DisplayBehavior mDisplayBehavior = DisplayBehavior.ALWAYS;
+        private boolean mIsTinted = true;
+        private boolean mShowIconAndTitle = false;
+        private boolean mIsEnabled = true;
+        private boolean mIsCheckable = false;
+        private boolean mIsChecked = false;
+        private boolean mIsVisible = true;
+        private boolean mIsActivatable = false;
+        private boolean mIsActivated = false;
+        private boolean mIsSearch = false;
+        private boolean mIsSettings = false;
+        @CarUxRestrictions.CarUxRestrictionsInfo
+        private int mUxRestrictions = CarUxRestrictions.UX_RESTRICTIONS_BASELINE;
+
+        public Builder(Context c) {
+            // Must use getApplicationContext to avoid leaking activities when the MenuItem
+            // is held onto for longer than the Activity's lifecycle
+            mContext = c.getApplicationContext();
+        }
+
+        /** Builds a {@link MenuItem} from the current state of the Builder */
+        public MenuItem build() {
+            if (mIsActivatable && (mShowIconAndTitle || mIcon == null)) {
+                throw new IllegalStateException("Only simple icons can be activatable");
+            }
+            if (mIsCheckable && (mShowIconAndTitle || mIsActivatable)) {
+                throw new IllegalStateException("Unsupported options for a checkable MenuItem");
+            }
+            if (mIsSearch && mIsSettings) {
+                throw new IllegalStateException("Can't have both a search and settings MenuItem");
+            }
+            if (mIsActivatable && mDisplayBehavior == DisplayBehavior.NEVER) {
+                throw new IllegalStateException("Activatable MenuItems not supported as Overflow");
+            }
+
+            if (mIsSearch && (!mSearchTitle.contentEquals(mTitle)
+                    || !mSearchIcon.equals(mIcon)
+                    || mIsCheckable
+                    || mIsActivatable
+                    || !mIsTinted
+                    || mShowIconAndTitle
+                    || mDisplayBehavior != DisplayBehavior.ALWAYS)) {
+                throw new IllegalStateException("Invalid search MenuItem");
+            }
+
+            if (mIsSettings && (!mSettingsTitle.contentEquals(mTitle)
+                    || !mSettingsIcon.equals(mIcon)
+                    || mIsCheckable
+                    || mIsActivatable
+                    || !mIsTinted
+                    || mShowIconAndTitle
+                    || mDisplayBehavior != DisplayBehavior.ALWAYS)) {
+                throw new IllegalStateException("Invalid settings MenuItem");
+            }
+
+            return new MenuItem(this);
+        }
+
+        /** Sets the id, which is purely for the client to distinguish MenuItems with. */
+        public Builder setId(int id) {
+            mId = id;
+            return this;
+        }
+
+        /** Sets the title to a string resource id */
+        public Builder setTitle(int resId) {
+            setTitle(mContext.getString(resId));
+            return this;
+        }
+
+        /** Sets the title */
+        public Builder setTitle(CharSequence title) {
+            mTitle = title;
+            return this;
+        }
+
+        /**
+         * Sets the icon to a drawable resource id.
+         *
+         * <p>The icon's color and size will be changed to match the other MenuItems.
+         */
+        public Builder setIcon(int resId) {
+            mIcon = resId == 0
+                    ? null
+                    : mContext.getDrawable(resId);
+            return this;
+        }
+
+        /**
+         * Sets the icon to a drawable.
+         *
+         * <p>The icon's color and size will be changed to match the other MenuItems.
+         */
+        public Builder setIcon(Drawable icon) {
+            mIcon = icon;
+            return this;
+        }
+
+        /**
+         * Sets whether to tint the icon, true by default.
+         *
+         * <p>Try not to use this, it should only be used if the MenuItem is displaying some
+         * kind of logo or avatar and should be colored.
+         */
+        public Builder setTinted(boolean tinted) {
+            mIsTinted = tinted;
+            return this;
+        }
+
+        /** Sets whether the MenuItem is visible or not. Default true. */
+        public Builder setVisible(boolean visible) {
+            mIsVisible = visible;
+            return this;
+        }
+
+        /**
+         * Makes the MenuItem activatable, which means it will toggle it's visual state after
+         * every click.
+         */
+        public Builder setActivatable() {
+            mIsActivatable = true;
+            return this;
+        }
+
+        /**
+         * Sets whether or not the MenuItem is selected. If it is,
+         * {@link View#setSelected(boolean)} will be called on its View.
+         */
+        public Builder setActivated(boolean activated) {
+            setActivatable();
+            mIsActivated = activated;
+            return this;
+        }
+
+        /** Sets the {@link OnClickListener} */
+        public Builder setOnClickListener(OnClickListener listener) {
+            mOnClickListener = listener;
+            return this;
+        }
+
+        /**
+         * Used to show both the icon and title when displayed on the toolbar. If this
+         * is false, only the icon while be displayed when the MenuItem is in the toolbar
+         * and only the title will be displayed when the MenuItem is in the overflow menu.
+         *
+         * <p>Defaults to false.
+         */
+        public Builder setShowIconAndTitle(boolean showIconAndTitle) {
+            mShowIconAndTitle = showIconAndTitle;
+            return this;
+        }
+
+        /**
+         * Sets the {@link DisplayBehavior}.
+         *
+         * <p>If the DisplayBehavior is {@link DisplayBehavior#NEVER}, the MenuItem must not be
+         * {@link #setCheckable() checkable}.
+         */
+        public Builder setDisplayBehavior(DisplayBehavior behavior) {
+            mDisplayBehavior = behavior;
+            return this;
+        }
+
+        /** Sets whether the MenuItem is enabled or not. Default true. */
+        public Builder setEnabled(boolean enabled) {
+            mIsEnabled = enabled;
+            return this;
+        }
+
+        /**
+         * Makes the MenuItem checkable, meaning it will be displayed as a
+         * switch.
+         *
+         * <p>The MenuItem is not checkable by default.
+         */
+        public Builder setCheckable() {
+            mIsCheckable = true;
+            return this;
+        }
+
+        /**
+         * Sets whether the MenuItem is checked or not. This will imply {@link #setCheckable()}.
+         */
+        public Builder setChecked(boolean checked) {
+            setCheckable();
+            mIsChecked = checked;
+            return this;
+        }
+
+        /**
+         * Sets under what {@link android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo}
+         * the MenuItem should be restricted.
+         */
+        public Builder setUxRestrictions(
+                @CarUxRestrictions.CarUxRestrictionsInfo int restrictions) {
+            mUxRestrictions = restrictions;
+            return this;
+        }
+
+        /**
+         * Creates a search MenuItem.
+         *
+         * <p>The advantage of using this over creating your own is getting an OEM-styled search
+         * icon, and this button will always disappear while searching, even when the
+         * {@link Toolbar Toolbar's} showMenuItemsWhileSearching is true.
+         *
+         * <p>If using this, you should only change the id, visibility, or onClickListener.
+         */
+        public Builder setToSearch() {
+            mSearchTitle = mContext.getString(R.string.car_ui_toolbar_menu_item_search_title);
+            mSearchIcon = mContext.getDrawable(R.drawable.car_ui_icon_search);
+            mIsSearch = true;
+            setTitle(mSearchTitle);
+            setIcon(mSearchIcon);
+            return this;
+        }
+
+        /**
+         * Creates a settings MenuItem.
+         *
+         * <p>The advantage of this over creating your own is getting an OEM-styled settings icon,
+         * and that the MenuItem will be restricted based on
+         * {@link CarUxRestrictions#UX_RESTRICTIONS_NO_SETUP}
+         *
+         * <p>If using this, you should only change the id, visibility, or onClickListener.
+         */
+        public Builder setToSettings() {
+            mSettingsTitle = mContext.getString(R.string.car_ui_toolbar_menu_item_settings_title);
+            mSettingsIcon = mContext.getDrawable(R.drawable.car_ui_icon_settings);
+            mIsSettings = true;
+            setTitle(mSettingsTitle);
+            setIcon(mSettingsIcon);
+            setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP);
+            return this;
+        }
+
+        /** @deprecated Use {@link #setToSearch()} instead. */
+        @Deprecated
+        public static MenuItem createSearch(Context c, OnClickListener listener) {
+            return MenuItem.builder(c)
+                    .setToSearch()
+                    .setOnClickListener(listener)
+                    .build();
+        }
+
+        /** @deprecated Use {@link #setToSettings()} instead. */
+        @Deprecated
+        public static MenuItem createSettings(Context c, OnClickListener listener) {
+            return MenuItem.builder(c)
+                    .setToSettings()
+                    .setOnClickListener(listener)
+                    .build();
+        }
+    }
+
+    /** Get a new {@link Builder}. */
+    public static Builder builder(Context context) {
+        return new Builder(context);
+    }
+
+    /**
+     * OnClickListener for a MenuItem.
+     */
+    public interface OnClickListener {
+        /** Called when the MenuItem is clicked */
+        void onClick(MenuItem item);
+    }
+
+    /**
+     * DisplayBehavior controls how the MenuItem is presented in the Toolbar
+     */
+    public enum DisplayBehavior {
+        /** Always show the MenuItem on the toolbar instead of the overflow menu */
+        ALWAYS,
+        /** Never show the MenuItem in the toolbar, always put it in the overflow menu */
+        NEVER
+    }
+
+    /** Listener for {@link Toolbar} to update when this MenuItem changes */
+    interface Listener {
+        /** Called when the MenuItem is changed. For use only by {@link Toolbar} */
+        void onMenuItemChanged(MenuItem item);
+    }
+
+    /**
+     * Sets a listener for changes to this MenuItem. Note that the MenuItem will only hold
+     * weak references to the Listener, so that the listener is not held if the MenuItem
+     * outlives the toolbar.
+     */
+    void setListener(Listener listener) {
+        mListener = new WeakReference<>(listener);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/MenuItemRenderer.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/MenuItemRenderer.java
new file mode 100644
index 0000000..85141f1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/MenuItemRenderer.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.toolbar;
+
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+
+import android.app.Activity;
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Xml;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import androidx.annotation.XmlRes;
+import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
+import androidx.core.util.Consumer;
+
+import com.android.car.ui.R;
+import com.android.car.ui.utils.CarUiUtils;
+import com.android.car.ui.uxr.DrawableStateView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+class MenuItemRenderer implements MenuItem.Listener {
+
+    private static final int[] RESTRICTED_STATE = new int[] {R.attr.state_ux_restricted};
+
+    private final int mMenuItemIconSize;
+
+    private Toolbar.State mToolbarState;
+
+    private final MenuItem mMenuItem;
+    private final ViewGroup mParentView;
+    private View mView;
+    private View mIconContainer;
+    private ImageView mIconView;
+    private Switch mSwitch;
+    private View mTextContainer;
+    private TextView mTextView;
+    private TextView mTextWithIconView;
+
+    /** Whether the layout file supports rotary mode. */
+    private boolean mIsRotaryEnabledLayout;
+
+    MenuItemRenderer(MenuItem item, ViewGroup parentView) {
+        mMenuItem = item;
+        mParentView = parentView;
+        mMenuItem.setListener(this);
+
+        mMenuItemIconSize = parentView.getContext().getResources()
+                .getDimensionPixelSize(R.dimen.car_ui_toolbar_menu_item_icon_size);
+    }
+
+    void setToolbarState(Toolbar.State state) {
+        mToolbarState = state;
+
+        if (mMenuItem.isSearch()) {
+            updateView();
+        }
+    }
+
+    void setCarUxRestrictions(CarUxRestrictions restrictions) {
+        mMenuItem.setCarUxRestrictions(restrictions);
+    }
+
+    @Override
+    public void onMenuItemChanged(MenuItem changedItem) {
+        updateView();
+    }
+
+    void createView(Consumer<View> callback) {
+        AsyncLayoutInflater inflater = new AsyncLayoutInflater(mParentView.getContext());
+        inflater.inflate(R.layout.car_ui_toolbar_menu_item, mParentView, (View view, int resid,
+                ViewGroup parent) -> {
+            mView = view;
+
+            mIconContainer =
+                    requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_icon_container);
+            mIconView = requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_icon);
+            mSwitch = requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_switch);
+            // mTextContainer is only available in rotary enabled layout.
+            mTextContainer =
+                    CarUiUtils.findViewByRefId(mView, R.id.car_ui_toolbar_menu_item_text_container);
+            mIsRotaryEnabledLayout = mTextContainer != null;
+            mTextView = requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_text);
+            mTextWithIconView =
+                    requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_text_with_icon);
+
+            updateView();
+            callback.accept(mView);
+        });
+    }
+
+    private void updateView() {
+        if (mView == null) {
+            return;
+        }
+
+        mView.setId(mMenuItem.getId());
+
+        boolean hasIcon = mMenuItem.getIcon() != null;
+        boolean hasText = !TextUtils.isEmpty(mMenuItem.getTitle());
+        boolean textAndIcon = mMenuItem.isShowingIconAndTitle();
+        boolean checkable = mMenuItem.isCheckable();
+
+        if (!mMenuItem.isVisible()
+                || (mMenuItem.isSearch() && mToolbarState == Toolbar.State.SEARCH)
+                || (!checkable && !hasIcon && !hasText)) {
+            mView.setVisibility(View.GONE);
+            return;
+        }
+        mView.setVisibility(View.VISIBLE);
+        mView.setContentDescription(mMenuItem.getTitle());
+
+        int iconContainerVisibility = View.GONE;
+        int textContainerVisibility = View.GONE;
+        mTextView.setVisibility(View.GONE);
+        mTextWithIconView.setVisibility(View.GONE);
+        mSwitch.setVisibility(View.GONE);
+        if (checkable) {
+            mSwitch.setChecked(mMenuItem.isChecked());
+            mSwitch.setVisibility(View.VISIBLE);
+            if (mIsRotaryEnabledLayout) {
+                iconContainerVisibility = View.VISIBLE;
+            }
+        } else if (hasText && hasIcon && textAndIcon) {
+            mMenuItem.getIcon().setBounds(0, 0, mMenuItemIconSize, mMenuItemIconSize);
+            mTextWithIconView.setCompoundDrawables(mMenuItem.getIcon(), null, null, null);
+            mTextWithIconView.setText(mMenuItem.getTitle());
+            mTextWithIconView.setVisibility(View.VISIBLE);
+            textContainerVisibility = View.VISIBLE;
+        } else if (hasIcon) {
+            mIconView.setImageDrawable(mMenuItem.getIcon());
+            iconContainerVisibility = View.VISIBLE;
+        } else { // hasText will be true
+            mTextView.setText(mMenuItem.getTitle());
+            mTextView.setVisibility(View.VISIBLE);
+            textContainerVisibility = View.VISIBLE;
+        }
+        // Unlike other views, we should only update the visibility of mIconContainer and
+        // mTextContainer once, otherwise rotary focus might break.
+        mIconContainer.setVisibility(iconContainerVisibility);
+        if (mTextContainer != null) {
+            mTextContainer.setVisibility(textContainerVisibility);
+        }
+
+        if (!mMenuItem.isTinted() && hasIcon) {
+            mMenuItem.getIcon().setTintList(null);
+        }
+
+        recursiveSetEnabledAndDrawableState(mView);
+        mView.setActivated(mMenuItem.isActivated());
+
+        View clickTarget = null;
+        if (mIsRotaryEnabledLayout) {
+            clickTarget = iconContainerVisibility == View.VISIBLE ? mIconContainer : mTextContainer;
+        } else {
+            clickTarget = mView;
+        }
+        if (mMenuItem.getOnClickListener() != null
+                || mMenuItem.isCheckable()
+                || mMenuItem.isActivatable()) {
+            clickTarget.setOnClickListener(v -> mMenuItem.performClick());
+        } else {
+            clickTarget.setOnClickListener(null);
+            clickTarget.setClickable(false);
+        }
+    }
+
+    private void recursiveSetEnabledAndDrawableState(View view) {
+        view.setEnabled(mMenuItem.isEnabled());
+
+        int[] drawableState = mMenuItem.isRestricted() ? RESTRICTED_STATE : null;
+        if (view instanceof ImageView) {
+            ((ImageView) view).setImageState(drawableState, true);
+        } else if (view instanceof DrawableStateView) {
+            ((DrawableStateView) view).setDrawableState(drawableState);
+        }
+
+        if (view instanceof ViewGroup) {
+            ViewGroup viewGroup = ((ViewGroup) view);
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                recursiveSetEnabledAndDrawableState(viewGroup.getChildAt(i));
+            }
+        }
+    }
+
+    static List<MenuItem> readMenuItemList(Context c, @XmlRes int resId) {
+        if (resId == 0) {
+            return new ArrayList<>();
+        }
+
+        try (XmlResourceParser parser = c.getResources().getXml(resId)) {
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+            List<MenuItem> menuItems = new ArrayList<>();
+
+            parser.next();
+            parser.next();
+            parser.require(XmlPullParser.START_TAG, null, "MenuItems");
+            while (parser.next() != XmlPullParser.END_TAG) {
+                menuItems.add(readMenuItem(c, parser, attrs));
+            }
+
+            return menuItems;
+        } catch (XmlPullParserException | IOException e) {
+            throw new RuntimeException("Unable to parse Menu Items", e);
+        }
+    }
+
+    private static MenuItem readMenuItem(Context c, XmlResourceParser parser, AttributeSet attrs)
+            throws XmlPullParserException, IOException {
+
+        parser.require(XmlPullParser.START_TAG, null, "MenuItem");
+
+        TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.CarUiToolbarMenuItem);
+        try {
+            int id = a.getResourceId(R.styleable.CarUiToolbarMenuItem_id, View.NO_ID);
+            String title = a.getString(R.styleable.CarUiToolbarMenuItem_title);
+            Drawable icon = a.getDrawable(R.styleable.CarUiToolbarMenuItem_icon);
+            boolean isSearch = a.getBoolean(R.styleable.CarUiToolbarMenuItem_search, false);
+            boolean isSettings = a.getBoolean(R.styleable.CarUiToolbarMenuItem_settings, false);
+            boolean tinted = a.getBoolean(R.styleable.CarUiToolbarMenuItem_tinted, true);
+            boolean visible = a.getBoolean(R.styleable.CarUiToolbarMenuItem_visible, true);
+            boolean showIconAndTitle = a.getBoolean(
+                    R.styleable.CarUiToolbarMenuItem_showIconAndTitle, false);
+            boolean checkable = a.getBoolean(R.styleable.CarUiToolbarMenuItem_checkable, false);
+            boolean checked = a.getBoolean(R.styleable.CarUiToolbarMenuItem_checked, false);
+            boolean checkedExists = a.hasValue(R.styleable.CarUiToolbarMenuItem_checked);
+            boolean activatable = a.getBoolean(R.styleable.CarUiToolbarMenuItem_activatable, false);
+            boolean activated = a.getBoolean(R.styleable.CarUiToolbarMenuItem_activated, false);
+            boolean activatedExists = a.hasValue(R.styleable.CarUiToolbarMenuItem_activated);
+            int displayBehaviorInt = a.getInt(R.styleable.CarUiToolbarMenuItem_displayBehavior, 0);
+            int uxRestrictions = a.getInt(R.styleable.CarUiToolbarMenuItem_uxRestrictions, 0);
+            String onClickMethod = a.getString(R.styleable.CarUiToolbarMenuItem_onClick);
+            MenuItem.OnClickListener onClickListener = null;
+
+            if (onClickMethod != null) {
+                Activity activity = CarUiUtils.getActivity(c);
+                if (activity == null) {
+                    throw new RuntimeException("Couldn't find an activity for the MenuItem");
+                }
+
+                try {
+                    Method m = activity.getClass().getMethod(onClickMethod, MenuItem.class);
+                    onClickListener = i -> {
+                        try {
+                            m.invoke(activity, i);
+                        } catch (InvocationTargetException | IllegalAccessException e) {
+                            throw new RuntimeException("Couldn't call the MenuItem's listener", e);
+                        }
+                    };
+                } catch (NoSuchMethodException e) {
+                    throw new RuntimeException("OnClick method "
+                            + onClickMethod + "(MenuItem) not found in your activity", e);
+                }
+            }
+
+            MenuItem.DisplayBehavior displayBehavior = displayBehaviorInt == 0
+                    ? MenuItem.DisplayBehavior.ALWAYS
+                    : MenuItem.DisplayBehavior.NEVER;
+
+            parser.next();
+            parser.require(XmlPullParser.END_TAG, null, "MenuItem");
+
+            MenuItem.Builder builder = MenuItem.builder(c)
+                    .setId(id)
+                    .setTitle(title)
+                    .setIcon(icon)
+                    .setOnClickListener(onClickListener)
+                    .setUxRestrictions(uxRestrictions)
+                    .setTinted(tinted)
+                    .setVisible(visible)
+                    .setShowIconAndTitle(showIconAndTitle)
+                    .setDisplayBehavior(displayBehavior);
+
+            if (isSearch) {
+                builder.setToSearch();
+            }
+
+            if (isSettings) {
+                builder.setToSettings();
+            }
+
+            if (checkable || checkedExists) {
+                builder.setChecked(checked);
+            }
+
+            if (activatable || activatedExists) {
+                builder.setActivated(activated);
+            }
+
+            return builder.build();
+        } finally {
+            a.recycle();
+        }
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarController.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ProgressBarController.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarController.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ProgressBarController.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ProgressBarControllerImpl.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ProgressBarControllerImpl.java
new file mode 100644
index 0000000..07a59b2
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ProgressBarControllerImpl.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 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.car.ui.toolbar;
+
+import android.view.View;
+import android.widget.ProgressBar;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Implementation of {@link ProgressBarController}.
+ *
+ * <p>This class accepts a {@link ProgressBar} in it's constructor and forwards the methods
+ * of {@link ProgressBarController} to it.
+ */
+class ProgressBarControllerImpl implements ProgressBarController {
+
+    @NonNull
+    private final ProgressBar mProgressBar;
+
+    ProgressBarControllerImpl(@NonNull ProgressBar progressBar) {
+        mProgressBar = progressBar;
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        mProgressBar.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public boolean isVisible() {
+        return mProgressBar.getVisibility() == View.VISIBLE;
+    }
+
+    @Override
+    public void setIndeterminate(boolean indeterminate) {
+        mProgressBar.setIndeterminate(indeterminate);
+    }
+
+    @Override
+    public boolean isIndeterminate() {
+        return mProgressBar.isIndeterminate();
+    }
+
+    @Override
+    public void setMax(int max) {
+        mProgressBar.setMax(max);
+    }
+
+    @Override
+    public int getMax() {
+        return mProgressBar.getMax();
+    }
+
+    @Override
+    public void setMin(int min) {
+        mProgressBar.setMin(min);
+    }
+
+    @Override
+    public int getMin() {
+        return mProgressBar.getMin();
+    }
+
+    @Override
+    public void setProgress(int progress) {
+        mProgressBar.setProgress(progress);
+    }
+
+    @Override
+    public int getProgress() {
+        return mProgressBar.getProgress();
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/SearchView.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/SearchView.java
new file mode 100644
index 0000000..9506fe1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/SearchView.java
@@ -0,0 +1,264 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.toolbar;
+
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.car.ui.R;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * A search view used by {@link Toolbar}.
+ */
+public class SearchView extends ConstraintLayout {
+    private final InputMethodManager mInputMethodManager;
+    private final ImageView mIcon;
+    private final EditText mSearchText;
+    private final View mCloseIcon;
+    private final int mStartPaddingWithoutIcon;
+    private final int mStartPadding;
+    private final int mEndPadding;
+    private Set<Toolbar.OnSearchListener> mSearchListeners = Collections.emptySet();
+    private Set<Toolbar.OnSearchCompletedListener> mSearchCompletedListeners =
+            Collections.emptySet();
+    private final TextWatcher mTextWatcher = new TextWatcher() {
+        @Override
+        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+        }
+
+        @Override
+        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+        }
+
+        @Override
+        public void afterTextChanged(Editable editable) {
+            onSearch(editable.toString());
+        }
+    };
+
+    private boolean mIsPlainText = false;
+
+    public SearchView(Context context) {
+        this(context, null);
+    }
+
+    public SearchView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SearchView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        mInputMethodManager = (InputMethodManager)
+            getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        inflater.inflate(R.layout.car_ui_toolbar_search_view, this, true);
+
+        mSearchText = requireViewByRefId(this, R.id.car_ui_toolbar_search_bar);
+        mIcon = requireViewByRefId(this, R.id.car_ui_toolbar_search_icon);
+        mCloseIcon = requireViewByRefId(this, R.id.car_ui_toolbar_search_close);
+
+        mCloseIcon.setOnClickListener(view -> mSearchText.getText().clear());
+        mCloseIcon.setVisibility(View.GONE);
+
+        mStartPaddingWithoutIcon = mSearchText.getPaddingStart();
+        mStartPadding = context.getResources().getDimensionPixelSize(
+                R.dimen.car_ui_toolbar_search_search_icon_container_width);
+        mEndPadding = context.getResources().getDimensionPixelSize(
+                R.dimen.car_ui_toolbar_search_close_icon_container_width);
+
+        mSearchText.setSaveEnabled(false);
+        mSearchText.setPaddingRelative(mStartPadding, 0, mEndPadding, 0);
+
+        mSearchText.setOnFocusChangeListener(
+                (view, hasFocus) -> {
+                    if (hasFocus) {
+                        mInputMethodManager.showSoftInput(view, 0);
+                    } else {
+                        mInputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
+                    }
+                });
+
+        mSearchText.addTextChangedListener(mTextWatcher);
+
+        mSearchText.setOnEditorActionListener((v, actionId, event) -> {
+            if (actionId == EditorInfo.IME_ACTION_DONE
+                    || actionId == EditorInfo.IME_ACTION_SEARCH) {
+                notifyQuerySubmit();
+            } else if (isEnter(event)) {
+                if (event.getAction() == KeyEvent.ACTION_UP) {
+                    // Note that we want to trigger search only on ACTION_UP, but want to return
+                    // true for all actions for the relevant key event.
+                    notifyQuerySubmit();
+                }
+                return true;
+            }
+            return false;
+        });
+    }
+
+    private boolean isEnter(KeyEvent event) {
+        boolean result = false;
+        if (event != null) {
+            int keyCode = event.getKeyCode();
+            result = keyCode == KeyEvent.KEYCODE_ENTER
+                    || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER
+                    || keyCode == KeyEvent.KEYCODE_SEARCH;
+        }
+        return result;
+    }
+
+    private void notifyQuerySubmit() {
+        mSearchText.clearFocus();
+        for (Toolbar.OnSearchCompletedListener listener : mSearchCompletedListeners) {
+            listener.onSearchCompleted();
+        }
+    }
+
+    private boolean mWasShown = false;
+
+    @Override
+    public void onVisibilityChanged(@NonNull View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+
+        boolean isShown = isShown();
+        if (isShown && !mWasShown) {
+            boolean hasQuery = mSearchText.getText().length() > 0;
+            mCloseIcon.setVisibility(hasQuery ? View.VISIBLE : View.GONE);
+            mSearchText.requestFocus();
+        }
+        mWasShown = isShown;
+    }
+
+    /**
+     * Adds a listener for the search text changing.
+     * See also {@link #unregisterOnSearchListener(Toolbar.OnSearchListener)}
+     */
+    public void setSearchListeners(Set<Toolbar.OnSearchListener> listeners) {
+        mSearchListeners = listeners;
+    }
+
+    /**
+     * Removes a search listener.
+     * See also {@link #registerOnSearchListener(Toolbar.OnSearchListener)}
+     */
+    public void setSearchCompletedListeners(Set<Toolbar.OnSearchCompletedListener> listeners) {
+        mSearchCompletedListeners = listeners;
+    }
+
+    /**
+     * Sets the search hint.
+     *
+     * @param resId A string resource id of the search hint.
+     */
+    public void setHint(int resId) {
+        mSearchText.setHint(resId);
+    }
+
+    /**
+     * Sets the search hint
+     *
+     * @param hint A CharSequence of the search hint.
+     */
+    public void setHint(CharSequence hint) {
+        mSearchText.setHint(hint);
+    }
+
+    /** Gets the search hint */
+    public CharSequence getHint() {
+        return mSearchText.getHint();
+    }
+
+    /**
+     * Sets a custom icon to display in the search box.
+     */
+    public void setIcon(Drawable d) {
+        if (d == null) {
+            mIcon.setImageResource(R.drawable.car_ui_icon_search);
+        } else {
+            mIcon.setImageDrawable(d);
+        }
+    }
+
+    /**
+     * Sets a custom icon to display in the search box.
+     */
+    public void setIcon(int resId) {
+        if (resId == 0) {
+            mIcon.setImageResource(R.drawable.car_ui_icon_search);
+        } else {
+            mIcon.setImageResource(resId);
+        }
+    }
+
+    /**
+     * Sets whether or not the search bar should look like a regular text box
+     * instead of a search box.
+     */
+    public void setPlainText(boolean plainText) {
+        if (plainText != mIsPlainText) {
+            if (plainText) {
+                mSearchText.setPaddingRelative(mStartPaddingWithoutIcon, 0, mEndPadding, 0);
+                mSearchText.setImeOptions(EditorInfo.IME_ACTION_DONE);
+                mIcon.setVisibility(View.GONE);
+            } else {
+                mSearchText.setPaddingRelative(mStartPadding, 0, mEndPadding, 0);
+                mSearchText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
+                mIcon.setVisibility(View.VISIBLE);
+            }
+            mIsPlainText = plainText;
+
+            // Needed to detect changes to imeOptions
+            mInputMethodManager.restartInput(mSearchText);
+        }
+    }
+
+    private void onSearch(String query) {
+        mCloseIcon.setVisibility(TextUtils.isEmpty(query) ? View.GONE : View.VISIBLE);
+
+        for (Toolbar.OnSearchListener listener : mSearchListeners) {
+            listener.onSearch(query);
+        }
+    }
+
+    /**
+     * Sets the text being searched.
+     */
+    public void setSearchQuery(String query) {
+        mSearchText.setText(query);
+        mSearchText.setSelection(mSearchText.getText().length());
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/TabLayout.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/TabLayout.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/toolbar/TabLayout.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/TabLayout.java
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/Toolbar.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/Toolbar.java
new file mode 100644
index 0000000..45e7dce
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/Toolbar.java
@@ -0,0 +1,683 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.toolbar;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.annotation.XmlRes;
+
+import com.android.car.ui.R;
+
+import java.util.List;
+
+/**
+ * A toolbar for Android Automotive OS apps.
+ *
+ * <p>This isn't a toolbar in the android framework sense, it's merely a custom view that can be
+ * added to a layout. (You can't call
+ * {@link android.app.Activity#setActionBar(android.widget.Toolbar)} with it)
+ *
+ * <p>The toolbar supports a navigation button, title, tabs, search, and {@link MenuItem MenuItems}
+ *
+ * @deprecated Instead of creating this class, use Theme.CarUi.WithToolbar, and get access to it
+ *             via {@link com.android.car.ui.core.CarUi#requireToolbar(android.app.Activity)}
+ */
+@Deprecated
+public final class Toolbar extends FrameLayout implements ToolbarController {
+
+    /** Callback that will be issued whenever the height of toolbar is changed. */
+    public interface OnHeightChangedListener {
+        /**
+         * Will be called when the height of the toolbar is changed.
+         *
+         * @param height new height of the toolbar
+         */
+        void onHeightChanged(int height);
+    }
+
+    /** Back button listener */
+    public interface OnBackListener {
+        /**
+         * Invoked when the user clicks on the back button. By default, the toolbar will call
+         * the Activity's {@link android.app.Activity#onBackPressed()}. Returning true from
+         * this method will absorb the back press and prevent that behavior.
+         */
+        boolean onBack();
+    }
+
+    /** Tab selection listener */
+    public interface OnTabSelectedListener {
+        /** Called when a {@link TabLayout.Tab} is selected */
+        void onTabSelected(TabLayout.Tab tab);
+    }
+
+    /** Search listener */
+    public interface OnSearchListener {
+        /**
+         * Invoked when the user edits a search query.
+         *
+         * <p>This is called for every letter the user types, and also empty strings if the user
+         * erases everything.
+         */
+        void onSearch(String query);
+    }
+
+    /** Search completed listener */
+    public interface OnSearchCompletedListener {
+        /**
+         * Invoked when the user submits a search query by clicking the keyboard's search / done
+         * button.
+         */
+        void onSearchCompleted();
+    }
+
+    private static final String TAG = "CarUiToolbar";
+
+    /** Enum of states the toolbar can be in. Controls what elements of the toolbar are displayed */
+    public enum State {
+        /**
+         * In the HOME state, the logo will be displayed if there is one, and no navigation icon
+         * will be displayed. The tab bar will be visible. The title will be displayed if there
+         * is space. MenuItems will be displayed.
+         */
+        HOME,
+        /**
+         * In the SUBPAGE state, the logo will be replaced with a back button, the tab bar won't
+         * be visible. The title and MenuItems will be displayed.
+         */
+        SUBPAGE,
+        /**
+         * In the SEARCH state, only the back button and the search bar will be visible.
+         */
+        SEARCH,
+        /**
+         * In the EDIT state, the search bar will look like a regular text box, but will be
+         * functionally identical to the SEARCH state.
+         */
+        EDIT,
+    }
+
+    private ToolbarControllerImpl mController;
+    private boolean mEatingTouch = false;
+    private boolean mEatingHover = false;
+
+    public Toolbar(Context context) {
+        this(context, null);
+    }
+
+    public Toolbar(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.CarUiToolbarStyle);
+    }
+
+    public Toolbar(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public Toolbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(getToolbarLayout(), this, true);
+
+        mController = new ToolbarControllerImpl(this);
+
+        TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.CarUiToolbar, defStyleAttr, defStyleRes);
+
+        try {
+            setShowTabsInSubpage(a.getBoolean(R.styleable.CarUiToolbar_showTabsInSubpage, false));
+            setTitle(a.getString(R.styleable.CarUiToolbar_title));
+            setLogo(a.getResourceId(R.styleable.CarUiToolbar_logo, 0));
+            setBackgroundShown(a.getBoolean(R.styleable.CarUiToolbar_showBackground, true));
+            setMenuItems(a.getResourceId(R.styleable.CarUiToolbar_menuItems, 0));
+            String searchHint = a.getString(R.styleable.CarUiToolbar_searchHint);
+            if (searchHint != null) {
+                setSearchHint(searchHint);
+            }
+
+            switch (a.getInt(R.styleable.CarUiToolbar_car_ui_state, 0)) {
+                case 0:
+                    setState(State.HOME);
+                    break;
+                case 1:
+                    setState(State.SUBPAGE);
+                    break;
+                case 2:
+                    setState(State.SEARCH);
+                    break;
+                default:
+                    if (Log.isLoggable(TAG, Log.WARN)) {
+                        Log.w(TAG, "Unknown initial state");
+                    }
+                    break;
+            }
+
+            switch (a.getInt(R.styleable.CarUiToolbar_car_ui_navButtonMode, 0)) {
+                case 0:
+                    setNavButtonMode(NavButtonMode.BACK);
+                    break;
+                case 1:
+                    setNavButtonMode(NavButtonMode.CLOSE);
+                    break;
+                case 2:
+                    setNavButtonMode(NavButtonMode.DOWN);
+                    break;
+                default:
+                    if (Log.isLoggable(TAG, Log.WARN)) {
+                        Log.w(TAG, "Unknown navigation button style");
+                    }
+                    break;
+            }
+        } finally {
+            a.recycle();
+        }
+    }
+
+    /**
+     * Override this in a subclass to allow for different toolbar layouts within a single app.
+     *
+     * <p>Non-system apps should not use this, as customising the layout isn't possible with RROs
+     */
+    protected int getToolbarLayout() {
+        if (getContext().getResources().getBoolean(
+                R.bool.car_ui_toolbar_tabs_on_second_row)) {
+            return R.layout.car_ui_toolbar_two_row;
+        }
+
+        return R.layout.car_ui_toolbar;
+    }
+
+    /**
+     * Returns {@code true} if a two row layout in enabled for the toolbar.
+     */
+    @Override
+    public boolean isTabsInSecondRow() {
+        return mController.isTabsInSecondRow();
+    }
+
+    /**
+     * Sets the title of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setTitle(@StringRes int title) {
+        mController.setTitle(title);
+    }
+
+    /**
+     * Sets the title of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setTitle(CharSequence title) {
+        mController.setTitle(title);
+    }
+
+    @Override
+    public CharSequence getTitle() {
+        return mController.getTitle();
+    }
+
+    /**
+     * Sets the subtitle of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(@StringRes int title) {
+        mController.setSubtitle(title);
+    }
+
+    /**
+     * Sets the subtitle of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(CharSequence title) {
+        mController.setSubtitle(title);
+    }
+
+    @Override
+    public CharSequence getSubtitle() {
+        return mController.getSubtitle();
+    }
+
+    /**
+     * Gets the {@link TabLayout} for this toolbar.
+     * @deprecated Use other tab-related functions in the ToolbarController interface.
+     */
+    @Deprecated
+    @Override
+    public TabLayout getTabLayout() {
+        return mController.getTabLayout();
+    }
+
+    /**
+     * Gets the number of tabs in the toolbar. The tabs can be retrieved using
+     * {@link #getTab(int)}.
+     */
+    @Override
+    public int getTabCount() {
+        return mController.getTabCount();
+    }
+
+    /**
+     * Gets the index of the tab.
+     */
+    @Override
+    public int getTabPosition(TabLayout.Tab tab) {
+        return mController.getTabPosition(tab);
+    }
+
+    /**
+     * Adds a tab to this toolbar. You can listen for when it is selected via
+     * {@link #registerOnTabSelectedListener(OnTabSelectedListener)}.
+     */
+    @Override
+    public void addTab(TabLayout.Tab tab) {
+        mController.addTab(tab);
+    }
+
+    /** Removes all the tabs. */
+    @Override
+    public void clearAllTabs() {
+        mController.clearAllTabs();
+    }
+
+    /**
+     * Gets a tab added to this toolbar. See
+     * {@link #addTab(TabLayout.Tab)}.
+     */
+    @Override
+    public TabLayout.Tab getTab(int position) {
+        return mController.getTab(position);
+    }
+
+    /**
+     * Selects a tab added to this toolbar. See
+     * {@link #addTab(TabLayout.Tab)}.
+     */
+    @Override
+    public void selectTab(int position) {
+        mController.selectTab(position);
+    }
+
+    /**
+     * Sets whether or not tabs should also be shown in the SUBPAGE {@link State}.
+     */
+    @Override
+    public void setShowTabsInSubpage(boolean showTabs) {
+        mController.setShowTabsInSubpage(showTabs);
+    }
+
+    /**
+     * Gets whether or not tabs should also be shown in the SUBPAGE {@link State}.
+     */
+    @Override
+    public boolean getShowTabsInSubpage() {
+        return mController.getShowTabsInSubpage();
+    }
+
+    /**
+     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
+     * will be displayed next to the title.
+     */
+    @Override
+    public void setLogo(@DrawableRes int resId) {
+        mController.setLogo(resId);
+    }
+
+    /**
+     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
+     * will be displayed next to the title.
+     */
+    @Override
+    public void setLogo(Drawable drawable) {
+        mController.setLogo(drawable);
+    }
+
+    /** Sets the hint for the search bar. */
+    @Override
+    public void setSearchHint(@StringRes int resId) {
+        mController.setSearchHint(resId);
+    }
+
+    /** Sets the hint for the search bar. */
+    @Override
+    public void setSearchHint(CharSequence hint) {
+        mController.setSearchHint(hint);
+    }
+
+    /** Gets the search hint */
+    @Override
+    public CharSequence getSearchHint() {
+        return mController.getSearchHint();
+    }
+
+    /**
+     * Sets the icon to display in the search box.
+     *
+     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
+     * a similar place.
+     */
+    @Override
+    public void setSearchIcon(@DrawableRes int resId) {
+        mController.setSearchIcon(resId);
+    }
+
+    /**
+     * Sets the icon to display in the search box.
+     *
+     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
+     * a similar place.
+     */
+    @Override
+    public void setSearchIcon(Drawable d) {
+        mController.setSearchIcon(d);
+    }
+
+    /**
+     * An enum of possible styles the nav button could be in. All styles will still call
+     * {@link OnBackListener#onBack()}.
+     */
+    public enum NavButtonMode {
+        /** A back button */
+        BACK,
+        /** A close button */
+        CLOSE,
+        /** A down button, used to indicate that the page will animate down when navigating away */
+        DOWN
+    }
+
+    /** Sets the {@link NavButtonMode} */
+    @Override
+    public void setNavButtonMode(NavButtonMode style) {
+        mController.setNavButtonMode(style);
+    }
+
+    /** Gets the {@link NavButtonMode} */
+    @Override
+    public NavButtonMode getNavButtonMode() {
+        return mController.getNavButtonMode();
+    }
+
+    /**
+     * setBackground is disallowed, to prevent apps from deviating from the intended style too much.
+     */
+    @Override
+    public void setBackground(Drawable d) {
+        throw new UnsupportedOperationException(
+                "You can not change the background of a CarUi toolbar, use "
+                        + "setBackgroundShown(boolean) or an RRO instead.");
+    }
+
+    /** Show/hide the background. When hidden, the toolbar is completely transparent. */
+    @Override
+    public void setBackgroundShown(boolean shown) {
+        mController.setBackgroundShown(shown);
+    }
+
+    /** Returns true is the toolbar background is shown */
+    @Override
+    public boolean getBackgroundShown() {
+        return mController.getBackgroundShown();
+    }
+
+    /**
+     * Sets the {@link MenuItem Menuitems} to display.
+     */
+    @Override
+    public void setMenuItems(@Nullable List<MenuItem> items) {
+        mController.setMenuItems(items);
+    }
+
+    /**
+     * Sets the {@link MenuItem Menuitems} to display to a list defined in XML.
+     *
+     * <p>If this method is called twice with the same argument (and {@link #setMenuItems(List)}
+     * wasn't called), nothing will happen the second time, even if the MenuItems were changed.
+     *
+     * <p>The XML file must have one <MenuItems> tag, with a variable number of <MenuItem>
+     * child tags. See CarUiToolbarMenuItem in CarUi's attrs.xml for a list of available attributes.
+     *
+     * Example:
+     * <pre>
+     * <MenuItems>
+     *     <MenuItem
+     *         app:title="Foo"/>
+     *     <MenuItem
+     *         app:title="Bar"
+     *         app:icon="@drawable/ic_tracklist"
+     *         app:onClick="xmlMenuItemClicked"/>
+     *     <MenuItem
+     *         app:title="Bar"
+     *         app:checkable="true"
+     *         app:uxRestrictions="FULLY_RESTRICTED"
+     *         app:onClick="xmlMenuItemClicked"/>
+     * </MenuItems>
+     * </pre>
+     *
+     * @return The MenuItems that were loaded from XML.
+     * @see #setMenuItems(List)
+     */
+    @Override
+    public List<MenuItem> setMenuItems(@XmlRes int resId) {
+        return mController.setMenuItems(resId);
+    }
+
+    /** Gets the {@link MenuItem MenuItems} currently displayed */
+    @Override
+    @NonNull
+    public List<MenuItem> getMenuItems() {
+        return mController.getMenuItems();
+    }
+
+    /** Gets a {@link MenuItem} by id. */
+    @Override
+    @Nullable
+    public MenuItem findMenuItemById(int id) {
+        return mController.findMenuItemById(id);
+    }
+
+    /** Gets a {@link MenuItem} by id. Will throw an exception if not found. */
+    @Override
+    @NonNull
+    public MenuItem requireMenuItemById(int id) {
+        return mController.requireMenuItemById(id);
+    }
+
+    /**
+     * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
+     * Even if this is set to true, the {@link MenuItem} created by
+     * {@link MenuItem.Builder#setToSearch()} will still be hidden.
+     */
+    @Override
+    public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
+        mController.setShowMenuItemsWhileSearching(showMenuItems);
+    }
+
+    /** Returns if {@link MenuItem MenuItems} are shown while searching */
+    @Override
+    public boolean getShowMenuItemsWhileSearching() {
+        return mController.getShowMenuItemsWhileSearching();
+    }
+
+    /**
+     * Sets the search query.
+     */
+    @Override
+    public void setSearchQuery(String query) {
+        mController.setSearchQuery(query);
+    }
+
+    /**
+     * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
+     * for the desired state.
+     */
+    @Override
+    public void setState(State state) {
+        mController.setState(state);
+    }
+
+    /** Gets the current {@link State} of the toolbar. */
+    @Override
+    public State getState() {
+        return mController.getState();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        // Copied from androidx.appcompat.widget.Toolbar
+
+        // Toolbars always eat touch events, but should still respect the touch event dispatch
+        // contract. If the normal View implementation doesn't want the events, we'll just silently
+        // eat the rest of the gesture without reporting the events to the default implementation
+        // since that's what it expects.
+
+        final int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_DOWN) {
+            mEatingTouch = false;
+        }
+
+        if (!mEatingTouch) {
+            final boolean handled = super.onTouchEvent(ev);
+            if (action == MotionEvent.ACTION_DOWN && !handled) {
+                mEatingTouch = true;
+            }
+        }
+
+        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+            mEatingTouch = false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent ev) {
+        // Copied from androidx.appcompat.widget.Toolbar
+
+        // Same deal as onTouchEvent() above. Eat all hover events, but still
+        // respect the touch event dispatch contract.
+
+        final int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_HOVER_ENTER) {
+            mEatingHover = false;
+        }
+
+        if (!mEatingHover) {
+            final boolean handled = super.onHoverEvent(ev);
+            if (action == MotionEvent.ACTION_HOVER_ENTER && !handled) {
+                mEatingHover = true;
+            }
+        }
+
+        if (action == MotionEvent.ACTION_HOVER_EXIT || action == MotionEvent.ACTION_CANCEL) {
+            mEatingHover = false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Registers a new {@link OnHeightChangedListener} to the list of listeners. Register a
+     * {@link com.android.car.ui.recyclerview.CarUiRecyclerView} only if there is a toolbar at
+     * the top and a {@link com.android.car.ui.recyclerview.CarUiRecyclerView} in the view and
+     * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
+     * automatically adjust its height according to the height of the Toolbar.
+     */
+    @Override
+    public void registerToolbarHeightChangeListener(
+            OnHeightChangedListener listener) {
+        mController.registerToolbarHeightChangeListener(listener);
+    }
+
+    /** Unregisters an existing {@link OnHeightChangedListener} from the list of listeners. */
+    @Override
+    public boolean unregisterToolbarHeightChangeListener(
+            OnHeightChangedListener listener) {
+        return mController.unregisterToolbarHeightChangeListener(listener);
+    }
+
+    /** Registers a new {@link OnTabSelectedListener} to the list of listeners. */
+    @Override
+    public void registerOnTabSelectedListener(OnTabSelectedListener listener) {
+        mController.registerOnTabSelectedListener(listener);
+    }
+
+    /** Unregisters an existing {@link OnTabSelectedListener} from the list of listeners. */
+    @Override
+    public boolean unregisterOnTabSelectedListener(OnTabSelectedListener listener) {
+        return mController.unregisterOnTabSelectedListener(listener);
+    }
+
+    /** Registers a new {@link OnSearchListener} to the list of listeners. */
+    @Override
+    public void registerOnSearchListener(OnSearchListener listener) {
+        mController.registerOnSearchListener(listener);
+    }
+
+    /** Unregisters an existing {@link OnSearchListener} from the list of listeners. */
+    @Override
+    public boolean unregisterOnSearchListener(OnSearchListener listener) {
+        return mController.unregisterOnSearchListener(listener);
+    }
+
+    /** Registers a new {@link OnSearchCompletedListener} to the list of listeners. */
+    @Override
+    public void registerOnSearchCompletedListener(OnSearchCompletedListener listener) {
+        mController.registerOnSearchCompletedListener(listener);
+    }
+
+    /** Unregisters an existing {@link OnSearchCompletedListener} from the list of listeners. */
+    @Override
+    public boolean unregisterOnSearchCompletedListener(OnSearchCompletedListener listener) {
+        return mController.unregisterOnSearchCompletedListener(listener);
+    }
+
+    /** Registers a new {@link OnBackListener} to the list of listeners. */
+    @Override
+    public void registerOnBackListener(OnBackListener listener) {
+        mController.registerOnBackListener(listener);
+    }
+
+    /** Unregisters an existing {@link OnBackListener} from the list of listeners. */
+    @Override
+    public boolean unregisterOnBackListener(OnBackListener listener) {
+        return mController.unregisterOnBackListener(listener);
+    }
+
+    /** Returns the progress bar */
+    @Override
+    public ProgressBarController getProgressBar() {
+        return mController.getProgressBar();
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarController.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarController.java
new file mode 100644
index 0000000..d3e3910
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarController.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2020 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.car.ui.toolbar;
+
+import android.graphics.drawable.Drawable;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.annotation.XmlRes;
+
+import java.util.List;
+
+/**
+ * An interface for accessing a Chassis Toolbar, regardless of how the underlying
+ * views are represented.
+ */
+public interface ToolbarController {
+
+    /**
+     * Returns {@code true} if a two row layout in enabled for the toolbar.
+     */
+    boolean isTabsInSecondRow();
+
+    /**
+     * Sets the title of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    void setTitle(@StringRes int title);
+
+    /**
+     * Sets the title of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    void setTitle(CharSequence title);
+
+    /**
+     * Gets the current toolbar title.
+     */
+    CharSequence getTitle();
+
+    /**
+     * Sets the subtitle of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    void setSubtitle(@StringRes int title);
+
+    /**
+     * Sets the subtitle of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    void setSubtitle(CharSequence title);
+
+    /**
+     * Gets the current toolbar subtitle.
+     */
+    CharSequence getSubtitle();
+
+    /**
+     * Gets the {@link TabLayout} for this toolbar.
+     * @deprecated Use other tab-related functions in this interface.
+     */
+    @Deprecated
+    TabLayout getTabLayout();
+
+    /**
+     * Gets the number of tabs in the toolbar. The tabs can be retrieved using
+     * {@link #getTab(int)}.
+     */
+    int getTabCount();
+
+    /**
+     * Gets the index of the tab.
+     */
+    int getTabPosition(TabLayout.Tab tab);
+
+    /**
+     * Adds a tab to this toolbar. You can listen for when it is selected via
+     * {@link #registerOnTabSelectedListener(Toolbar.OnTabSelectedListener)}.
+     */
+    void addTab(TabLayout.Tab tab);
+
+    /** Removes all the tabs. */
+    void clearAllTabs();
+
+    /**
+     * Gets a tab added to this toolbar. See
+     * {@link #addTab(TabLayout.Tab)}.
+     */
+    TabLayout.Tab getTab(int position);
+
+    /**
+     * Selects a tab added to this toolbar. See
+     * {@link #addTab(TabLayout.Tab)}.
+     */
+    void selectTab(int position);
+
+    /**
+     * Sets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
+     */
+    void setShowTabsInSubpage(boolean showTabs);
+
+    /**
+     * Gets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
+     */
+    boolean getShowTabsInSubpage();
+
+    /**
+     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
+     * will be displayed next to the title.
+     */
+    void setLogo(@DrawableRes int resId);
+
+    /**
+     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
+     * will be displayed next to the title.
+     */
+    void setLogo(Drawable drawable);
+
+    /** Sets the hint for the search bar. */
+    void setSearchHint(@StringRes int resId);
+
+    /** Sets the hint for the search bar. */
+    void setSearchHint(CharSequence hint);
+
+    /** Gets the search hint */
+    CharSequence getSearchHint();
+
+    /**
+     * Sets the icon to display in the search box.
+     *
+     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
+     * a similar place.
+     */
+    void setSearchIcon(@DrawableRes int resId);
+
+    /**
+     * Sets the icon to display in the search box.
+     *
+     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
+     * a similar place.
+     */
+    void setSearchIcon(Drawable d);
+
+
+    /** Sets the {@link Toolbar.NavButtonMode} */
+    void setNavButtonMode(Toolbar.NavButtonMode style);
+
+    /** Gets the {@link Toolbar.NavButtonMode} */
+    Toolbar.NavButtonMode getNavButtonMode();
+
+    /** Show/hide the background. When hidden, the toolbar is completely transparent. */
+    void setBackgroundShown(boolean shown);
+
+    /** Returns true is the toolbar background is shown */
+    boolean getBackgroundShown();
+
+    /**
+     * Sets the {@link MenuItem Menuitems} to display.
+     */
+    void setMenuItems(@Nullable List<MenuItem> items);
+
+    /**
+     * Sets the {@link MenuItem Menuitems} to display to a list defined in XML.
+     *
+     * <p>If this method is called twice with the same argument (and {@link #setMenuItems(List)}
+     * wasn't called), nothing will happen the second time, even if the MenuItems were changed.
+     *
+     * <p>The XML file must have one <MenuItems> tag, with a variable number of <MenuItem>
+     * child tags. See CarUiToolbarMenuItem in CarUi's attrs.xml for a list of available attributes.
+     *
+     * Example:
+     * <pre>
+     * <MenuItems>
+     *     <MenuItem
+     *         app:title="Foo"/>
+     *     <MenuItem
+     *         app:title="Bar"
+     *         app:icon="@drawable/ic_tracklist"
+     *         app:onClick="xmlMenuItemClicked"/>
+     *     <MenuItem
+     *         app:title="Bar"
+     *         app:checkable="true"
+     *         app:uxRestrictions="FULLY_RESTRICTED"
+     *         app:onClick="xmlMenuItemClicked"/>
+     * </MenuItems>
+     * </pre>
+     *
+     * @return The MenuItems that were loaded from XML.
+     * @see #setMenuItems(List)
+     */
+    List<MenuItem> setMenuItems(@XmlRes int resId);
+
+    /** Gets the {@link MenuItem MenuItems} currently displayed */
+    @NonNull
+    List<MenuItem> getMenuItems();
+
+    /** Gets a {@link MenuItem} by id. */
+    @Nullable
+    MenuItem findMenuItemById(int id);
+
+    /** Gets a {@link MenuItem} by id. Will throw an IllegalArgumentException if not found. */
+    @NonNull
+    MenuItem requireMenuItemById(int id);
+
+    /**
+     * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
+     * Even if this is set to true, the {@link MenuItem} created by
+     * {@link MenuItem.Builder#setToSearch()} will still be hidden.
+     */
+    void setShowMenuItemsWhileSearching(boolean showMenuItems);
+
+    /** Returns if {@link MenuItem MenuItems} are shown while searching */
+    boolean getShowMenuItemsWhileSearching();
+
+    /**
+     * Sets the search query.
+     */
+    void setSearchQuery(String query);
+
+    /**
+     * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
+     * for the desired state.
+     */
+    void setState(Toolbar.State state);
+
+    /** Gets the current {@link Toolbar.State} of the toolbar. */
+    Toolbar.State getState();
+
+    /**
+     * Registers a new {@link Toolbar.OnHeightChangedListener} to the list of listeners. Register a
+     * {@link com.android.car.ui.recyclerview.CarUiRecyclerView} only if there is a toolbar at
+     * the top and a {@link com.android.car.ui.recyclerview.CarUiRecyclerView} in the view and
+     * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
+     * automatically adjust its height according to the height of the Toolbar.
+     */
+    void registerToolbarHeightChangeListener(Toolbar.OnHeightChangedListener listener);
+
+    /** Unregisters an existing {@link Toolbar.OnHeightChangedListener} from the list of
+     * listeners. */
+    boolean unregisterToolbarHeightChangeListener(Toolbar.OnHeightChangedListener listener);
+
+    /** Registers a new {@link Toolbar.OnTabSelectedListener} to the list of listeners. */
+    void registerOnTabSelectedListener(Toolbar.OnTabSelectedListener listener);
+
+    /** Unregisters an existing {@link Toolbar.OnTabSelectedListener} from the list of listeners. */
+    boolean unregisterOnTabSelectedListener(Toolbar.OnTabSelectedListener listener);
+
+    /** Registers a new {@link Toolbar.OnSearchListener} to the list of listeners. */
+    void registerOnSearchListener(Toolbar.OnSearchListener listener);
+
+    /** Unregisters an existing {@link Toolbar.OnSearchListener} from the list of listeners. */
+    boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener);
+
+    /** Registers a new {@link Toolbar.OnSearchCompletedListener} to the list of listeners. */
+    void registerOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener);
+
+    /** Unregisters an existing {@link Toolbar.OnSearchCompletedListener} from the list of
+     * listeners. */
+    boolean unregisterOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener);
+
+    /** Registers a new {@link Toolbar.OnBackListener} to the list of listeners. */
+    void registerOnBackListener(Toolbar.OnBackListener listener);
+
+    /** Unregisters an existing {@link Toolbar.OnBackListener} from the list of listeners. */
+    boolean unregisterOnBackListener(Toolbar.OnBackListener listener);
+
+    /** Gets a {@link ProgressBarController} */
+    ProgressBarController getProgressBar();
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarControllerImpl.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarControllerImpl.java
new file mode 100644
index 0000000..c3ce075
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarControllerImpl.java
@@ -0,0 +1,898 @@
+/*
+ * Copyright (C) 2020 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.car.ui.toolbar;
+
+import static android.view.View.GONE;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
+import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.annotation.XmlRes;
+
+import com.android.car.ui.AlertDialogBuilder;
+import com.android.car.ui.R;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
+import com.android.car.ui.utils.CarUiUtils;
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * The implementation of {@link ToolbarController}. This class takes a ViewGroup, and looks
+ * in the ViewGroup to find all the toolbar-related views to control.
+ */
+public final class ToolbarControllerImpl implements ToolbarController {
+    private static final String TAG = "CarUiToolbarController";
+
+    @Nullable
+    private View mBackground;
+    private ImageView mNavIcon;
+    private ImageView mLogoInNavIconSpace;
+    private ViewGroup mNavIconContainer;
+    private ViewGroup mTitleContainer;
+    private TextView mTitle;
+    private TextView mSubtitle;
+    private ImageView mTitleLogo;
+    private ViewGroup mTitleLogoContainer;
+    private TabLayout mTabLayout;
+    private ViewGroup mMenuItemsContainer;
+    private FrameLayout mSearchViewContainer;
+    private SearchView mSearchView;
+
+
+    // Cached values that we will send to views when they are inflated
+    private CharSequence mSearchHint;
+    private Drawable mSearchIcon;
+    private String mSearchQuery;
+    private final Context mContext;
+    private final Set<Toolbar.OnSearchListener> mOnSearchListeners = new HashSet<>();
+    private final Set<Toolbar.OnSearchCompletedListener> mOnSearchCompletedListeners =
+            new HashSet<>();
+
+    private final Set<Toolbar.OnBackListener> mOnBackListeners = new HashSet<>();
+    private final Set<Toolbar.OnTabSelectedListener> mOnTabSelectedListeners = new HashSet<>();
+    private final Set<Toolbar.OnHeightChangedListener> mOnHeightChangedListeners = new HashSet<>();
+
+    private final MenuItem mOverflowButton;
+    private final boolean mIsTabsInSecondRow;
+    private boolean mShowTabsInSubpage = false;
+    private boolean mHasLogo = false;
+    private boolean mShowMenuItemsWhileSearching;
+    private Toolbar.State mState = Toolbar.State.HOME;
+    private Toolbar.NavButtonMode mNavButtonMode = Toolbar.NavButtonMode.BACK;
+    @NonNull
+    private List<MenuItem> mMenuItems = Collections.emptyList();
+    private List<MenuItem> mOverflowItems = new ArrayList<>();
+    private final List<CarUiListItem> mUiOverflowItems = new ArrayList<>();
+    private final CarUiListItemAdapter mOverflowAdapter;
+    private final List<MenuItemRenderer> mMenuItemRenderers = new ArrayList<>();
+    private View[] mMenuItemViews;
+    private int mMenuItemsXmlId = 0;
+    private AlertDialog mOverflowDialog;
+    private boolean mNavIconSpaceReserved;
+    private boolean mLogoFillsNavIconSpace;
+    private boolean mShowLogo;
+    private final ProgressBarController mProgressBar;
+    private final MenuItem.Listener mOverflowItemListener = item -> {
+        updateOverflowDialog(item);
+        setState(getState());
+    };
+
+    // Despite the warning, this has to be a field so it's not garbage-collected.
+    // The only other reference to it is a weak reference
+    private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener
+            mOnUxRestrictionsChangedListener = restrictions -> {
+                for (MenuItemRenderer renderer : mMenuItemRenderers) {
+                    renderer.setCarUxRestrictions(restrictions);
+                }
+            };
+
+
+    public ToolbarControllerImpl(View view) {
+        mContext = view.getContext();
+        mOverflowButton = MenuItem.builder(getContext())
+                .setIcon(R.drawable.car_ui_icon_overflow_menu)
+                .setTitle(R.string.car_ui_toolbar_menu_item_overflow_title)
+                .setOnClickListener(v -> {
+                    if (mOverflowDialog == null) {
+                        if (Log.isLoggable(TAG, Log.ERROR)) {
+                            Log.e(TAG, "Overflow dialog was null when trying to show it!");
+                        }
+                    } else {
+                        mOverflowDialog.show();
+                    }
+                })
+                .build();
+
+        mIsTabsInSecondRow = getContext().getResources().getBoolean(
+                R.bool.car_ui_toolbar_tabs_on_second_row);
+        mNavIconSpaceReserved = getContext().getResources().getBoolean(
+                R.bool.car_ui_toolbar_nav_icon_reserve_space);
+        mLogoFillsNavIconSpace = getContext().getResources().getBoolean(
+                R.bool.car_ui_toolbar_logo_fills_nav_icon_space);
+        mShowLogo = getContext().getResources().getBoolean(
+                R.bool.car_ui_toolbar_show_logo);
+        mSearchHint = getContext().getString(R.string.car_ui_toolbar_default_search_hint);
+
+        mBackground = findViewByRefId(view, R.id.car_ui_toolbar_background);
+        mTabLayout = requireViewByRefId(view, R.id.car_ui_toolbar_tabs);
+        mNavIcon = requireViewByRefId(view, R.id.car_ui_toolbar_nav_icon);
+        mLogoInNavIconSpace = requireViewByRefId(view, R.id.car_ui_toolbar_logo);
+        mNavIconContainer = requireViewByRefId(view, R.id.car_ui_toolbar_nav_icon_container);
+        mMenuItemsContainer = requireViewByRefId(view, R.id.car_ui_toolbar_menu_items_container);
+        mTitleContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_container);
+        mSubtitle = requireViewByRefId(view, R.id.car_ui_toolbar_subtitle);
+        mTitle = requireViewByRefId(view, R.id.car_ui_toolbar_title);
+        mTitleLogoContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo_container);
+        mTitleLogo = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo);
+        mSearchViewContainer = requireViewByRefId(view, R.id.car_ui_toolbar_search_view_container);
+        mProgressBar = new ProgressBarControllerImpl(
+                requireViewByRefId(view, R.id.car_ui_toolbar_progress_bar));
+
+        mTabLayout.addListener(new TabLayout.Listener() {
+            @Override
+            public void onTabSelected(TabLayout.Tab tab) {
+                for (Toolbar.OnTabSelectedListener listener : mOnTabSelectedListeners) {
+                    listener.onTabSelected(tab);
+                }
+            }
+        });
+
+        if (mBackground != null) {
+            mBackground.addOnLayoutChangeListener((v, left, top, right, bottom,
+                    oldLeft, oldTop, oldRight, oldBottom) -> {
+                if (oldBottom - oldTop != bottom - top) {
+                    for (Toolbar.OnHeightChangedListener listener : mOnHeightChangedListeners) {
+                        listener.onHeightChanged(mBackground.getHeight());
+                    }
+                }
+            });
+        }
+
+        setBackgroundShown(true);
+
+        mOverflowAdapter = new CarUiListItemAdapter(mUiOverflowItems);
+
+        // This holds weak references so we don't need to unregister later
+        CarUxRestrictionsUtil.getInstance(getContext())
+                .register(mOnUxRestrictionsChangedListener);
+    }
+
+    private Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Returns {@code true} if a two row layout in enabled for the toolbar.
+     */
+    @Override
+    public boolean isTabsInSecondRow() {
+        return mIsTabsInSecondRow;
+    }
+
+    /**
+     * Sets the title of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setTitle(@StringRes int title) {
+        mTitle.setText(title);
+        setState(getState());
+    }
+
+    /**
+     * Sets the title of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setTitle(CharSequence title) {
+        mTitle.setText(title);
+        setState(getState());
+    }
+
+    @Override
+    public CharSequence getTitle() {
+        return mTitle.getText();
+    }
+
+    /**
+     * Sets the subtitle of the toolbar to a string resource.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(@StringRes int title) {
+        mSubtitle.setText(title);
+        setState(getState());
+    }
+
+    /**
+     * Sets the subtitle of the toolbar to a CharSequence.
+     *
+     * <p>The title may not always be shown, for example with one row layout with tabs.
+     */
+    @Override
+    public void setSubtitle(CharSequence title) {
+        mSubtitle.setText(title);
+        setState(getState());
+    }
+
+    @Override
+    public CharSequence getSubtitle() {
+        return mSubtitle.getText();
+    }
+
+    /**
+     * Gets the {@link TabLayout} for this toolbar.
+     * @deprecated Use other tab-related functions in the ToolbarController interface.
+     */
+    @Deprecated
+    @Override
+    public TabLayout getTabLayout() {
+        return mTabLayout;
+    }
+
+    /**
+     * Gets the number of tabs in the toolbar. The tabs can be retrieved using
+     * {@link #getTab(int)}.
+     */
+    @Override
+    public int getTabCount() {
+        return mTabLayout.getTabCount();
+    }
+
+    /**
+     * Gets the index of the tab.
+     */
+    @Override
+    public int getTabPosition(TabLayout.Tab tab) {
+        return mTabLayout.getTabPosition(tab);
+    }
+
+    /**
+     * Adds a tab to this toolbar. You can listen for when it is selected via
+     * {@link #registerOnTabSelectedListener(Toolbar.OnTabSelectedListener)}.
+     */
+    @Override
+    public void addTab(TabLayout.Tab tab) {
+        mTabLayout.addTab(tab);
+        setState(getState());
+    }
+
+    /** Removes all the tabs. */
+    @Override
+    public void clearAllTabs() {
+        mTabLayout.clearAllTabs();
+        setState(getState());
+    }
+
+    /**
+     * Gets a tab added to this toolbar. See
+     * {@link #addTab(TabLayout.Tab)}.
+     */
+    @Override
+    public TabLayout.Tab getTab(int position) {
+        return mTabLayout.get(position);
+    }
+
+    /**
+     * Selects a tab added to this toolbar. See
+     * {@link #addTab(TabLayout.Tab)}.
+     */
+    @Override
+    public void selectTab(int position) {
+        mTabLayout.selectTab(position);
+    }
+
+    /**
+     * Sets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
+     */
+    @Override
+    public void setShowTabsInSubpage(boolean showTabs) {
+        if (showTabs != mShowTabsInSubpage) {
+            mShowTabsInSubpage = showTabs;
+            setState(getState());
+        }
+    }
+
+    /**
+     * Gets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
+     */
+    @Override
+    public boolean getShowTabsInSubpage() {
+        return mShowTabsInSubpage;
+    }
+
+    /**
+     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
+     * will be displayed next to the title.
+     */
+    @Override
+    public void setLogo(@DrawableRes int resId) {
+        setLogo(resId != 0 ? getContext().getDrawable(resId) : null);
+    }
+
+    /**
+     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
+     * will be displayed next to the title.
+     */
+    @Override
+    public void setLogo(Drawable drawable) {
+        if (!mShowLogo) {
+            // If no logo should be shown then we act as if we never received one.
+            return;
+        }
+        if (drawable != null) {
+            mLogoInNavIconSpace.setImageDrawable(drawable);
+            mTitleLogo.setImageDrawable(drawable);
+            mHasLogo = true;
+        } else {
+            mHasLogo = false;
+        }
+        setState(mState);
+    }
+
+    /** Sets the hint for the search bar. */
+    @Override
+    public void setSearchHint(@StringRes int resId) {
+        setSearchHint(getContext().getString(resId));
+    }
+
+    /** Sets the hint for the search bar. */
+    public void setSearchHint(CharSequence hint) {
+        mSearchHint = hint;
+        if (mSearchView != null) {
+            mSearchView.setHint(mSearchHint);
+        }
+    }
+
+    /** Gets the search hint */
+    @Override
+    public CharSequence getSearchHint() {
+        return mSearchHint;
+    }
+
+    /**
+     * Sets the icon to display in the search box.
+     *
+     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
+     * a similar place.
+     */
+    @Override
+    public void setSearchIcon(@DrawableRes int resId) {
+        setSearchIcon(getContext().getDrawable(resId));
+    }
+
+    /**
+     * Sets the icon to display in the search box.
+     *
+     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
+     * a similar place.
+     */
+    @Override
+    public void setSearchIcon(Drawable d) {
+        if (!Objects.equals(d, mSearchIcon)) {
+            mSearchIcon = d;
+            if (mSearchView != null) {
+                mSearchView.setIcon(mSearchIcon);
+            }
+        }
+    }
+
+
+    /** Sets the {@link Toolbar.NavButtonMode} */
+    @Override
+    public void setNavButtonMode(Toolbar.NavButtonMode style) {
+        if (style != mNavButtonMode) {
+            mNavButtonMode = style;
+            setState(mState);
+        }
+    }
+
+    /** Gets the {@link Toolbar.NavButtonMode} */
+    @Override
+    public Toolbar.NavButtonMode getNavButtonMode() {
+        return mNavButtonMode;
+    }
+
+    /** Show/hide the background. When hidden, the toolbar is completely transparent. */
+    @Override
+    public void setBackgroundShown(boolean shown) {
+        if (mBackground == null) {
+            return;
+        }
+
+        if (shown) {
+            mBackground.setBackground(
+                    getContext().getDrawable(R.drawable.car_ui_toolbar_background));
+        } else {
+            mBackground.setBackground(null);
+        }
+    }
+
+    /** Returns true is the toolbar background is shown */
+    @Override
+    public boolean getBackgroundShown() {
+        if (mBackground == null) {
+            return true;
+        }
+
+        return mBackground.getBackground() != null;
+    }
+
+    private void setMenuItemsInternal(@Nullable List<MenuItem> items) {
+        if (items == null) {
+            items = Collections.emptyList();
+        }
+
+        List<MenuItem> visibleMenuItems = new ArrayList<>();
+        List<MenuItem> overflowItems = new ArrayList<>();
+        AtomicInteger loadedMenuItems = new AtomicInteger(0);
+
+        synchronized (this) {
+            if (items.equals(mMenuItems)) {
+                return;
+            }
+
+            for (MenuItem item : items) {
+                if (item.getDisplayBehavior() == MenuItem.DisplayBehavior.NEVER) {
+                    overflowItems.add(item);
+                    item.setListener(mOverflowItemListener);
+                } else {
+                    visibleMenuItems.add(item);
+                }
+            }
+
+            // Copy the list so that if the list is modified and setMenuItems is called again,
+            // the equals() check will fail. Note that the MenuItems are not copied here.
+            mMenuItems = new ArrayList<>(items);
+            mOverflowItems = overflowItems;
+            mMenuItemRenderers.clear();
+            mMenuItemsContainer.removeAllViews();
+
+            if (!overflowItems.isEmpty()) {
+                visibleMenuItems.add(mOverflowButton);
+                createOverflowDialog();
+            }
+
+            View[] menuItemViews = new View[visibleMenuItems.size()];
+            mMenuItemViews = menuItemViews;
+
+            for (int i = 0; i < visibleMenuItems.size(); ++i) {
+                int index = i;
+                MenuItem item = visibleMenuItems.get(i);
+                MenuItemRenderer renderer = new MenuItemRenderer(item, mMenuItemsContainer);
+                mMenuItemRenderers.add(renderer);
+                renderer.createView(view -> {
+                    synchronized (ToolbarControllerImpl.this) {
+                        if (menuItemViews != mMenuItemViews) {
+                            return;
+                        }
+
+                        menuItemViews[index] = view;
+                        if (loadedMenuItems.addAndGet(1) == menuItemViews.length) {
+                            for (View v : menuItemViews) {
+                                mMenuItemsContainer.addView(v);
+                            }
+                        }
+                    }
+                });
+            }
+        }
+
+        setState(mState);
+    }
+
+    /**
+     * Sets the {@link MenuItem Menuitems} to display.
+     */
+    @Override
+    public void setMenuItems(@Nullable List<MenuItem> items) {
+        mMenuItemsXmlId = 0;
+        setMenuItemsInternal(items);
+    }
+
+    /**
+     * Sets the {@link MenuItem Menuitems} to display to a list defined in XML.
+     *
+     * <p>If this method is called twice with the same argument (and {@link #setMenuItems(List)}
+     * wasn't called), nothing will happen the second time, even if the MenuItems were changed.
+     *
+     * <p>The XML file must have one <MenuItems> tag, with a variable number of <MenuItem>
+     * child tags. See CarUiToolbarMenuItem in CarUi's attrs.xml for a list of available attributes.
+     *
+     * Example:
+     * <pre>
+     * <MenuItems>
+     *     <MenuItem
+     *         app:title="Foo"/>
+     *     <MenuItem
+     *         app:title="Bar"
+     *         app:icon="@drawable/ic_tracklist"
+     *         app:onClick="xmlMenuItemClicked"/>
+     *     <MenuItem
+     *         app:title="Bar"
+     *         app:checkable="true"
+     *         app:uxRestrictions="FULLY_RESTRICTED"
+     *         app:onClick="xmlMenuItemClicked"/>
+     * </MenuItems>
+     * </pre>
+     *
+     * @return The MenuItems that were loaded from XML.
+     * @see #setMenuItems(List)
+     */
+    @Override
+    public List<MenuItem> setMenuItems(@XmlRes int resId) {
+        if (mMenuItemsXmlId != 0 && mMenuItemsXmlId == resId) {
+            return mMenuItems;
+        }
+
+        mMenuItemsXmlId = resId;
+        List<MenuItem> menuItems = MenuItemRenderer.readMenuItemList(getContext(), resId);
+        setMenuItemsInternal(menuItems);
+        return menuItems;
+    }
+
+    /** Gets the {@link MenuItem MenuItems} currently displayed */
+    @Override
+    @NonNull
+    public List<MenuItem> getMenuItems() {
+        return Collections.unmodifiableList(mMenuItems);
+    }
+
+    /** Gets a {@link MenuItem} by id. */
+    @Override
+    @Nullable
+    public MenuItem findMenuItemById(int id) {
+        for (MenuItem item : mMenuItems) {
+            if (item.getId() == id) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    /** Gets a {@link MenuItem} by id. Will throw an IllegalArgumentException if not found. */
+    @Override
+    @NonNull
+    public MenuItem requireMenuItemById(int id) {
+        MenuItem result = findMenuItemById(id);
+
+        if (result == null) {
+            throw new IllegalArgumentException("ID does not reference a MenuItem on this Toolbar");
+        }
+
+        return result;
+    }
+
+    private int countVisibleOverflowItems() {
+        int numVisibleItems = 0;
+        for (MenuItem item : mOverflowItems) {
+            if (item.isVisible()) {
+                numVisibleItems++;
+            }
+        }
+        return numVisibleItems;
+    }
+
+    private void createOverflowDialog() {
+        mUiOverflowItems.clear();
+        for (MenuItem menuItem : mOverflowItems) {
+            if (menuItem.isVisible()) {
+                mUiOverflowItems.add(toCarUiContentListItem(menuItem));
+            }
+        }
+
+        mOverflowDialog = new AlertDialogBuilder(getContext())
+                .setAdapter(mOverflowAdapter)
+                .create();
+    }
+
+    private void updateOverflowDialog(MenuItem changedItem) {
+        int itemIndex = mOverflowItems.indexOf(changedItem);
+        if (itemIndex >= 0) {
+            mUiOverflowItems.set(itemIndex, toCarUiContentListItem(changedItem));
+            mOverflowAdapter.notifyItemChanged(itemIndex);
+        } else {
+            createOverflowDialog();
+        }
+    }
+
+    private CarUiContentListItem toCarUiContentListItem(MenuItem menuItem) {
+        CarUiContentListItem carUiItem;
+        if (menuItem.isCheckable()) {
+            carUiItem = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
+        } else {
+            carUiItem = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        }
+        carUiItem.setIcon(menuItem.getIcon());
+        carUiItem.setActivated(menuItem.isActivated());
+        carUiItem.setChecked(menuItem.isChecked());
+        carUiItem.setEnabled(menuItem.isEnabled());
+        carUiItem.setTitle(menuItem.getTitle());
+        carUiItem.setOnItemClickedListener(item -> {
+            menuItem.performClick();
+            mOverflowDialog.hide();
+        });
+        return carUiItem;
+    }
+
+    /**
+     * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
+     * Even if this is set to true, the {@link MenuItem} created by
+     * {@link MenuItem.Builder#setToSearch()} will still be hidden.
+     */
+    @Override
+    public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
+        mShowMenuItemsWhileSearching = showMenuItems;
+        setState(mState);
+    }
+
+    /** Returns if {@link MenuItem MenuItems} are shown while searching */
+    @Override
+    public boolean getShowMenuItemsWhileSearching() {
+        return mShowMenuItemsWhileSearching;
+    }
+
+    /**
+     * Sets the search query.
+     */
+    @Override
+    public void setSearchQuery(String query) {
+        if (mSearchView != null) {
+            mSearchView.setSearchQuery(query);
+        } else {
+            mSearchQuery = query;
+            for (Toolbar.OnSearchListener listener : mOnSearchListeners) {
+                listener.onSearch(query);
+            }
+        }
+    }
+
+    /**
+     * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
+     * for the desired state.
+     */
+    @Override
+    public void setState(Toolbar.State state) {
+        mState = state;
+
+        if (mSearchView == null && (state == Toolbar.State.SEARCH || state == Toolbar.State.EDIT)) {
+            SearchView searchView = new SearchView(getContext());
+            searchView.setHint(mSearchHint);
+            searchView.setIcon(mSearchIcon);
+            searchView.setSearchQuery(mSearchQuery);
+            searchView.setSearchListeners(mOnSearchListeners);
+            searchView.setSearchCompletedListeners(mOnSearchCompletedListeners);
+            searchView.setVisibility(GONE);
+
+            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT);
+            mSearchViewContainer.addView(searchView, layoutParams);
+
+            mSearchView = searchView;
+        }
+
+        for (MenuItemRenderer renderer : mMenuItemRenderers) {
+            renderer.setToolbarState(mState);
+        }
+
+        View.OnClickListener backClickListener = (v) -> {
+            boolean absorbed = false;
+            List<Toolbar.OnBackListener> listenersCopy = new ArrayList<>(mOnBackListeners);
+            for (Toolbar.OnBackListener listener : listenersCopy) {
+                absorbed = absorbed || listener.onBack();
+            }
+
+            if (!absorbed) {
+                Activity activity = CarUiUtils.getActivity(getContext());
+                if (activity != null) {
+                    activity.onBackPressed();
+                }
+            }
+        };
+
+        if (state == Toolbar.State.SEARCH) {
+            mNavIcon.setImageResource(R.drawable.car_ui_icon_search_nav_icon);
+        } else {
+            switch (mNavButtonMode) {
+                case CLOSE:
+                    mNavIcon.setImageResource(R.drawable.car_ui_icon_close);
+                    break;
+                case DOWN:
+                    mNavIcon.setImageResource(R.drawable.car_ui_icon_down);
+                    break;
+                default:
+                    mNavIcon.setImageResource(R.drawable.car_ui_icon_arrow_back);
+                    break;
+            }
+        }
+
+        mNavIcon.setVisibility(state != Toolbar.State.HOME ? VISIBLE : GONE);
+
+        // Show the logo in the nav space if that's enabled, we have a logo,
+        // and we're in the Home state.
+        mLogoInNavIconSpace.setVisibility(mHasLogo
+                && state == Toolbar.State.HOME
+                && mLogoFillsNavIconSpace
+                ? VISIBLE : INVISIBLE);
+
+        // Show logo next to the title if we're in the subpage state or we're configured to not show
+        // the logo in the nav icon space.
+        mTitleLogoContainer.setVisibility(mHasLogo
+                && (state == Toolbar.State.SUBPAGE
+                || (state == Toolbar.State.HOME && !mLogoFillsNavIconSpace))
+                ? VISIBLE : GONE);
+
+        // Show the nav icon container if we're not in the home space or the logo fills the nav icon
+        // container. If car_ui_toolbar_nav_icon_reserve_space is true, hiding it will still reserve
+        // its space
+        mNavIconContainer.setVisibility(
+                state != Toolbar.State.HOME || (mHasLogo && mLogoFillsNavIconSpace)
+                        ? VISIBLE : (mNavIconSpaceReserved ? INVISIBLE : GONE));
+        mNavIconContainer.setOnClickListener(
+                state != Toolbar.State.HOME ? backClickListener : null);
+        mNavIconContainer.setClickable(state != Toolbar.State.HOME);
+        mNavIconContainer.setContentDescription(state != Toolbar.State.HOME
+                ? mContext.getString(R.string.car_ui_toolbar_nav_icon_content_description)
+                : null);
+
+        boolean hasTabs = mTabLayout.getTabCount() > 0
+                && (state == Toolbar.State.HOME
+                || (state == Toolbar.State.SUBPAGE && mShowTabsInSubpage));
+        // Show the title if we're in the subpage state, or in the home state with no tabs or tabs
+        // on the second row
+        int visibility = (state == Toolbar.State.SUBPAGE || state == Toolbar.State.HOME)
+                && (!hasTabs || mIsTabsInSecondRow)
+                ? VISIBLE : GONE;
+        mTitleContainer.setVisibility(visibility);
+        mSubtitle.setVisibility(
+                TextUtils.isEmpty(mSubtitle.getText()) ? GONE : VISIBLE);
+
+        mTabLayout.setVisibility(hasTabs ? VISIBLE : GONE);
+
+        if (mSearchView != null) {
+            if (state == Toolbar.State.SEARCH || state == Toolbar.State.EDIT) {
+                mSearchView.setPlainText(state == Toolbar.State.EDIT);
+                mSearchView.setVisibility(VISIBLE);
+            } else {
+                mSearchView.setVisibility(GONE);
+            }
+        }
+
+        boolean showButtons = (state != Toolbar.State.SEARCH && state != Toolbar.State.EDIT)
+                || mShowMenuItemsWhileSearching;
+        mMenuItemsContainer.setVisibility(showButtons ? VISIBLE : GONE);
+        mOverflowButton.setVisible(showButtons && countVisibleOverflowItems() > 0);
+    }
+
+    /** Gets the current {@link Toolbar.State} of the toolbar. */
+    @Override
+    public Toolbar.State getState() {
+        return mState;
+    }
+
+
+    /**
+     * Registers a new {@link Toolbar.OnHeightChangedListener} to the list of listeners. Register a
+     * {@link com.android.car.ui.recyclerview.CarUiRecyclerView} only if there is a toolbar at
+     * the top and a {@link com.android.car.ui.recyclerview.CarUiRecyclerView} in the view and
+     * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
+     * automatically adjust its height according to the height of the Toolbar.
+     */
+    @Override
+    public void registerToolbarHeightChangeListener(
+            Toolbar.OnHeightChangedListener listener) {
+        mOnHeightChangedListeners.add(listener);
+    }
+
+    /**
+     * Unregisters an existing {@link Toolbar.OnHeightChangedListener} from the list of
+     * listeners.
+     */
+    @Override
+    public boolean unregisterToolbarHeightChangeListener(
+            Toolbar.OnHeightChangedListener listener) {
+        return mOnHeightChangedListeners.remove(listener);
+    }
+
+    /** Registers a new {@link Toolbar.OnTabSelectedListener} to the list of listeners. */
+    @Override
+    public void registerOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
+        mOnTabSelectedListeners.add(listener);
+    }
+
+    /** Unregisters an existing {@link Toolbar.OnTabSelectedListener} from the list of listeners. */
+    @Override
+    public boolean unregisterOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
+        return mOnTabSelectedListeners.remove(listener);
+    }
+
+    /** Registers a new {@link Toolbar.OnSearchListener} to the list of listeners. */
+    @Override
+    public void registerOnSearchListener(Toolbar.OnSearchListener listener) {
+        mOnSearchListeners.add(listener);
+    }
+
+    /** Unregisters an existing {@link Toolbar.OnSearchListener} from the list of listeners. */
+    @Override
+    public boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener) {
+        return mOnSearchListeners.remove(listener);
+    }
+
+    /** Registers a new {@link Toolbar.OnSearchCompletedListener} to the list of listeners. */
+    @Override
+    public void registerOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
+        mOnSearchCompletedListeners.add(listener);
+    }
+
+    /**
+     * Unregisters an existing {@link Toolbar.OnSearchCompletedListener} from the list of
+     * listeners.
+     */
+    @Override
+    public boolean unregisterOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
+        return mOnSearchCompletedListeners.remove(listener);
+    }
+
+    /** Registers a new {@link Toolbar.OnBackListener} to the list of listeners. */
+    @Override
+    public void registerOnBackListener(Toolbar.OnBackListener listener) {
+        mOnBackListeners.add(listener);
+    }
+
+    /** Unregisters an existing {@link Toolbar.OnBackListener} from the list of listeners. */
+    @Override
+    public boolean unregisterOnBackListener(Toolbar.OnBackListener listener) {
+        return mOnBackListeners.remove(listener);
+    }
+
+    /** Returns the progress bar */
+    @Override
+    public ProgressBarController getProgressBar() {
+        return mProgressBar;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUiUtils.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUiUtils.java
new file mode 100644
index 0000000..ce4d8a5
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUiUtils.java
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.utils;
+
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_HORIZONTALLY_SCROLLABLE;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_VERTICALLY_SCROLLABLE;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.DimenRes;
+import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StyleRes;
+import androidx.annotation.UiThread;
+import androidx.core.view.ViewCompat;
+
+/**
+ * Collection of utility methods
+ */
+public final class CarUiUtils {
+    /** This is a utility class */
+    private CarUiUtils() {
+    }
+
+    /**
+     * Reads a float value from a dimens resource. This is necessary as {@link Resources#getFloat}
+     * is not currently public.
+     *
+     * @param res {@link Resources} to read values from
+     * @param resId Id of the dimens resource to read
+     */
+    public static float getFloat(Resources res, @DimenRes int resId) {
+        TypedValue outValue = new TypedValue();
+        res.getValue(resId, outValue, true);
+        return outValue.getFloat();
+    }
+
+    /** Returns the identifier of the resolved resource assigned to the given attribute. */
+    public static int getAttrResourceId(Context context, int attr) {
+        return getAttrResourceId(context, /*styleResId=*/ 0, attr);
+    }
+
+    /**
+     * Returns the identifier of the resolved resource assigned to the given attribute defined in
+     * the given style.
+     */
+    public static int getAttrResourceId(Context context, @StyleRes int styleResId, int attr) {
+        TypedArray ta = context.obtainStyledAttributes(styleResId, new int[]{attr});
+        int resId = ta.getResourceId(0, 0);
+        ta.recycle();
+        return resId;
+    }
+
+    /**
+     * Gets the {@link Activity} for a certain {@link Context}.
+     *
+     * <p>It is possible the Context is not associated with an Activity, in which case
+     * this method will return null.
+     */
+    @Nullable
+    public static Activity getActivity(Context context) {
+        while (context instanceof ContextWrapper) {
+            if (context instanceof Activity) {
+                return (Activity) context;
+            }
+            context = ((ContextWrapper) context).getBaseContext();
+        }
+        return null;
+    }
+
+    /**
+     * Updates the preference view enabled state. If the view is disabled we just disable the child
+     * of preference like TextView, ImageView. The preference itself is always enabled to get the
+     * click events. Ripple effect in background is also removed by default. If the ripple is
+     * needed see
+     * {@link IDisabledPreferenceCallback#setShouldShowRippleOnDisabledPreference(boolean)}
+     */
+    public static Drawable setPreferenceViewEnabled(boolean viewEnabled, View itemView,
+            Drawable background, boolean shouldShowRippleOnDisabledPreference) {
+        if (viewEnabled) {
+            if (background != null) {
+                ViewCompat.setBackground(itemView, background);
+            }
+            setChildViewsEnabled(itemView, true, false);
+        } else {
+            itemView.setEnabled(true);
+            if (background == null) {
+                // store the original background.
+                background = itemView.getBackground();
+            }
+            updateRippleStateOnDisabledPreference(false, shouldShowRippleOnDisabledPreference,
+                    background, itemView);
+            setChildViewsEnabled(itemView, false, true);
+        }
+        return background;
+    }
+
+    /**
+     * Sets the enabled state on the views of the preference. If the view is being disabled we want
+     * only child views of preference to be disabled.
+     */
+    private static void setChildViewsEnabled(View view, boolean enabled, boolean isRootView) {
+        if (!isRootView) {
+            view.setEnabled(enabled);
+        }
+        if (view instanceof ViewGroup) {
+            ViewGroup grp = (ViewGroup) view;
+            for (int index = 0; index < grp.getChildCount(); index++) {
+                setChildViewsEnabled(grp.getChildAt(index), enabled, false);
+            }
+        }
+    }
+
+    /**
+     * Updates the ripple state on the given preference.
+     *
+     * @param isEnabled whether the preference is enabled or not
+     * @param shouldShowRippleOnDisabledPreference should ripple be displayed when the preference is
+     * clicked
+     * @param background drawable that represents the ripple
+     * @param preference preference on which drawable will be applied
+     */
+    public static void updateRippleStateOnDisabledPreference(boolean isEnabled,
+            boolean shouldShowRippleOnDisabledPreference, Drawable background, View preference) {
+        if (isEnabled || preference == null) {
+            return;
+        }
+        if (shouldShowRippleOnDisabledPreference && background != null) {
+            ViewCompat.setBackground(preference, background);
+        } else {
+            ViewCompat.setBackground(preference, null);
+        }
+    }
+
+    /**
+     * Enables rotary scrolling for {@code view}, either vertically (if {@code isVertical} is true)
+     * or horizontally (if {@code isVertical} is false). With rotary scrolling enabled, rotating the
+     * rotary controller will scroll rather than moving the focus when moving the focus would cause
+     * a lot of scrolling. Rotary scrolling should be enabled for scrolling views which contain
+     * content which the user may want to see but can't interact with, either alone or along with
+     * interactive (focusable) content.
+     */
+    public static void setRotaryScrollEnabled(@NonNull View view, boolean isVertical) {
+        view.setContentDescription(
+                isVertical ? ROTARY_VERTICALLY_SCROLLABLE : ROTARY_HORIZONTALLY_SCROLLABLE);
+    }
+
+    /**
+     * It behaves similarly to {@link View#findViewById(int)}, except that on Q and below,
+     * it will first resolve the id to whatever it references.
+     *
+     * This is to support layout RROs before the new RRO features in R.
+     *
+     * @param id the ID to search for
+     * @return a view with given ID if found, or {@code null} otherwise
+     * @see View#requireViewById(int)
+     */
+    @Nullable
+    @UiThread
+    public static <T extends View> T findViewByRefId(@NonNull View root, @IdRes int id) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            return root.findViewById(id);
+        }
+
+        if (id == View.NO_ID) {
+            return null;
+        }
+
+        TypedValue value = new TypedValue();
+        root.getResources().getValue(id, value, true);
+        return root.findViewById(value.resourceId);
+    }
+
+    /**
+     * It behaves similarly to {@link View#requireViewById(int)}, except that on Q and below,
+     * it will first resolve the id to whatever it references.
+     *
+     * This is to support layout RROs before the new RRO features in R.
+     *
+     * @param id the ID to search for
+     * @return a view with given ID
+     * @see View#findViewById(int)
+     */
+    @NonNull
+    @UiThread
+    public static <T extends View> T requireViewByRefId(@NonNull View root, @IdRes int id) {
+        T view = findViewByRefId(root, id);
+        if (view == null) {
+            throw new IllegalArgumentException("ID "
+                    + root.getResources().getResourceName(id)
+                    + " does not reference a View inside this View");
+        }
+        return view;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUxRestrictionsUtil.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUxRestrictionsUtil.java
new file mode 100644
index 0000000..b4baf31
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUxRestrictionsUtil.java
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.utils;
+
+import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH;
+
+import android.car.Car;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo;
+import android.car.drivingstate.CarUxRestrictionsManager;
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.ui.R;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * Utility class to access Car Restriction Manager.
+ *
+ * <p>This class must be a singleton because only one listener can be registered with {@link
+ * CarUxRestrictionsManager} at a time, as documented in {@link
+ * CarUxRestrictionsManager#registerListener}.
+ */
+public class CarUxRestrictionsUtil {
+    private static final String TAG = "CarUxRestrictionsUtil";
+
+    @NonNull
+    private CarUxRestrictions mCarUxRestrictions = getDefaultRestrictions();
+
+    private final Set<OnUxRestrictionsChangedListener> mObservers =
+            Collections.newSetFromMap(new WeakHashMap<>());
+    private static CarUxRestrictionsUtil sInstance = null;
+
+    private CarUxRestrictionsUtil(Context context) {
+        CarUxRestrictionsManager.OnUxRestrictionsChangedListener listener =
+                (carUxRestrictions) -> {
+                    if (carUxRestrictions == null) {
+                        mCarUxRestrictions = getDefaultRestrictions();
+                    } else {
+                        mCarUxRestrictions = carUxRestrictions;
+                    }
+
+                    for (OnUxRestrictionsChangedListener observer : mObservers) {
+                        observer.onRestrictionsChanged(mCarUxRestrictions);
+                    }
+                };
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            Car.createCar(context.getApplicationContext(), null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+                    (Car car, boolean ready) -> {
+                        if (ready) {
+                            CarUxRestrictionsManager carUxRestrictionsManager =
+                                    (CarUxRestrictionsManager) car.getCarManager(
+                                            Car.CAR_UX_RESTRICTION_SERVICE);
+                            carUxRestrictionsManager.registerListener(listener);
+                            listener.onUxRestrictionsChanged(
+                                    carUxRestrictionsManager.getCurrentCarUxRestrictions());
+                        } else {
+                            Log.w(TAG, "Car service disconnected, assuming fully restricted uxr");
+                            listener.onUxRestrictionsChanged(null);
+                        }
+                    });
+        } else {
+            Car carApi = Car.createCar(context.getApplicationContext());
+
+            try {
+                CarUxRestrictionsManager carUxRestrictionsManager =
+                        (CarUxRestrictionsManager) carApi.getCarManager(
+                                Car.CAR_UX_RESTRICTION_SERVICE);
+                carUxRestrictionsManager.registerListener(listener);
+                listener.onUxRestrictionsChanged(
+                        carUxRestrictionsManager.getCurrentCarUxRestrictions());
+            } catch (NullPointerException e) {
+                Log.e(TAG, "Car not connected", e);
+                // mCarUxRestrictions will be the default
+            }
+        }
+    }
+
+    @NonNull
+    private static CarUxRestrictions getDefaultRestrictions() {
+        return new CarUxRestrictions.Builder(
+                true, CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0)
+                .build();
+    }
+
+    /** Listener interface used to update clients on UxRestrictions changes */
+    public interface OnUxRestrictionsChangedListener {
+        /** Called when CarUxRestrictions changes */
+        void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions);
+    }
+
+    /** Returns the singleton sInstance of this class */
+    @NonNull
+    public static CarUxRestrictionsUtil getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new CarUxRestrictionsUtil(context);
+        }
+
+        return sInstance;
+    }
+
+    /**
+     * Registers a listener on this class for updates to CarUxRestrictions. Multiple listeners may
+     * be registered. Note that this class will only hold a weak reference to the listener, you
+     * must maintain a strong reference to it elsewhere.
+     */
+    public void register(OnUxRestrictionsChangedListener listener) {
+        mObservers.add(listener);
+        listener.onRestrictionsChanged(mCarUxRestrictions);
+    }
+
+    /** Unregisters a registered listener */
+    public void unregister(OnUxRestrictionsChangedListener listener) {
+        mObservers.remove(listener);
+    }
+
+    @NonNull
+    public CarUxRestrictions getCurrentRestrictions() {
+        return mCarUxRestrictions;
+    }
+
+    /**
+     * Returns whether any of the given flags are blocked by the specified restrictions. If null is
+     * given, the method returns true for safety.
+     */
+    public static boolean isRestricted(
+            @CarUxRestrictionsInfo int restrictionFlags, @Nullable CarUxRestrictions uxr) {
+        return (uxr == null) || ((uxr.getActiveRestrictions() & restrictionFlags) != 0);
+    }
+
+    /**
+     * Complies the input string with the given UX restrictions. Returns the original string if
+     * already compliant, otherwise a shortened ellipsized string.
+     */
+    public static String complyString(Context context, String str, CarUxRestrictions uxr) {
+
+        if (isRestricted(UX_RESTRICTIONS_LIMIT_STRING_LENGTH, uxr)) {
+            int maxLength =
+                    uxr == null
+                            ? context.getResources().getInteger(
+                            R.integer.car_ui_default_max_string_length)
+                            : uxr.getMaxRestrictedStringLength();
+
+            if (str.length() > maxLength) {
+                return str.substring(0, maxLength) + context.getString(R.string.car_ui_ellipsis);
+            }
+        }
+
+        return str;
+    }
+
+    /** Sets car UX restrictions. Only used for testing. */
+    @VisibleForTesting
+    public void setUxRestrictions(CarUxRestrictions carUxRestrictions) {
+        mCarUxRestrictions = carUxRestrictions;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/DirectManipulationHelper.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/DirectManipulationHelper.java
new file mode 100644
index 0000000..184e522
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/DirectManipulationHelper.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 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.car.ui.utils;
+
+import static android.os.Build.VERSION_CODES.R;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import androidx.annotation.NonNull;
+
+/** Helper class to toggle direct manipulation mode. */
+public final class DirectManipulationHelper {
+
+    /**
+     * StateDescription for a {@link View} to support direct manipulation mode. It's also used as
+     * class name of {@link AccessibilityEvent} to indicate that the AccessibilityEvent represents
+     * a request to toggle direct manipulation mode.
+     */
+    private static final String DIRECT_MANIPULATION =
+            "com.android.car.ui.utils.DIRECT_MANIPULATION";
+
+    /** This is a utility class. */
+    private DirectManipulationHelper() {
+    }
+
+    /**
+     * Enables or disables direct manipulation mode. This method sends an {@link AccessibilityEvent}
+     * to tell {@link com.android.car.rotary.RotaryService} to enter or exit direct manipulation
+     * mode. Typically pressing the center button of the rotary controller with a direct
+     * manipulation view focused will enter direct manipulation mode, while pressing the Back button
+     * will exit direct manipulation mode.
+     *
+     * @param view   the direct manipulation view
+     * @param enable true to enter direct manipulation mode, false to exit direct manipulation mode
+     * @return whether the AccessibilityEvent was sent
+     */
+    public static boolean enableDirectManipulationMode(@NonNull View view, boolean enable) {
+        AccessibilityManager accessibilityManager = (AccessibilityManager)
+                view.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+        if (accessibilityManager == null || !accessibilityManager.isEnabled()) {
+            return false;
+        }
+        AccessibilityEvent event = AccessibilityEvent.obtain();
+        event.setClassName(DIRECT_MANIPULATION);
+        event.setSource(view);
+        event.setEventType(enable
+                ? AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
+                : AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+        accessibilityManager.sendAccessibilityEvent(event);
+        return true;
+    }
+
+    /** Returns whether the given {@code event} is for direct manipulation. */
+    public static boolean isDirectManipulation(@NonNull AccessibilityEvent event) {
+        return TextUtils.equals(DIRECT_MANIPULATION, event.getClassName());
+    }
+
+    /** Returns whether the given {@code node} supports rotate directly. */
+    @TargetApi(R)
+    public static boolean supportRotateDirectly(@NonNull AccessibilityNodeInfo node) {
+        return TextUtils.equals(DIRECT_MANIPULATION, node.getStateDescription());
+    }
+
+    /**
+     * Sets whether the given {@code view} supports rotate directly.
+     * <p>
+     * If the view supports rotate directly, when it's focused but not in direct manipulation mode,
+     * clicking the center button of the rotary controller will make RotaryService enter direct
+     * manipulation mode. In this mode, the view's selected state is toggled, and only controller
+     * rotation and Back button press are supported.
+     * <ul>
+     *   <li>When the controller is rotated, the view will be asked to perform ACTION_SCROLL_FORWARD
+     *       or ACTION_SCROLL_BACKWARD.
+     *   <li>When Back button is pressed, RotaryService will toggle off the view's selected state
+     *       and exit this mode.
+     * </ul>
+     * To support controller nudges as well in direct manipulation mode, use {@link
+     * #enableDirectManipulationMode} instead.
+     */
+    @TargetApi(R)
+    public static void setSupportsRotateDirectly(@NonNull View view, boolean enable) {
+        view.setStateDescription(enable ? DIRECT_MANIPULATION : null);
+    }
+
+    /**
+     * Returns whether the given {@code node} supports rotate directly.
+     *
+     * @deprecated use {@link #supportRotateDirectly} instead
+     */
+    @Deprecated
+    public static boolean supportDirectManipulation(@NonNull AccessibilityNodeInfo node) {
+        return supportRotateDirectly(node);
+    }
+
+    /**
+     * Sets whether the given {@code view} supports rotate directly.
+     *
+     * @deprecated use {@link #setSupportsRotateDirectly} instead
+     */
+    @Deprecated
+    public static void setSupportsDirectManipulation(@NonNull View view, boolean enable) {
+        setSupportsRotateDirectly(view, enable);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/RotaryConstants.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/RotaryConstants.java
new file mode 100644
index 0000000..e6c62c9
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/RotaryConstants.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 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.car.ui.utils;
+
+/**
+ * Constants for the rotary controller.
+ *
+ * @hide
+ */
+public final class RotaryConstants {
+    /**
+     * Content description indicating that the view is a rotary container.
+     * <p>
+     * A rotary container contains focusable elements. When initializing focus, the first element
+     * in the rotary container is prioritized to take focus. When searching for nudge target, the
+     * bounds of the rotary container is the minimum bounds containing its descendants.
+     * <p>
+     * A rotary container shouldn't be focusable unless it's a scrollable container. Though it
+     * can't be focused, it can be scrolled as a side-effect of moving the focus within it.
+     */
+    public static final String ROTARY_CONTAINER =
+            "com.android.car.ui.utils.ROTARY_CONTAINER";
+
+    /**
+     * Content description indicating that the view is a scrollable container and can be scrolled
+     * horizontally by the rotary controller.
+     * <p>
+     * A scrollable container is a focusable rotary container. When it's focused, it can be scrolled
+     * when the rotary controller rotates. A scrollable container is often used to show long text.
+     */
+    public static final String ROTARY_HORIZONTALLY_SCROLLABLE =
+            "com.android.car.ui.utils.HORIZONTALLY_SCROLLABLE";
+
+    /**
+     * Content description indicating that the view is a scrollable container and can be scrolled
+     * vertically by the rotary controller.
+     * <p>
+     * A scrollable container is a focusable rotary container. When it's focused, it can be scrolled
+     * when the rotary controller rotates. A scrollable container is often used to show long text.
+     */
+    public static final String ROTARY_VERTICALLY_SCROLLABLE =
+            "com.android.car.ui.utils.VERTICALLY_SCROLLABLE";
+
+    /**
+     * Content description indicating that the view is a focus delegating container. When
+     * restoring focus, FocusParkingView and FocusArea will skip non-focusable views unless it's
+     * a focus delegating container. The focus delegating container can delegate focus to one of
+     * its descendants.
+     */
+    public static final String ROTARY_FOCUS_DELEGATING_CONTAINER =
+            "com.android.car.ui.utils.FOCUS_DELEGATING_CONTAINER";
+
+    /** The key to store the offset of the FocusArea's left bound in the node's extras. */
+    public static final String FOCUS_AREA_LEFT_BOUND_OFFSET =
+            "com.android.car.ui.utils.FOCUS_AREA_LEFT_BOUND_OFFSET";
+
+    /** The key to store the offset of the FocusArea's right bound in the node's extras. */
+    public static final String FOCUS_AREA_RIGHT_BOUND_OFFSET =
+            "com.android.car.ui.utils.FOCUS_AREA_RIGHT_BOUND_OFFSET";
+
+    /** The key to store the offset of the FocusArea's top bound in the node's extras. */
+    public static final String FOCUS_AREA_TOP_BOUND_OFFSET =
+            "com.android.car.ui.utils.FOCUS_AREA_TOP_BOUND_OFFSET";
+
+    /** The key to store the offset of the FocusArea's bottom bound in the node's extras. */
+    public static final String FOCUS_AREA_BOTTOM_BOUND_OFFSET =
+            "com.android.car.ui.utils.FOCUS_AREA_BOTTOM_BOUND_OFFSET";
+
+    /** The key to store nudge direction in the Bundle. */
+    public static final String NUDGE_DIRECTION =
+            "com.android.car.ui.utils.NUDGE_DIRECTION";
+
+    /**
+     * Action performed on a FocusArea to move focus to the nudge shortcut within the same
+     * FocusArea.
+     * <p>
+     * This action and the actions below only use the most significant 8 bits to avoid
+     * conflicting with legacy standard actions (which don't use the most significant 8 bits),
+     * e.g. ACTION_FOCUS. The actions only use one bit to avoid conflicting with IDs defined in
+     * framework (which start with 0x0102), e.g. R.id.accessibilityActionScrollUp.
+     */
+    public static final int ACTION_NUDGE_SHORTCUT = 0x01000000;
+
+    /** Action performed on a FocusArea to move focus to another FocusArea. */
+    public static final int ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA = 0x02000000;
+
+    /** Action performed on a FocusParkingView to restore the focus in the window. */
+    public static final int ACTION_RESTORE_DEFAULT_FOCUS = 0x04000000;
+
+    /** Action performed on a FocusParkingView to hide the IME. */
+    public static final int ACTION_HIDE_IME = 0x08000000;
+
+    /** Prevent instantiation. */
+    private RotaryConstants() {
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/ViewUtils.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/ViewUtils.java
new file mode 100644
index 0000000..62c189f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/ViewUtils.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2020 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.car.ui.utils;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_CONTAINER;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_FOCUS_DELEGATING_CONTAINER;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_HORIZONTALLY_SCROLLABLE;
+import static com.android.car.ui.utils.RotaryConstants.ROTARY_VERTICALLY_SCROLLABLE;
+
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.ui.FocusArea;
+import com.android.car.ui.FocusParkingView;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Utility class used by {@link com.android.car.ui.FocusArea} and {@link
+ * com.android.car.ui.FocusParkingView}.
+ *
+ * @hide
+ */
+public final class ViewUtils {
+
+    /**
+     * No view is focused, the focused view is not shown, or the focused view is a FocusParkingView.
+     */
+    public static final int NO_FOCUS = 1;
+
+    /** A scrollable container is focused. */
+    public static final int SCROLLABLE_CONTAINER_FOCUS = 2;
+
+    /**
+     * A regular view is focused. A regular View is a View that is neither a FocusParkingView nor a
+     * scrollable container.
+     */
+    public static final int REGULAR_FOCUS = 3;
+
+    /**
+     * An implicit default focus view (i.e., the first focusable item in a scrollable container) is
+     * focused.
+     */
+    public static final int IMPLICIT_DEFAULT_FOCUS = 4;
+
+    /** The {@code app:defaultFocus} view is focused. */
+    public static final int DEFAULT_FOCUS = 5;
+
+    /** The {@code android:focusedByDefault} view is focused. */
+    public static final int FOCUSED_BY_DEFAULT = 6;
+
+    /**
+     * Focus level of a view. When adjusting the focus, the view with the highest focus level will
+     * be focused.
+     */
+    @IntDef(flag = true, value = {NO_FOCUS, SCROLLABLE_CONTAINER_FOCUS, REGULAR_FOCUS,
+            IMPLICIT_DEFAULT_FOCUS, DEFAULT_FOCUS, FOCUSED_BY_DEFAULT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FocusLevel {
+    }
+
+    /** This is a utility class. */
+    private ViewUtils() {
+    }
+
+    /**
+     * This is a functional interface and can therefore be used as the assignment target for a
+     * lambda expression or method reference.
+     *
+     * @param <T> the type of the input to the predicate
+     */
+    private interface Predicate<T> {
+        /** Evaluates this predicate on the given argument. */
+        boolean test(@NonNull T t);
+    }
+
+    /** Gets the ancestor FocusArea of the {@code view}, if any. Returns null if not found. */
+    @Nullable
+    public static FocusArea getAncestorFocusArea(@NonNull View view) {
+        ViewParent parent = view.getParent();
+        while (parent != null) {
+            if (parent instanceof FocusArea) {
+                return (FocusArea) parent;
+            }
+            parent = parent.getParent();
+        }
+        return null;
+    }
+
+    /**
+     * Gets the ancestor scrollable container of the {@code view}, if any. Returns null if not
+     * found.
+     */
+    @Nullable
+    public static ViewGroup getAncestorScrollableContainer(@Nullable View view) {
+        if (view == null) {
+            return null;
+        }
+        ViewParent parent = view.getParent();
+        // A scrollable container can't contain a FocusArea, so let's return earlier if we found
+        // a FocusArea.
+        while (parent != null && parent instanceof ViewGroup && !(parent instanceof FocusArea)) {
+            ViewGroup viewGroup = (ViewGroup) parent;
+            if (isScrollableContainer(viewGroup)) {
+                return viewGroup;
+            }
+            parent = parent.getParent();
+        }
+        return null;
+    }
+
+    /**
+     * Focuses on the {@code view} if it can be focused.
+     *
+     * @return whether it was successfully focused or already focused
+     */
+    public static boolean requestFocus(@Nullable View view) {
+        if (view == null || !canTakeFocus(view)) {
+            return false;
+        }
+        if (view.isFocused()) {
+            return true;
+        }
+        // Exit touch mode and focus the view. The view may not be focusable in touch mode, so we
+        // need to exit touch mode before focusing it.
+        return view.performAccessibilityAction(ACTION_FOCUS, /* arguments= */ null);
+    }
+
+    /**
+     * Searches the {@code root}'s descendants for a view with the highest {@link FocusLevel}. If
+     * the view's FocusLevel is higher than the {@code currentFocus}'s FocusLevel, focuses on the
+     * view.
+     *
+     * @return whether the view is focused
+     */
+    public static boolean adjustFocus(@NonNull View root, @Nullable View currentFocus) {
+        @FocusLevel int level = getFocusLevel(currentFocus);
+        return adjustFocus(root, level);
+    }
+
+    /**
+     * Searches the {@code root}'s descendants for a view with the highest {@link FocusLevel}. If
+     * the view's FocusLevel is higher than {@code currentLevel}, focuses on the view.
+     *
+     * @return whether the view is focused
+     */
+    public static boolean adjustFocus(@NonNull View root, @FocusLevel int currentLevel) {
+        if (currentLevel < FOCUSED_BY_DEFAULT && focusOnFocusedByDefaultView(root)) {
+            return true;
+        }
+        if (currentLevel < DEFAULT_FOCUS && focusOnDefaultFocusView(root)) {
+            return true;
+        }
+        if (currentLevel < IMPLICIT_DEFAULT_FOCUS && focusOnImplicitDefaultFocusView(root)) {
+            return true;
+        }
+        if (currentLevel < REGULAR_FOCUS && focusOnFirstRegularView(root)) {
+            return true;
+        }
+        if (currentLevel < SCROLLABLE_CONTAINER_FOCUS) {
+            return focusOnScrollableContainer(root);
+        }
+        return false;
+    }
+
+    @VisibleForTesting
+    @FocusLevel
+    static int getFocusLevel(@Nullable View view) {
+        if (view == null || view instanceof FocusParkingView || !view.isShown()) {
+            return NO_FOCUS;
+        }
+        if (view.isFocusedByDefault()) {
+            return FOCUSED_BY_DEFAULT;
+        }
+        if (isDefaultFocus(view)) {
+            return DEFAULT_FOCUS;
+        }
+        if (isImplicitDefaultFocusView(view)) {
+            return IMPLICIT_DEFAULT_FOCUS;
+        }
+        if (isScrollableContainer(view)) {
+            return SCROLLABLE_CONTAINER_FOCUS;
+        }
+        return REGULAR_FOCUS;
+    }
+
+    /** Returns whether the {@code view} is a {@code app:defaultFocus} view. */
+    private static boolean isDefaultFocus(@NonNull View view) {
+        FocusArea parent = getAncestorFocusArea(view);
+        return parent != null && view == parent.getDefaultFocusView();
+    }
+
+    /**
+     * Returns whether the {@code view} is an implicit default focus view, i.e., the first focusable
+     * item in a rotary container.
+     */
+    @VisibleForTesting
+    static boolean isImplicitDefaultFocusView(@NonNull View view) {
+        ViewGroup rotaryContainer = null;
+        ViewParent parent = view.getParent();
+        while (parent != null && parent instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) parent;
+            if (isRotaryContainer(viewGroup)) {
+                rotaryContainer = viewGroup;
+                break;
+            }
+            parent = parent.getParent();
+        }
+        if (rotaryContainer == null) {
+            return false;
+        }
+        return findFirstFocusableDescendant(rotaryContainer) == view;
+    }
+
+    private static boolean isRotaryContainer(@NonNull View view) {
+        CharSequence contentDescription = view.getContentDescription();
+        return TextUtils.equals(contentDescription, ROTARY_CONTAINER)
+                || TextUtils.equals(contentDescription, ROTARY_VERTICALLY_SCROLLABLE)
+                || TextUtils.equals(contentDescription, ROTARY_HORIZONTALLY_SCROLLABLE);
+    }
+
+    private static boolean isScrollableContainer(@NonNull View view) {
+        CharSequence contentDescription = view.getContentDescription();
+        return TextUtils.equals(contentDescription, ROTARY_VERTICALLY_SCROLLABLE)
+                || TextUtils.equals(contentDescription, ROTARY_HORIZONTALLY_SCROLLABLE);
+    }
+
+    private static boolean isFocusDelegatingContainer(@NonNull View view) {
+        CharSequence contentDescription = view.getContentDescription();
+        return TextUtils.equals(contentDescription, ROTARY_FOCUS_DELEGATING_CONTAINER);
+    }
+
+    /**
+     * Focuses on the first {@code app:defaultFocus} view in the view tree, if any.
+     *
+     * @param root the root of the view tree
+     * @return whether succeeded
+     */
+    private static boolean focusOnDefaultFocusView(@NonNull View root) {
+        View defaultFocus = findDefaultFocusView(root);
+        return requestFocus(defaultFocus);
+    }
+
+    /**
+     * Focuses on the first {@code android:focusedByDefault} view in the view tree, if any.
+     *
+     * @param root the root of the view tree
+     * @return whether succeeded
+     */
+    private static boolean focusOnFocusedByDefaultView(@NonNull View root) {
+        View focusedByDefault = findFocusedByDefaultView(root);
+        return requestFocus(focusedByDefault);
+    }
+
+    /**
+     * Focuses on the first implicit default focus view in the view tree, if any.
+     *
+     * @param root the root of the view tree
+     * @return whether succeeded
+     */
+    private static boolean focusOnImplicitDefaultFocusView(@NonNull View root) {
+        View implicitDefaultFocus = findImplicitDefaultFocusView(root);
+        return requestFocus(implicitDefaultFocus);
+    }
+
+    /**
+     * Tries to focus on the first focusable view in the view tree in depth first order, excluding
+     * the FocusParkingView and scrollable containers. If focusing on the first such view fails,
+     * keeps trying other views in depth first order until succeeds or there are no more such views.
+     *
+     * @param root the root of the view tree
+     * @return whether succeeded
+     */
+    private static boolean focusOnFirstRegularView(@NonNull View root) {
+        View focusedView = ViewUtils.depthFirstSearch(root,
+                /* targetPredicate= */
+                v -> !isScrollableContainer(v) && canTakeFocus(v) && requestFocus(v),
+                /* skipPredicate= */ v -> !v.isShown());
+        return focusedView != null;
+    }
+
+    /**
+     * Focuses on the first scrollable container in the view tree, if any.
+     *
+     * @param root the root of the view tree
+     * @return whether succeeded
+     */
+    private static boolean focusOnScrollableContainer(@NonNull View root) {
+        View focusedView = ViewUtils.depthFirstSearch(root,
+                /* targetPredicate= */ v -> isScrollableContainer(v) && canTakeFocus(v),
+                /* skipPredicate= */ v -> !v.isShown());
+        return requestFocus(focusedView);
+    }
+
+    /**
+     * Searches the {@code root}'s descendants in depth first order, and returns the first
+     * {@code app:defaultFocus} view that can take focus. Returns null if not found.
+     */
+    @Nullable
+    private static View findDefaultFocusView(@NonNull View view) {
+        if (!view.isShown()) {
+            return null;
+        }
+        if (view instanceof FocusArea) {
+            FocusArea focusArea = (FocusArea) view;
+            View defaultFocus = focusArea.getDefaultFocusView();
+            if (defaultFocus != null && canTakeFocus(defaultFocus)) {
+                return defaultFocus;
+            }
+        } else if (view instanceof ViewGroup) {
+            ViewGroup parent = (ViewGroup) view;
+            for (int i = 0; i < parent.getChildCount(); i++) {
+                View child = parent.getChildAt(i);
+                View defaultFocus = findDefaultFocusView(child);
+                if (defaultFocus != null) {
+                    return defaultFocus;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Searches the {@code view} and its descendants in depth first order, and returns the first
+     * {@code android:focusedByDefault} view that can take focus. Returns null if not found.
+     */
+    @VisibleForTesting
+    @Nullable
+    static View findFocusedByDefaultView(@NonNull View view) {
+        return depthFirstSearch(view,
+                /* targetPredicate= */ v -> v.isFocusedByDefault() && canTakeFocus(v),
+                /* skipPredicate= */ v -> !v.isShown());
+    }
+
+    /**
+     * Searches the {@code view} and its descendants in depth first order, and returns the first
+     * implicit default focus view, i.e., the first focusable item in the first rotary container.
+     * Returns null if not found.
+     */
+    @VisibleForTesting
+    @Nullable
+    static View findImplicitDefaultFocusView(@NonNull View view) {
+        View rotaryContainer = findRotaryContainer(view);
+        return rotaryContainer == null
+                ? null
+                : findFirstFocusableDescendant(rotaryContainer);
+    }
+
+    /**
+     * Searches the {@code view}'s descendants in depth first order, and returns the first view
+     * that can take focus, or null if not found.
+     */
+    @VisibleForTesting
+    @Nullable
+    static View findFirstFocusableDescendant(@NonNull View view) {
+        return depthFirstSearch(view,
+                /* targetPredicate= */ v -> v != view && canTakeFocus(v),
+                /* skipPredicate= */ v -> !v.isShown());
+    }
+
+    /**
+     * Searches the {@code view} and its descendants in depth first order, and returns the first
+     * rotary container shown on the screen. Returns null if not found.
+     */
+    @Nullable
+    private static View findRotaryContainer(@NonNull View view) {
+        return depthFirstSearch(view,
+                /* targetPredicate= */ v -> isRotaryContainer(v),
+                /* skipPredicate= */ v -> !v.isShown());
+    }
+
+    /**
+     * Searches the {@code view} and its descendants in depth first order, skips the views that
+     * match {@code skipPredicate} and their descendants, and returns the first view that matches
+     * {@code targetPredicate}. Returns null if not found.
+     */
+    @Nullable
+    private static View depthFirstSearch(@NonNull View view,
+            @NonNull Predicate<View> targetPredicate,
+            @Nullable Predicate<View> skipPredicate) {
+        if (skipPredicate != null && skipPredicate.test(view)) {
+            return null;
+        }
+        if (targetPredicate.test(view)) {
+            return view;
+        }
+        if (view instanceof ViewGroup) {
+            ViewGroup parent = (ViewGroup) view;
+            for (int i = 0; i < parent.getChildCount(); i++) {
+                View child = parent.getChildAt(i);
+                View target = depthFirstSearch(child, targetPredicate, skipPredicate);
+                if (target != null) {
+                    return target;
+                }
+            }
+        }
+        return null;
+    }
+
+    /** Returns whether {@code view} can be focused. */
+    private static boolean canTakeFocus(@NonNull View view) {
+        boolean focusable = view.isFocusable() || isFocusDelegatingContainer(view);
+        return focusable && view.isEnabled() && view.isShown()
+                && view.getWidth() > 0 && view.getHeight() > 0 && view.isAttachedToWindow()
+                && !(view instanceof FocusParkingView)
+                // If it's a scrollable container, it can be focused only when it has no focusable
+                // descendants. We focus on it so that the rotary controller can scroll it.
+                && (!isScrollableContainer(view) || findFirstFocusableDescendant(view) == null);
+    }
+}
diff --git a/car-ui-lib/src/com/android/car/ui/uxr/DrawableStateButton.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/uxr/DrawableStateButton.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/uxr/DrawableStateButton.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/uxr/DrawableStateButton.java
diff --git a/car-ui-lib/src/com/android/car/ui/uxr/DrawableStateSwitch.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/uxr/DrawableStateSwitch.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/uxr/DrawableStateSwitch.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/uxr/DrawableStateSwitch.java
diff --git a/car-ui-lib/src/com/android/car/ui/uxr/DrawableStateView.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/uxr/DrawableStateView.java
similarity index 100%
rename from car-ui-lib/src/com/android/car/ui/uxr/DrawableStateView.java
rename to car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/uxr/DrawableStateView.java
diff --git a/car-ui-lib/car-ui-lib/src/main/res-overlayable/values/overlayable.xml b/car-ui-lib/car-ui-lib/src/main/res-overlayable/values/overlayable.xml
new file mode 100644
index 0000000..453db47
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res-overlayable/values/overlayable.xml
@@ -0,0 +1,485 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--Copyright (C) 2020 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.-->
+<!--THIS FILE IS AUTO GENERATED, DO NOT EDIT MANUALLY.-->
+<resources>
+  <overlayable name="car-ui-lib">
+    <policy type="public">
+      <item type="attr" name="CarUiToolbarStyle"/>
+      <item type="attr" name="barrierDirection"/>
+      <item type="attr" name="carUiPreferenceStyle"/>
+      <item type="attr" name="carUiRecyclerViewStyle"/>
+      <item type="attr" name="chainUseRtl"/>
+      <item type="attr" name="constraintSet"/>
+      <item type="attr" name="constraint_referenced_ids"/>
+      <item type="attr" name="layout_constraintBaseline_creator"/>
+      <item type="attr" name="layout_constraintBaseline_toBaselineOf"/>
+      <item type="attr" name="layout_constraintBottom_creator"/>
+      <item type="attr" name="layout_constraintBottom_toBottomOf"/>
+      <item type="attr" name="layout_constraintBottom_toTopOf"/>
+      <item type="attr" name="layout_constraintDimensionRatio"/>
+      <item type="attr" name="layout_constraintEnd_toEndOf"/>
+      <item type="attr" name="layout_constraintEnd_toStartOf"/>
+      <item type="attr" name="layout_constraintGuide_begin"/>
+      <item type="attr" name="layout_constraintGuide_end"/>
+      <item type="attr" name="layout_constraintGuide_percent"/>
+      <item type="attr" name="layout_constraintHeight_default"/>
+      <item type="attr" name="layout_constraintHeight_max"/>
+      <item type="attr" name="layout_constraintHeight_min"/>
+      <item type="attr" name="layout_constraintHeight_percent"/>
+      <item type="attr" name="layout_constraintHorizontal_bias"/>
+      <item type="attr" name="layout_constraintHorizontal_chainStyle"/>
+      <item type="attr" name="layout_constraintHorizontal_weight"/>
+      <item type="attr" name="layout_constraintLeft_creator"/>
+      <item type="attr" name="layout_constraintLeft_toLeftOf"/>
+      <item type="attr" name="layout_constraintLeft_toRightOf"/>
+      <item type="attr" name="layout_constraintRight_creator"/>
+      <item type="attr" name="layout_constraintRight_toLeftOf"/>
+      <item type="attr" name="layout_constraintRight_toRightOf"/>
+      <item type="attr" name="layout_constraintStart_toEndOf"/>
+      <item type="attr" name="layout_constraintStart_toStartOf"/>
+      <item type="attr" name="layout_constraintTop_creator"/>
+      <item type="attr" name="layout_constraintTop_toBottomOf"/>
+      <item type="attr" name="layout_constraintTop_toTopOf"/>
+      <item type="attr" name="layout_constraintVertical_bias"/>
+      <item type="attr" name="layout_constraintVertical_chainStyle"/>
+      <item type="attr" name="layout_constraintVertical_weight"/>
+      <item type="attr" name="layout_constraintWidth_default"/>
+      <item type="attr" name="layout_constraintWidth_max"/>
+      <item type="attr" name="layout_constraintWidth_min"/>
+      <item type="attr" name="layout_constraintWidth_percent"/>
+      <item type="attr" name="layout_editor_absoluteX"/>
+      <item type="attr" name="layout_editor_absoluteY"/>
+      <item type="attr" name="layout_goneMarginBottom"/>
+      <item type="attr" name="layout_goneMarginEnd"/>
+      <item type="attr" name="layout_goneMarginLeft"/>
+      <item type="attr" name="layout_goneMarginRight"/>
+      <item type="attr" name="layout_goneMarginStart"/>
+      <item type="attr" name="layout_goneMarginTop"/>
+      <item type="attr" name="layout_optimizationLevel"/>
+      <item type="attr" name="state_ux_restricted"/>
+      <item type="attr" name="title"/>
+      <item type="bool" name="car_ui_alert_dialog_force_dismiss_button"/>
+      <item type="bool" name="car_ui_clear_focus_area_history_when_rotating"/>
+      <item type="bool" name="car_ui_enable_focus_area_background_highlight"/>
+      <item type="bool" name="car_ui_enable_focus_area_foreground_highlight"/>
+      <item type="bool" name="car_ui_escrow_check_components_automatically"/>
+      <item type="bool" name="car_ui_focus_area_default_focus_overrides_history"/>
+      <item type="bool" name="car_ui_list_item_single_line_title"/>
+      <item type="bool" name="car_ui_preference_list_show_full_screen"/>
+      <item type="bool" name="car_ui_preference_show_chevron"/>
+      <item type="bool" name="car_ui_scrollbar_enable"/>
+      <item type="bool" name="car_ui_toolbar_logo_fills_nav_icon_space"/>
+      <item type="bool" name="car_ui_toolbar_nav_icon_reserve_space"/>
+      <item type="bool" name="car_ui_toolbar_show_logo"/>
+      <item type="bool" name="car_ui_toolbar_tab_flexible_layout"/>
+      <item type="bool" name="car_ui_toolbar_tabs_on_second_row"/>
+      <item type="color" name="car_ui_activity_background_color"/>
+      <item type="color" name="car_ui_color_accent"/>
+      <item type="color" name="car_ui_dialog_icon_color"/>
+      <item type="color" name="car_ui_list_item_divider"/>
+      <item type="color" name="car_ui_preference_icon_color"/>
+      <item type="color" name="car_ui_preference_two_action_divider_color"/>
+      <item type="color" name="car_ui_recyclerview_divider_color"/>
+      <item type="color" name="car_ui_ripple_color"/>
+      <item type="color" name="car_ui_rotary_focus_fill_color"/>
+      <item type="color" name="car_ui_rotary_focus_fill_secondary_color"/>
+      <item type="color" name="car_ui_rotary_focus_pressed_fill_color"/>
+      <item type="color" name="car_ui_rotary_focus_pressed_stroke_color"/>
+      <item type="color" name="car_ui_rotary_focus_stroke_color"/>
+      <item type="color" name="car_ui_rotary_focus_stroke_secondary_color"/>
+      <item type="color" name="car_ui_scrollbar_thumb"/>
+      <item type="color" name="car_ui_text_color_hint"/>
+      <item type="color" name="car_ui_text_color_primary"/>
+      <item type="color" name="car_ui_text_color_secondary"/>
+      <item type="color" name="car_ui_toolbar_menu_item_icon_background_color"/>
+      <item type="color" name="car_ui_toolbar_menu_item_icon_color"/>
+      <item type="color" name="car_ui_toolbar_nav_icon_color"/>
+      <item type="color" name="car_ui_toolbar_search_hint_text_color"/>
+      <item type="color" name="car_ui_toolbar_tab_item_selector"/>
+      <item type="color" name="car_ui_toolbar_tab_selected_color"/>
+      <item type="color" name="car_ui_toolbar_tab_unselected_color"/>
+      <item type="dimen" name="car_ui_body1_size"/>
+      <item type="dimen" name="car_ui_body2_size"/>
+      <item type="dimen" name="car_ui_body3_size"/>
+      <item type="dimen" name="car_ui_button_disabled_alpha"/>
+      <item type="dimen" name="car_ui_dialog_edittext_height"/>
+      <item type="dimen" name="car_ui_dialog_edittext_margin_bottom"/>
+      <item type="dimen" name="car_ui_dialog_edittext_margin_end"/>
+      <item type="dimen" name="car_ui_dialog_edittext_margin_start"/>
+      <item type="dimen" name="car_ui_dialog_edittext_margin_top"/>
+      <item type="dimen" name="car_ui_dialog_icon_size"/>
+      <item type="dimen" name="car_ui_dialog_title_margin"/>
+      <item type="dimen" name="car_ui_divider_width"/>
+      <item type="dimen" name="car_ui_header_list_item_text_start_margin"/>
+      <item type="dimen" name="car_ui_list_item_action_divider_height"/>
+      <item type="dimen" name="car_ui_list_item_action_divider_width"/>
+      <item type="dimen" name="car_ui_list_item_avatar_icon_height"/>
+      <item type="dimen" name="car_ui_list_item_avatar_icon_width"/>
+      <item type="dimen" name="car_ui_list_item_check_box_end_inset"/>
+      <item type="dimen" name="car_ui_list_item_check_box_height"/>
+      <item type="dimen" name="car_ui_list_item_check_box_icon_container_width"/>
+      <item type="dimen" name="car_ui_list_item_check_box_start_inset"/>
+      <item type="dimen" name="car_ui_list_item_content_icon_height"/>
+      <item type="dimen" name="car_ui_list_item_content_icon_width"/>
+      <item type="dimen" name="car_ui_list_item_end_inset"/>
+      <item type="dimen" name="car_ui_list_item_header_height"/>
+      <item type="dimen" name="car_ui_list_item_header_start_inset"/>
+      <item type="dimen" name="car_ui_list_item_height"/>
+      <item type="dimen" name="car_ui_list_item_icon_container_width"/>
+      <item type="dimen" name="car_ui_list_item_icon_size"/>
+      <item type="dimen" name="car_ui_list_item_radio_button_end_inset"/>
+      <item type="dimen" name="car_ui_list_item_radio_button_height"/>
+      <item type="dimen" name="car_ui_list_item_radio_button_icon_container_width"/>
+      <item type="dimen" name="car_ui_list_item_radio_button_start_inset"/>
+      <item type="dimen" name="car_ui_list_item_start_inset"/>
+      <item type="dimen" name="car_ui_list_item_supplemental_icon_size"/>
+      <item type="dimen" name="car_ui_list_item_text_no_icon_start_margin"/>
+      <item type="dimen" name="car_ui_list_item_text_start_margin"/>
+      <item type="dimen" name="car_ui_margin"/>
+      <item type="dimen" name="car_ui_padding_0"/>
+      <item type="dimen" name="car_ui_padding_1"/>
+      <item type="dimen" name="car_ui_padding_2"/>
+      <item type="dimen" name="car_ui_padding_3"/>
+      <item type="dimen" name="car_ui_padding_4"/>
+      <item type="dimen" name="car_ui_padding_5"/>
+      <item type="dimen" name="car_ui_padding_6"/>
+      <item type="dimen" name="car_ui_preference_category_icon_margin_end"/>
+      <item type="dimen" name="car_ui_preference_category_icon_size"/>
+      <item type="dimen" name="car_ui_preference_category_min_height"/>
+      <item type="dimen" name="car_ui_preference_content_margin_bottom"/>
+      <item type="dimen" name="car_ui_preference_content_margin_top"/>
+      <item type="dimen" name="car_ui_preference_dropdown_padding_start"/>
+      <item type="dimen" name="car_ui_preference_edit_text_dialog_margin_bottom"/>
+      <item type="dimen" name="car_ui_preference_edit_text_dialog_margin_top"/>
+      <item type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_bottom"/>
+      <item type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_end"/>
+      <item type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_start"/>
+      <item type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_end"/>
+      <item type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_start"/>
+      <item type="dimen" name="car_ui_preference_icon_margin_end"/>
+      <item type="dimen" name="car_ui_preference_icon_size"/>
+      <item type="dimen" name="car_ui_primary_icon_size"/>
+      <item type="dimen" name="car_ui_recyclerview_divider_bottom_margin"/>
+      <item type="dimen" name="car_ui_recyclerview_divider_end_margin"/>
+      <item type="dimen" name="car_ui_recyclerview_divider_height"/>
+      <item type="dimen" name="car_ui_recyclerview_divider_start_margin"/>
+      <item type="dimen" name="car_ui_recyclerview_divider_top_margin"/>
+      <item type="dimen" name="car_ui_rotary_focus_pressed_stroke_width"/>
+      <item type="dimen" name="car_ui_rotary_focus_stroke_width"/>
+      <item type="dimen" name="car_ui_scrollbar_button_size"/>
+      <item type="dimen" name="car_ui_scrollbar_container_width"/>
+      <item type="dimen" name="car_ui_scrollbar_decelerate_interpolator_factor"/>
+      <item type="dimen" name="car_ui_scrollbar_deceleration_times_divisor"/>
+      <item type="dimen" name="car_ui_scrollbar_margin"/>
+      <item type="dimen" name="car_ui_scrollbar_milliseconds_per_inch"/>
+      <item type="dimen" name="car_ui_scrollbar_min_thumb_height"/>
+      <item type="dimen" name="car_ui_scrollbar_padding_bottom"/>
+      <item type="dimen" name="car_ui_scrollbar_padding_top"/>
+      <item type="dimen" name="car_ui_scrollbar_separator_margin"/>
+      <item type="dimen" name="car_ui_scrollbar_thumb_radius"/>
+      <item type="dimen" name="car_ui_scrollbar_thumb_width"/>
+      <item type="dimen" name="car_ui_sub1_size"/>
+      <item type="dimen" name="car_ui_sub2_size"/>
+      <item type="dimen" name="car_ui_sub3_size"/>
+      <item type="dimen" name="car_ui_toolbar_bottom_inset"/>
+      <item type="dimen" name="car_ui_toolbar_bottom_view_height"/>
+      <item type="dimen" name="car_ui_toolbar_end_inset"/>
+      <item type="dimen" name="car_ui_toolbar_first_row_height"/>
+      <item type="dimen" name="car_ui_toolbar_logo_size"/>
+      <item type="dimen" name="car_ui_toolbar_margin"/>
+      <item type="dimen" name="car_ui_toolbar_menu_item_icon_background_size"/>
+      <item type="dimen" name="car_ui_toolbar_menu_item_icon_ripple_radius"/>
+      <item type="dimen" name="car_ui_toolbar_menu_item_icon_size"/>
+      <item type="dimen" name="car_ui_toolbar_menu_item_margin"/>
+      <item type="dimen" name="car_ui_toolbar_nav_icon_size"/>
+      <item type="dimen" name="car_ui_toolbar_row_height"/>
+      <item type="dimen" name="car_ui_toolbar_search_close_icon_container_width"/>
+      <item type="dimen" name="car_ui_toolbar_search_close_icon_size"/>
+      <item type="dimen" name="car_ui_toolbar_search_height"/>
+      <item type="dimen" name="car_ui_toolbar_search_search_icon_container_width"/>
+      <item type="dimen" name="car_ui_toolbar_search_search_icon_size"/>
+      <item type="dimen" name="car_ui_toolbar_second_row_height"/>
+      <item type="dimen" name="car_ui_toolbar_separator_height"/>
+      <item type="dimen" name="car_ui_toolbar_start_inset"/>
+      <item type="dimen" name="car_ui_toolbar_tab_icon_height"/>
+      <item type="dimen" name="car_ui_toolbar_tab_icon_width"/>
+      <item type="dimen" name="car_ui_toolbar_tab_padding_x"/>
+      <item type="dimen" name="car_ui_toolbar_tab_text_width"/>
+      <item type="dimen" name="car_ui_toolbar_title_logo_padding"/>
+      <item type="dimen" name="car_ui_toolbar_title_margin_start"/>
+      <item type="dimen" name="car_ui_toolbar_title_no_logo_margin_start"/>
+      <item type="dimen" name="car_ui_toolbar_top_inset"/>
+      <item type="dimen" name="car_ui_touch_target_height"/>
+      <item type="dimen" name="car_ui_touch_target_size"/>
+      <item type="dimen" name="car_ui_touch_target_width"/>
+      <item type="dimen" name="wrap_content"/>
+      <item type="drawable" name="car_ui_activity_background"/>
+      <item type="drawable" name="car_ui_divider"/>
+      <item type="drawable" name="car_ui_focus_area_background_highlight"/>
+      <item type="drawable" name="car_ui_focus_area_foreground_highlight"/>
+      <item type="drawable" name="car_ui_icon_add"/>
+      <item type="drawable" name="car_ui_icon_arrow_back"/>
+      <item type="drawable" name="car_ui_icon_close"/>
+      <item type="drawable" name="car_ui_icon_delete"/>
+      <item type="drawable" name="car_ui_icon_down"/>
+      <item type="drawable" name="car_ui_icon_edit"/>
+      <item type="drawable" name="car_ui_icon_lock"/>
+      <item type="drawable" name="car_ui_icon_overflow_menu"/>
+      <item type="drawable" name="car_ui_icon_save"/>
+      <item type="drawable" name="car_ui_icon_search"/>
+      <item type="drawable" name="car_ui_icon_search_nav_icon"/>
+      <item type="drawable" name="car_ui_icon_settings"/>
+      <item type="drawable" name="car_ui_list_header_background"/>
+      <item type="drawable" name="car_ui_list_item_avatar_icon_outline"/>
+      <item type="drawable" name="car_ui_list_item_background"/>
+      <item type="drawable" name="car_ui_list_item_divider"/>
+      <item type="drawable" name="car_ui_list_limiting_message_background"/>
+      <item type="drawable" name="car_ui_preference_icon_chevron"/>
+      <item type="drawable" name="car_ui_preference_icon_chevron_disabled"/>
+      <item type="drawable" name="car_ui_preference_icon_chevron_enabled"/>
+      <item type="drawable" name="car_ui_recyclerview_button_ripple_background"/>
+      <item type="drawable" name="car_ui_recyclerview_divider"/>
+      <item type="drawable" name="car_ui_recyclerview_ic_down"/>
+      <item type="drawable" name="car_ui_recyclerview_ic_up"/>
+      <item type="drawable" name="car_ui_recyclerview_scrollbar_thumb"/>
+      <item type="drawable" name="car_ui_toolbar_background"/>
+      <item type="drawable" name="car_ui_toolbar_menu_item_divider"/>
+      <item type="drawable" name="car_ui_toolbar_menu_item_icon_background"/>
+      <item type="drawable" name="car_ui_toolbar_menu_item_icon_ripple"/>
+      <item type="drawable" name="car_ui_toolbar_search_close_icon"/>
+      <item type="drawable" name="car_ui_toolbar_search_search_icon"/>
+      <item type="id" name="action_container"/>
+      <item type="id" name="action_container_touch_interceptor"/>
+      <item type="id" name="action_divider"/>
+      <item type="id" name="action_widget_container"/>
+      <item type="id" name="avatar_icon"/>
+      <item type="id" name="body"/>
+      <item type="id" name="car_ui_alert_icon"/>
+      <item type="id" name="car_ui_alert_subtitle"/>
+      <item type="id" name="car_ui_alert_title"/>
+      <item type="id" name="car_ui_base_layout_content_container"/>
+      <item type="id" name="car_ui_focus_area"/>
+      <item type="id" name="car_ui_list_item_end_guideline"/>
+      <item type="id" name="car_ui_list_item_start_guideline"/>
+      <item type="id" name="car_ui_list_limiting_message"/>
+      <item type="id" name="car_ui_preference_container_without_widget"/>
+      <item type="id" name="car_ui_preference_fragment_container"/>
+      <item type="id" name="car_ui_recycler_view"/>
+      <item type="id" name="car_ui_scroll_bar"/>
+      <item type="id" name="car_ui_scrollbar_page_down"/>
+      <item type="id" name="car_ui_scrollbar_page_up"/>
+      <item type="id" name="car_ui_scrollbar_thumb"/>
+      <item type="id" name="car_ui_scrollbar_track"/>
+      <item type="id" name="car_ui_toolbar"/>
+      <item type="id" name="car_ui_toolbar_background"/>
+      <item type="id" name="car_ui_toolbar_bottom_guideline"/>
+      <item type="id" name="car_ui_toolbar_bottom_styleable"/>
+      <item type="id" name="car_ui_toolbar_end_guideline"/>
+      <item type="id" name="car_ui_toolbar_logo"/>
+      <item type="id" name="car_ui_toolbar_menu_item_icon"/>
+      <item type="id" name="car_ui_toolbar_menu_item_icon_container"/>
+      <item type="id" name="car_ui_toolbar_menu_item_switch"/>
+      <item type="id" name="car_ui_toolbar_menu_item_text"/>
+      <item type="id" name="car_ui_toolbar_menu_item_text_container"/>
+      <item type="id" name="car_ui_toolbar_menu_item_text_with_icon"/>
+      <item type="id" name="car_ui_toolbar_menu_items_container"/>
+      <item type="id" name="car_ui_toolbar_nav_icon"/>
+      <item type="id" name="car_ui_toolbar_nav_icon_container"/>
+      <item type="id" name="car_ui_toolbar_progress_bar"/>
+      <item type="id" name="car_ui_toolbar_row_separator"/>
+      <item type="id" name="car_ui_toolbar_row_separator_guideline"/>
+      <item type="id" name="car_ui_toolbar_search_bar"/>
+      <item type="id" name="car_ui_toolbar_search_close"/>
+      <item type="id" name="car_ui_toolbar_search_icon"/>
+      <item type="id" name="car_ui_toolbar_search_view_container"/>
+      <item type="id" name="car_ui_toolbar_start_guideline"/>
+      <item type="id" name="car_ui_toolbar_subtitle"/>
+      <item type="id" name="car_ui_toolbar_tab_item_icon"/>
+      <item type="id" name="car_ui_toolbar_tab_item_text"/>
+      <item type="id" name="car_ui_toolbar_tabs"/>
+      <item type="id" name="car_ui_toolbar_title"/>
+      <item type="id" name="car_ui_toolbar_title_container"/>
+      <item type="id" name="car_ui_toolbar_title_logo"/>
+      <item type="id" name="car_ui_toolbar_title_logo_container"/>
+      <item type="id" name="car_ui_toolbar_top_guideline"/>
+      <item type="id" name="checkbox_widget"/>
+      <item type="id" name="container"/>
+      <item type="id" name="content_icon"/>
+      <item type="id" name="icon"/>
+      <item type="id" name="icon_container"/>
+      <item type="id" name="list"/>
+      <item type="id" name="nested_recycler_view_layout"/>
+      <item type="id" name="radio_button"/>
+      <item type="id" name="radio_button_widget"/>
+      <item type="id" name="recycler_view"/>
+      <item type="id" name="reduced_touch_interceptor"/>
+      <item type="id" name="search"/>
+      <item type="id" name="seek_bar"/>
+      <item type="id" name="seek_bar_text_left"/>
+      <item type="id" name="seek_bar_text_right"/>
+      <item type="id" name="seek_bar_text_top"/>
+      <item type="id" name="seekbar"/>
+      <item type="id" name="seekbar_value"/>
+      <item type="id" name="spinner"/>
+      <item type="id" name="supplemental_icon"/>
+      <item type="id" name="switch_widget"/>
+      <item type="id" name="text_container"/>
+      <item type="id" name="textbox"/>
+      <item type="id" name="title"/>
+      <item type="id" name="title_template"/>
+      <item type="id" name="toolbar"/>
+      <item type="id" name="touch_interceptor"/>
+      <item type="integer" name="car_ui_default_max_string_length"/>
+      <item type="integer" name="car_ui_focus_area_history_cache_type"/>
+      <item type="integer" name="car_ui_focus_area_history_expiration_period_ms"/>
+      <item type="integer" name="car_ui_focus_history_cache_type"/>
+      <item type="integer" name="car_ui_focus_history_expiration_period_ms"/>
+      <item type="integer" name="car_ui_scrollbar_longpress_initial_delay"/>
+      <item type="integer" name="car_ui_scrollbar_longpress_repeat_interval"/>
+      <item type="layout" name="car_ui_alert_dialog_edit_text"/>
+      <item type="layout" name="car_ui_alert_dialog_list"/>
+      <item type="layout" name="car_ui_alert_dialog_title_with_subtitle"/>
+      <item type="layout" name="car_ui_base_layout"/>
+      <item type="layout" name="car_ui_base_layout_toolbar"/>
+      <item type="layout" name="car_ui_base_layout_toolbar_legacy"/>
+      <item type="layout" name="car_ui_header_list_item"/>
+      <item type="layout" name="car_ui_list_item"/>
+      <item type="layout" name="car_ui_list_limiting_message"/>
+      <item type="layout" name="car_ui_list_preference"/>
+      <item type="layout" name="car_ui_list_preference_with_toolbar"/>
+      <item type="layout" name="car_ui_preference"/>
+      <item type="layout" name="car_ui_preference_category"/>
+      <item type="layout" name="car_ui_preference_chevron"/>
+      <item type="layout" name="car_ui_preference_dialog_edittext"/>
+      <item type="layout" name="car_ui_preference_dropdown"/>
+      <item type="layout" name="car_ui_preference_fragment"/>
+      <item type="layout" name="car_ui_preference_fragment_with_toolbar"/>
+      <item type="layout" name="car_ui_preference_widget_checkbox"/>
+      <item type="layout" name="car_ui_preference_widget_seekbar"/>
+      <item type="layout" name="car_ui_preference_widget_switch"/>
+      <item type="layout" name="car_ui_radio_button_preference_widget"/>
+      <item type="layout" name="car_ui_recycler_view"/>
+      <item type="layout" name="car_ui_recycler_view_item"/>
+      <item type="layout" name="car_ui_recyclerview_scrollbar"/>
+      <item type="layout" name="car_ui_seekbar_dialog"/>
+      <item type="layout" name="car_ui_toolbar"/>
+      <item type="layout" name="car_ui_toolbar_menu_item"/>
+      <item type="layout" name="car_ui_toolbar_search_view"/>
+      <item type="layout" name="car_ui_toolbar_tab_item"/>
+      <item type="layout" name="car_ui_toolbar_tab_item_flexible"/>
+      <item type="layout" name="car_ui_toolbar_tab_item_layout"/>
+      <item type="layout" name="car_ui_toolbar_tab_item_layout_flexible"/>
+      <item type="layout" name="car_ui_toolbar_two_row"/>
+      <item type="layout" name="car_ui_two_action_preference"/>
+      <item type="string" name="car_ui_alert_dialog_default_button"/>
+      <item type="string" name="car_ui_dialog_preference_negative"/>
+      <item type="string" name="car_ui_dialog_preference_positive"/>
+      <item type="string" name="car_ui_ellipsis"/>
+      <item type="string" name="car_ui_installer_process_name"/>
+      <item type="string" name="car_ui_preference_switch_off"/>
+      <item type="string" name="car_ui_preference_switch_on"/>
+      <item type="string" name="car_ui_restricted_while_driving"/>
+      <item type="string" name="car_ui_scrollbar_component"/>
+      <item type="string" name="car_ui_scrollbar_page_down_button"/>
+      <item type="string" name="car_ui_scrollbar_page_up_button"/>
+      <item type="string" name="car_ui_scrolling_limited_message"/>
+      <item type="string" name="car_ui_toolbar_default_search_hint"/>
+      <item type="string" name="car_ui_toolbar_menu_item_overflow_title"/>
+      <item type="string" name="car_ui_toolbar_menu_item_search_title"/>
+      <item type="string" name="car_ui_toolbar_menu_item_settings_title"/>
+      <item type="string" name="car_ui_toolbar_nav_icon_content_description"/>
+      <item type="style" name="CarUiPreferenceTheme"/>
+      <item type="style" name="CarUiPreferenceTheme.WithToolbar"/>
+      <item type="style" name="Preference.CarUi"/>
+      <item type="style" name="Preference.CarUi.Category"/>
+      <item type="style" name="Preference.CarUi.CheckBoxPreference"/>
+      <item type="style" name="Preference.CarUi.DialogPreference"/>
+      <item type="style" name="Preference.CarUi.DialogPreference.EditTextPreference"/>
+      <item type="style" name="Preference.CarUi.DialogSeekBarPreference"/>
+      <item type="style" name="Preference.CarUi.DialogSeekBarPreference.LeftText"/>
+      <item type="style" name="Preference.CarUi.DialogSeekBarPreference.RightText"/>
+      <item type="style" name="Preference.CarUi.DialogSeekBarPreference.Seekbar"/>
+      <item type="style" name="Preference.CarUi.DialogSeekBarPreference.TopText"/>
+      <item type="style" name="Preference.CarUi.Divider"/>
+      <item type="style" name="Preference.CarUi.DropDown"/>
+      <item type="style" name="Preference.CarUi.Icon"/>
+      <item type="style" name="Preference.CarUi.Information"/>
+      <item type="style" name="Preference.CarUi.Preference"/>
+      <item type="style" name="Preference.CarUi.PreferenceScreen"/>
+      <item type="style" name="Preference.CarUi.SeekBarPreference"/>
+      <item type="style" name="Preference.CarUi.SwitchPreference"/>
+      <item type="style" name="PreferenceFragment.CarUi"/>
+      <item type="style" name="PreferenceFragment.CarUi.WithToolbar"/>
+      <item type="style" name="PreferenceFragmentList.CarUi"/>
+      <item type="style" name="TextAppearance.CarUi"/>
+      <item type="style" name="TextAppearance.CarUi.AlertDialog.Subtitle"/>
+      <item type="style" name="TextAppearance.CarUi.AlertDialog.Title"/>
+      <item type="style" name="TextAppearance.CarUi.Body1"/>
+      <item type="style" name="TextAppearance.CarUi.Body2"/>
+      <item type="style" name="TextAppearance.CarUi.Body3"/>
+      <item type="style" name="TextAppearance.CarUi.ListItem"/>
+      <item type="style" name="TextAppearance.CarUi.ListItem.Body"/>
+      <item type="style" name="TextAppearance.CarUi.ListItem.Header"/>
+      <item type="style" name="TextAppearance.CarUi.PreferenceCategoryTitle"/>
+      <item type="style" name="TextAppearance.CarUi.PreferenceEditTextDialogMessage"/>
+      <item type="style" name="TextAppearance.CarUi.PreferenceSummary"/>
+      <item type="style" name="TextAppearance.CarUi.PreferenceTitle"/>
+      <item type="style" name="TextAppearance.CarUi.Sub1"/>
+      <item type="style" name="TextAppearance.CarUi.Sub2"/>
+      <item type="style" name="TextAppearance.CarUi.Sub3"/>
+      <item type="style" name="TextAppearance.CarUi.Widget"/>
+      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar"/>
+      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar.Tab"/>
+      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar.Tab.Selected"/>
+      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar.Title"/>
+      <item type="style" name="Theme.CarUi"/>
+      <item type="style" name="Theme.CarUi.NoToolbar"/>
+      <item type="style" name="Theme.CarUi.WithToolbar"/>
+      <item type="style" name="Widget.CarUi"/>
+      <item type="style" name="Widget.CarUi.AlertDialog"/>
+      <item type="style" name="Widget.CarUi.AlertDialog.HeaderContainer"/>
+      <item type="style" name="Widget.CarUi.AlertDialog.Icon"/>
+      <item type="style" name="Widget.CarUi.AlertDialog.TitleContainer"/>
+      <item type="style" name="Widget.CarUi.Button"/>
+      <item type="style" name="Widget.CarUi.Button.Borderless.Colored"/>
+      <item type="style" name="Widget.CarUi.CarUiRecyclerView"/>
+      <item type="style" name="Widget.CarUi.SeekbarPreference"/>
+      <item type="style" name="Widget.CarUi.SeekbarPreference.Seekbar"/>
+      <item type="style" name="Widget.CarUi.Toolbar"/>
+      <item type="style" name="Widget.CarUi.Toolbar.BottomView"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Container"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Logo"/>
+      <item type="style" name="Widget.CarUi.Toolbar.LogoContainer"/>
+      <item type="style" name="Widget.CarUi.Toolbar.MenuItem"/>
+      <item type="style" name="Widget.CarUi.Toolbar.MenuItem.Container"/>
+      <item type="style" name="Widget.CarUi.Toolbar.MenuItem.IndividualContainer"/>
+      <item type="style" name="Widget.CarUi.Toolbar.NavIcon"/>
+      <item type="style" name="Widget.CarUi.Toolbar.NavIconContainer"/>
+      <item type="style" name="Widget.CarUi.Toolbar.ProgressBar"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Search.CloseIcon"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Search.EditText"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Search.SearchIcon"/>
+      <item type="style" name="Widget.CarUi.Toolbar.SeparatorView"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Subtitle"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Tab"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Tab.Container"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Tab.Icon"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Tab.Text"/>
+      <item type="style" name="Widget.CarUi.Toolbar.TextButton"/>
+      <item type="style" name="Widget.CarUi.Toolbar.TextButton.WithIcon"/>
+      <item type="style" name="Widget.CarUi.Toolbar.Title"/>
+    </policy>
+  </overlayable>
+</resources>
diff --git a/car-ui-lib/res/color/car_ui_color_accent.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_color_accent.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_color_accent.xml
rename to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_color_accent.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_dialog_icon_color.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_dialog_icon_color.xml
new file mode 100644
index 0000000..2965a49
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_dialog_icon_color.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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-ui-lib/res/color/car_ui_list_item_divider.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_list_item_divider.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_list_item_divider.xml
rename to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_list_item_divider.xml
diff --git a/car-ui-lib/res/color/car_ui_text_color_hint.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_text_color_hint.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_text_color_hint.xml
rename to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_text_color_hint.xml
diff --git a/car-ui-lib/res/color/car_ui_text_color_primary.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_text_color_primary.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_text_color_primary.xml
rename to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_text_color_primary.xml
diff --git a/car-ui-lib/res/color/car_ui_text_color_secondary.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_text_color_secondary.xml
similarity index 100%
copy from car-ui-lib/res/color/car_ui_text_color_secondary.xml
copy to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_text_color_secondary.xml
diff --git a/car-ui-lib/res/color/car_ui_toolbar_menu_item_icon_background_color.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_toolbar_menu_item_icon_background_color.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_toolbar_menu_item_icon_background_color.xml
rename to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_toolbar_menu_item_icon_background_color.xml
diff --git a/car-ui-lib/res/color/car_ui_toolbar_menu_item_icon_color.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_toolbar_menu_item_icon_color.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_toolbar_menu_item_icon_color.xml
rename to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_toolbar_menu_item_icon_color.xml
diff --git a/car-ui-lib/res/color/car_ui_toolbar_tab_item_selector.xml b/car-ui-lib/car-ui-lib/src/main/res/color/car_ui_toolbar_tab_item_selector.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_toolbar_tab_item_selector.xml
rename to car-ui-lib/car-ui-lib/src/main/res/color/car_ui_toolbar_tab_item_selector.xml
diff --git a/car-ui-lib/res/drawable/car_ui_divider.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_divider.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_divider.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_divider.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_focus_area_background_highlight.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_focus_area_background_highlight.xml
new file mode 100644
index 0000000..7dd6341
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_focus_area_background_highlight.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="#2994CBFF"/>
+</shape>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_focus_area_foreground_highlight.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_focus_area_foreground_highlight.xml
new file mode 100644
index 0000000..94de514
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_focus_area_foreground_highlight.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <stroke android:width="1dp"
+            android:color="@color/car_ui_rotary_focus_stroke_color"/>
+</shape>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_add.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_add.xml
new file mode 100644
index 0000000..2fa6580
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_add.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_arrow_back.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_arrow_back.xml
similarity index 100%
copy from car-ui-lib/res/drawable/car_ui_icon_arrow_back.xml
copy to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_arrow_back.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_close.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_close.xml
new file mode 100644
index 0000000..a02d199
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_close.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0">
+    <path
+        android:fillColor="#FFF"
+        android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
+</vector>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_delete.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_delete.xml
new file mode 100644
index 0000000..63aa782
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_delete.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_down.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_down.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_icon_down.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_down.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_edit.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_edit.xml
new file mode 100644
index 0000000..a418c7f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_edit.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_lock.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_lock.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_icon_lock.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_lock.xml
diff --git a/car-ui-lib/res/drawable/car_ui_icon_overflow_menu.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_overflow_menu.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_icon_overflow_menu.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_overflow_menu.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_save.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_save.xml
new file mode 100644
index 0000000..f65682a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_save.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<!-- Used in Carboard's toolbar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+<path
+    android:fillColor="@color/car_ui_toolbar_menu_item_icon_color"
+    android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
+</vector>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_search.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_search.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_icon_search.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_search.xml
diff --git a/car-ui-lib/res/drawable/car_ui_icon_settings.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_settings.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_icon_settings.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_icon_settings.xml
diff --git a/car-ui-lib/res/drawable/car_ui_list_header_background.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_header_background.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_list_header_background.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_header_background.xml
diff --git a/car-ui-lib/res/drawable/car_ui_list_item_avatar_icon_outline.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_avatar_icon_outline.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_list_item_avatar_icon_outline.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_avatar_icon_outline.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_background.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_background.xml
new file mode 100644
index 0000000..4d33475
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_background.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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:state_focused="true" android:state_pressed="true">
+        <shape android:shape="rectangle">
+            <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/>
+            <stroke android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width"
+                    android:color="@color/car_ui_rotary_focus_pressed_stroke_color"/>
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape android:shape="rectangle">
+            <solid android:color="@color/car_ui_rotary_focus_fill_color"/>
+            <stroke android:width="@dimen/car_ui_rotary_focus_stroke_width"
+                    android:color="@color/car_ui_rotary_focus_stroke_color"/>
+        </shape>
+    </item>
+    <item>
+        <ripple android:color="?android:attr/colorControlHighlight">
+            <item android:id="@android:id/mask">
+                <shape android:shape="rectangle">
+                    <solid android:color="?android:colorAccent"/>
+                </shape>
+            </item>
+        </ripple>
+    </item>
+</selector>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_divider.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_divider.xml
new file mode 100644
index 0000000..6f8e742
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_item_divider.xml
@@ -0,0 +1,22 @@
+<?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.
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <size android:height="@dimen/car_ui_list_item_action_divider_height" />
+    <solid android:color="@color/car_ui_list_item_divider" />
+</shape>
diff --git a/car-ui-lib/res/drawable/car_ui_list_limiting_message_background.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_limiting_message_background.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_list_limiting_message_background.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_list_limiting_message_background.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_preference_icon_chevron.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_preference_icon_chevron.xml
new file mode 100644
index 0000000..8011b92
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_preference_icon_chevron.xml
@@ -0,0 +1,21 @@
+<?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.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+  <item android:state_enabled="false" android:drawable="@drawable/car_ui_preference_icon_chevron_disabled"/>
+  <item android:state_enabled="true" android:drawable="@drawable/car_ui_preference_icon_chevron_enabled"/>
+</selector>
diff --git a/car-ui-lib/res/drawable/car_ui_recyclerview_button_ripple_background.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_button_ripple_background.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_recyclerview_button_ripple_background.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_button_ripple_background.xml
diff --git a/car-ui-lib/res/drawable/car_ui_recyclerview_divider.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_divider.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_recyclerview_divider.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_divider.xml
diff --git a/car-ui-lib/res/drawable/car_ui_recyclerview_ic_down.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_ic_down.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_recyclerview_ic_down.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_ic_down.xml
diff --git a/car-ui-lib/res/drawable/car_ui_recyclerview_ic_up.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_ic_up.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_recyclerview_ic_up.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_ic_up.xml
diff --git a/car-ui-lib/res/drawable/car_ui_recyclerview_scrollbar_thumb.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_scrollbar_thumb.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_recyclerview_scrollbar_thumb.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_recyclerview_scrollbar_thumb.xml
diff --git a/car-ui-lib/res/drawable/car_ui_toolbar_menu_item_divider.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_toolbar_menu_item_divider.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_toolbar_menu_item_divider.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_toolbar_menu_item_divider.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_toolbar_menu_item_icon_background.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_toolbar_menu_item_icon_background.xml
new file mode 100644
index 0000000..46171fd
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_toolbar_menu_item_icon_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~
+  ~ Copyright (C) 2019 Google Inc.
+  ~
+  ~ 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.
+  ~
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <size
+        android:width="@dimen/car_ui_toolbar_menu_item_icon_background_size"
+        android:height="@dimen/car_ui_toolbar_menu_item_icon_background_size"/>
+    <solid android:color="@color/car_ui_toolbar_menu_item_icon_background_color"/>
+</shape>
diff --git a/car-ui-lib/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml b/car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
rename to car-ui-lib/car-ui-lib/src/main/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_alert_dialog_edit_text.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_alert_dialog_edit_text.xml
new file mode 100644
index 0000000..d654b2b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_alert_dialog_edit_text.xml
@@ -0,0 +1,27 @@
+<?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.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android">
+    <EditText
+              android:id="@+id/textbox"
+              android:layout_width="match_parent"
+              android:layout_height="@dimen/car_ui_dialog_edittext_height"
+              android:layout_marginTop="@dimen/car_ui_dialog_edittext_margin_top"
+              android:layout_marginBottom="@dimen/car_ui_dialog_edittext_margin_bottom"
+              android:layout_marginStart="@dimen/car_ui_dialog_edittext_margin_start"
+              android:layout_marginEnd="@dimen/car_ui_dialog_edittext_margin_end"/>
+</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_alert_dialog_list.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_alert_dialog_list.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_alert_dialog_list.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_alert_dialog_list.xml
diff --git a/car-ui-lib/res/layout/car_ui_alert_dialog_title_with_subtitle.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_alert_dialog_title_with_subtitle.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_alert_dialog_title_with_subtitle.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_alert_dialog_title_with_subtitle.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout.xml
new file mode 100644
index 0000000..cd73725
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_base_layout_content_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout_toolbar.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout_toolbar.xml
new file mode 100644
index 0000000..410261c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout_toolbar.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:tag="CarUiBaseLayoutToolbar">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_base_layout_content_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+    <com.android.car.ui.FocusArea
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/car_ui_toolbar_first_row_height">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            style="@style/Widget.CarUi.Toolbar.Container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
+
+            <!-- The horizontal bias set to 0.0 here is so that when you set this view as GONE, it will
+                 be treated as if it's all the way to the left instead of centered in the margin -->
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+                android:layout_width="@dimen/car_ui_toolbar_margin"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintHorizontal_bias="0.0"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    style="@style/Widget.CarUi.Toolbar.NavIcon"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"/>
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"/>
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                style="@style/Widget.CarUi.Toolbar.LogoContainer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    style="@style/Widget.CarUi.Toolbar.Logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"/>
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
+                          app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
+                          app:layout_constraintBottom_toBottomOf="parent"
+                          app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+                          app:layout_constraintTop_toTopOf="parent">
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          style="@style/Widget.CarUi.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          style="@style/Widget.CarUi.Toolbar.Subtitle"/>
+            </LinearLayout>
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintHorizontal_bias="0.0"
+                app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+                app:layout_constraintTop_toTopOf="parent"/>
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="@dimen/car_ui_toolbar_search_height"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent"/>
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@style/Widget.CarUi.Toolbar.ProgressBar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"/>
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout_toolbar_legacy.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout_toolbar_legacy.xml
new file mode 100644
index 0000000..191fb3e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_base_layout_toolbar_legacy.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<!-- This layout is used on P or earlier, to support OEMs that shipped
+     on P and only customized the non-baselayout version of the toolbar -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_base_layout_content_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/car_ui_toolbar"
+        android:tag="car_ui_top_inset"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_header_list_item.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_header_list_item.xml
new file mode 100644
index 0000000..7ac4732
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_header_list_item.xml
@@ -0,0 +1,61 @@
+<?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.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:background="@drawable/car_ui_list_header_background"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/car_ui_list_item_header_height">
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/car_ui_list_item_start_guideline"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_begin="@dimen/car_ui_list_item_header_start_inset" />
+
+    <!-- Use nested layout as a workaround for a regression in constraintlayout where chains not
+    are not rendered correctly when the tail is gone (b/168627311).-->
+    <LinearLayout
+        android:id="@+id/text_container"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@id/car_ui_list_item_start_guideline"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/car_ui_header_list_item_text_start_margin"
+            android:textDirection="locale"
+            android:textAppearance="@style/TextAppearance.CarUi.ListItem.Header" />
+
+        <TextView
+            android:id="@+id/body"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/car_ui_list_item_text_no_icon_start_margin"
+            android:textDirection="locale"
+            android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body" />
+    </LinearLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_item.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_item.xml
new file mode 100644
index 0000000..d0f179e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_item.xml
@@ -0,0 +1,192 @@
+<?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.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:tag="carUiListItem"
+    android:minHeight="@dimen/car_ui_list_item_height">
+
+    <!-- The following touch interceptor views are sized to encompass the specific sub-sections of
+    the list item view to easily control the bounds of a background ripple effects. -->
+    <View
+        android:id="@+id/touch_interceptor"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:background="@drawable/car_ui_list_item_background"
+        android:clickable="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <!-- This touch interceptor does not include the action container -->
+    <View
+        android:id="@+id/reduced_touch_interceptor"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:background="@drawable/car_ui_list_item_background"
+        android:clickable="true"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/action_container"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/car_ui_list_item_start_guideline"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_begin="@dimen/car_ui_list_item_start_inset" />
+
+    <FrameLayout
+        android:id="@+id/icon_container"
+        android:layout_width="@dimen/car_ui_list_item_icon_container_width"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="@+id/car_ui_list_item_start_guideline"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/icon"
+            android:layout_width="@dimen/car_ui_list_item_icon_size"
+            android:layout_height="@dimen/car_ui_list_item_icon_size"
+            android:layout_gravity="center"
+            android:visibility="gone"
+            android:scaleType="fitXY" />
+
+        <ImageView
+            android:id="@+id/content_icon"
+            android:layout_width="@dimen/car_ui_list_item_content_icon_width"
+            android:layout_height="@dimen/car_ui_list_item_content_icon_height"
+            android:layout_gravity="center"
+            android:visibility="gone"
+            android:scaleType="fitXY" />
+
+        <ImageView
+            android:id="@+id/avatar_icon"
+            android:background="@drawable/car_ui_list_item_avatar_icon_outline"
+            android:layout_width="@dimen/car_ui_list_item_avatar_icon_width"
+            android:layout_height="@dimen/car_ui_list_item_avatar_icon_height"
+            android:layout_gravity="center"
+            android:visibility="gone"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <!-- Use nested layout as a workaround for a regression in constraintlayout where chains not
+    are not rendered correctly when the tail is gone (b/168627311).-->
+    <LinearLayout
+        android:id="@+id/text_container"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/action_container"
+        app:layout_constraintStart_toEndOf="@id/icon_container"
+        android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
+        app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:singleLine="@bool/car_ui_list_item_single_line_title"
+            android:textDirection="locale"
+            android:textAppearance="@style/TextAppearance.CarUi.ListItem" />
+
+        <TextView
+            android:id="@+id/body"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textDirection="locale"
+            android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body" />
+    </LinearLayout>
+
+    <!-- This touch interceptor is sized and positioned to encompass the action container   -->
+    <View
+        android:id="@+id/action_container_touch_interceptor"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:background="@drawable/car_ui_list_item_background"
+        android:clickable="true"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@id/action_container"
+        app:layout_constraintEnd_toEndOf="@id/action_container"
+        app:layout_constraintStart_toStartOf="@id/action_container"
+        app:layout_constraintTop_toTopOf="@id/action_container" />
+
+    <FrameLayout
+        android:id="@+id/action_container"
+        android:layout_width="wrap_content"
+        android:minWidth="@dimen/car_ui_list_item_icon_container_width"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="@+id/car_ui_list_item_end_guideline"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <View
+            android:id="@+id/action_divider"
+            android:layout_width="@dimen/car_ui_list_item_action_divider_width"
+            android:layout_height="@dimen/car_ui_list_item_action_divider_height"
+            android:layout_gravity="start|center_vertical"
+            android:background="@drawable/car_ui_list_item_divider" />
+
+        <Switch
+            android:id="@+id/switch_widget"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:clickable="false"
+            android:focusable="false" />
+
+        <CheckBox
+            android:id="@+id/checkbox_widget"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:clickable="false"
+            android:focusable="false" />
+
+        <RadioButton
+            android:id="@+id/radio_button_widget"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:clickable="false"
+            android:focusable="false" />
+
+        <ImageView
+            android:id="@+id/supplemental_icon"
+            android:layout_width="@dimen/car_ui_list_item_supplemental_icon_size"
+            android:layout_height="@dimen/car_ui_list_item_supplemental_icon_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/car_ui_list_item_end_guideline"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_end="@dimen/car_ui_list_item_end_inset" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_limiting_message.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_limiting_message.xml
new file mode 100644
index 0000000..a9f9b9b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_limiting_message.xml
@@ -0,0 +1,39 @@
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="144dp"
+    android:gravity="center"
+    android:paddingTop="16dp"
+    android:paddingBottom="32dp"
+>
+    <TextView
+        android:id="@+id/car_ui_list_limiting_message"
+        android:layout_width="wrap_content"
+        android:layout_height="96dp"
+        android:layout_gravity="center_horizontal"
+        android:gravity="center"
+        android:paddingStart="48dp"
+        android:paddingEnd="48dp"
+        android:drawableStart="@drawable/car_ui_icon_lock"
+        android:drawablePadding="24dp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textAllCaps="false"
+        android:singleLine="true"
+        android:background="@drawable/car_ui_list_limiting_message_background"
+    />
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_preference.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_preference.xml
new file mode 100644
index 0000000..70bf96d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_preference.xml
@@ -0,0 +1,32 @@
+<?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.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:tag="carUiPreferenceRecyclerView"
+        app:enableDivider="true" />
+
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_preference_with_toolbar.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_preference_with_toolbar.xml
new file mode 100644
index 0000000..f42c9f1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_list_preference_with_toolbar.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:tag="carUiPreferenceRecyclerView"
+        app:enableDivider="true" />
+
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:car_ui_state="subpage" />
+
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference.xml
new file mode 100644
index 0000000..52dbd68
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference.xml
@@ -0,0 +1,74 @@
+<?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.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?android:attr/selectableItemBackground"
+    android:clipToPadding="false"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:tag="carUiPreference"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart">
+
+    <ImageView
+        android:id="@android:id/icon"
+        android:layout_width="@dimen/car_ui_preference_icon_size"
+        android:layout_height="@dimen/car_ui_preference_icon_size"
+        android:layout_alignParentStart="true"
+        android:layout_centerVertical="true"
+        android:layout_marginBottom="@dimen/car_ui_preference_content_margin_bottom"
+        android:layout_marginEnd="@dimen/car_ui_preference_icon_margin_end"
+        android:layout_marginTop="@dimen/car_ui_preference_content_margin_top"
+        android:scaleType="fitCenter"
+        style="@style/Preference.CarUi.Icon"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_marginBottom="@dimen/car_ui_preference_content_margin_bottom"
+        android:layout_marginTop="@dimen/car_ui_preference_content_margin_top"
+        android:layout_toEndOf="@android:id/icon"
+        android:layout_toStartOf="@android:id/widget_frame"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="@style/TextAppearance.CarUi.PreferenceTitle"/>
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@style/TextAppearance.CarUi.PreferenceSummary"/>
+
+    </LinearLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <FrameLayout
+        android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentEnd="true"
+        android:layout_centerVertical="true"/>
+
+</RelativeLayout>
diff --git a/car-ui-lib/res/layout/car_ui_preference_category.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_category.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_preference_category.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_category.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_chevron.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_chevron.xml
new file mode 100644
index 0000000..e63e74c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_chevron.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_horizontal"
+    android:src="@drawable/car_ui_preference_icon_chevron"/>
diff --git a/car-ui-lib/res/layout/car_ui_preference_dialog_edittext.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_dialog_edittext.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_preference_dialog_edittext.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_dialog_edittext.xml
diff --git a/car-ui-lib/res/layout/car_ui_preference_dropdown.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_dropdown.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_preference_dropdown.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_dropdown.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_fragment.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_fragment.xml
new file mode 100644
index 0000000..53fc089
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_fragment.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+
+    <FrameLayout
+        android:id="@android:id/list_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <com.android.car.ui.FocusArea
+            android:id="@+id/car_ui_focus_area"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <com.android.car.ui.recyclerview.CarUiRecyclerView
+                android:id="@+id/recycler_view"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:tag="carUiPreferenceRecyclerView"
+                app:enableDivider="true"/>
+        </com.android.car.ui.FocusArea>
+    </FrameLayout>
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_fragment_with_toolbar.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_fragment_with_toolbar.xml
new file mode 100644
index 0000000..b3c6ea9
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_fragment_with_toolbar.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020 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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/car_ui_preference_fragment_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+
+    <FrameLayout
+        android:id="@android:id/list_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <com.android.car.ui.FocusArea
+            android:id="@+id/car_ui_focus_area"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <com.android.car.ui.recyclerview.CarUiRecyclerView
+                android:id="@+id/recycler_view"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:tag="carUiPreferenceRecyclerView"
+                app:enableDivider="true"/>
+        </com.android.car.ui.FocusArea>
+    </FrameLayout>
+
+    <com.android.car.ui.toolbar.Toolbar
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/toolbar"
+        app:car_ui_state="subpage"/>
+</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_preference_widget_checkbox.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_widget_checkbox.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_preference_widget_checkbox.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_widget_checkbox.xml
diff --git a/car-ui-lib/res/layout/car_ui_preference_widget_seekbar.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_widget_seekbar.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_preference_widget_seekbar.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_widget_seekbar.xml
diff --git a/car-ui-lib/res/layout/car_ui_preference_widget_switch.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_widget_switch.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_preference_widget_switch.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_preference_widget_switch.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_radio_button_preference_widget.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_radio_button_preference_widget.xml
new file mode 100644
index 0000000..d179a09
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_radio_button_preference_widget.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<RadioButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/radio_button"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:clickable="false"
+    android:focusable="false"/>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recycler_view.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recycler_view.xml
new file mode 100644
index 0000000..a0c955f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recycler_view.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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.
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <include layout="@layout/car_ui_recyclerview_scrollbar"/>
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerViewContainer
+        android:id="@+id/car_ui_recycler_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginEnd="@dimen/car_ui_scrollbar_margin"
+        android:tag="carUiRecyclerView"
+        android:layout_weight="1"/>
+</merge>
diff --git a/car-ui-lib/res/layout/car_ui_recycler_view_item.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recycler_view_item.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_recycler_view_item.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recycler_view_item.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recyclerview_scrollbar.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recyclerview_scrollbar.xml
new file mode 100644
index 0000000..5896819
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_recyclerview_scrollbar.xml
@@ -0,0 +1,77 @@
+<?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.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="@dimen/car_ui_scrollbar_container_width"
+    android:layout_height="match_parent"
+    android:id="@+id/car_ui_scroll_bar"
+    android:gravity="center">
+
+    <ImageView
+        android:id="@+id/car_ui_scrollbar_page_up"
+        android:layout_width="@dimen/car_ui_scrollbar_button_size"
+        android:layout_height="@dimen/car_ui_scrollbar_button_size"
+        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
+        android:contentDescription="@string/car_ui_scrollbar_page_up_button"
+        android:focusable="false"
+        android:hapticFeedbackEnabled="false"
+        android:src="@drawable/car_ui_recyclerview_ic_up"
+        android:scaleType="centerInside"
+        android:layout_marginTop="15dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+
+    <!-- View height is dynamically calculated during layout. -->
+    <View
+        android:id="@+id/car_ui_scrollbar_thumb"
+        android:layout_width="@dimen/car_ui_scrollbar_thumb_width"
+        android:layout_height="0dp"
+        android:layout_gravity="center_horizontal"
+        android:background="@drawable/car_ui_recyclerview_scrollbar_thumb"
+        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+
+    <View
+        android:id="@+id/car_ui_scrollbar_track"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_marginTop="@dimen/car_ui_scrollbar_separator_margin"
+        android:layout_marginBottom="@dimen/car_ui_scrollbar_separator_margin"
+        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
+        app:layout_constraintBottom_toTopOf="@+id/car_ui_scrollbar_page_down"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <ImageView
+        android:id="@+id/car_ui_scrollbar_page_down"
+        android:layout_width="@dimen/car_ui_scrollbar_button_size"
+        android:layout_height="@dimen/car_ui_scrollbar_button_size"
+        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
+        android:contentDescription="@string/car_ui_scrollbar_page_down_button"
+        android:focusable="false"
+        android:hapticFeedbackEnabled="false"
+        android:src="@drawable/car_ui_recyclerview_ic_down"
+        android:scaleType="centerInside"
+        android:layout_marginBottom="15dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_seekbar_dialog.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_seekbar_dialog.xml
new file mode 100644
index 0000000..90124c4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_seekbar_dialog.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+     Copyright (C) 2020 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="match_parent"
+              android:gravity="center_horizontal"
+              android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/seek_bar_text_top"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        style="@style/Preference.CarUi.DialogSeekBarPreference.TopText"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:id="@+id/seek_bar_text_left"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            style="@style/Preference.CarUi.DialogSeekBarPreference.LeftText"/>
+
+        <SeekBar
+            android:id="@+id/seek_bar"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            style="@style/Preference.CarUi.DialogSeekBarPreference.Seekbar"/>
+
+        <TextView
+            android:id="@+id/seek_bar_text_right"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            style="@style/Preference.CarUi.DialogSeekBarPreference.RightText"/>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar.xml
new file mode 100644
index 0000000..42cc59a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar.xml
@@ -0,0 +1,182 @@
+<?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.
+-->
+<com.android.car.ui.FocusArea
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/car_ui_toolbar_first_row_height">
+    <androidx.constraintlayout.widget.ConstraintLayout
+        xmlns:app="http://schemas.android.com/apk/res-auto"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/car_ui_toolbar_background"
+        android:tag="carUiToolbar"
+        style="@style/Widget.CarUi.Toolbar.Container">
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_start_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
+            android:orientation="vertical"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_top_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
+            android:orientation="horizontal"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_end_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
+            android:orientation="vertical"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
+            android:orientation="horizontal"/>
+
+        <!-- The horizontal bias here is so that when you set this view as GONE, it will be
+             treated as if it's all the way to the left instead of centered in the margin -->
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_nav_icon_container"
+            android:layout_width="@dimen/car_ui_toolbar_margin"
+            android:layout_height="0dp"
+            style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_start_guideline"
+            app:layout_constraintHorizontal_bias="0.0">
+            <ImageView
+                android:id="@+id/car_ui_toolbar_nav_icon"
+                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"
+                style="@style/Widget.CarUi.Toolbar.NavIcon"/>
+            <ImageView
+                android:id="@+id/car_ui_toolbar_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"/>
+        </FrameLayout>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_title_logo_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/Widget.CarUi.Toolbar.LogoContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
+
+            <ImageView
+                android:id="@+id/car_ui_toolbar_title_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:scaleType="fitXY"
+                android:layout_gravity="center"
+                style="@style/Widget.CarUi.Toolbar.Logo"/>
+        </FrameLayout>
+
+        <LinearLayout android:layout_height="wrap_content"
+                      android:layout_width="0dp"
+                      android:id="@+id/car_ui_toolbar_title_container"
+                      android:orientation="vertical"
+                      android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
+                      app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
+                      app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+                      app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+                      app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+                      app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container">
+            <TextView android:id="@+id/car_ui_toolbar_title"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:singleLine="true"
+                      style="@style/Widget.CarUi.Toolbar.Title"/>
+            <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:visibility="gone"
+                      style="@style/Widget.CarUi.Toolbar.Subtitle"/>
+        </LinearLayout>
+
+        <com.android.car.ui.toolbar.TabLayout
+            android:id="@+id/car_ui_toolbar_tabs"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+            app:layout_constraintHorizontal_bias="0.0"/>
+
+        <LinearLayout
+            android:id="@+id/car_ui_toolbar_menu_items_container"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            android:orientation="horizontal"
+            style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_end_guideline"/>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_search_view_container"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/car_ui_toolbar_search_height"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_row_separator"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_separator_height"
+            style="@style/Widget.CarUi.Toolbar.SeparatorView"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ProgressBar
+            android:id="@+id/car_ui_toolbar_progress_bar"
+            style="@style/Widget.CarUi.Toolbar.ProgressBar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            android:indeterminate="true"
+            android:visibility="gone"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_bottom_styleable"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
+            style="@style/Widget.CarUi.Toolbar.BottomView"
+            app:layout_constraintBottom_toTopOf="@+id/car_ui_toolbar_progress_bar"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</com.android.car.ui.FocusArea>
diff --git a/car-ui-lib/res/layout/car_ui_toolbar_menu_item.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_menu_item.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_toolbar_menu_item.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_menu_item.xml
diff --git a/car-ui-lib/res/layout/car_ui_toolbar_search_view.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_search_view.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_toolbar_search_view.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_search_view.xml
diff --git a/car-ui-lib/res/layout/car_ui_toolbar_tab_item.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_tab_item.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_toolbar_tab_item.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_tab_item.xml
diff --git a/car-ui-lib/res/layout/car_ui_toolbar_tab_item_flexible.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_tab_item_flexible.xml
similarity index 100%
rename from car-ui-lib/res/layout/car_ui_toolbar_tab_item_flexible.xml
rename to car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_tab_item_flexible.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_two_row.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_two_row.xml
new file mode 100644
index 0000000..9fecb3f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_toolbar_two_row.xml
@@ -0,0 +1,182 @@
+<?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.
+-->
+<com.android.car.ui.FocusArea
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+    <androidx.constraintlayout.widget.ConstraintLayout
+        xmlns:app="http://schemas.android.com/apk/res-auto"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/car_ui_toolbar_background"
+        style="@style/Widget.CarUi.Toolbar.Container">
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_start_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
+            android:orientation="vertical"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_top_guideline"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
+            android:orientation="horizontal"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_end_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
+            android:orientation="vertical"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/car_ui_toolbar_bottom_guideline"
+            app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
+            android:orientation="horizontal"/>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/car_ui_toolbar_row_separator_guideline"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_first_row_height"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_row_separator"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_separator_height"
+            style="@style/Widget.CarUi.Toolbar.SeparatorView"
+            app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_nav_icon_container"
+            android:layout_width="@dimen/car_ui_toolbar_margin"
+            android:layout_height="0dp"
+            style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toStartOf="@id/car_ui_toolbar_start_guideline">
+            <ImageView
+                android:id="@+id/car_ui_toolbar_nav_icon"
+                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"
+                style="@style/Widget.CarUi.Toolbar.NavIcon"/>
+            <ImageView
+                android:id="@+id/car_ui_toolbar_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:layout_gravity="center"
+                android:scaleType="fitXY"/>
+        </FrameLayout>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_title_logo_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/Widget.CarUi.Toolbar.LogoContainer"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
+
+            <ImageView
+                android:id="@+id/car_ui_toolbar_title_logo"
+                android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                android:scaleType="fitXY"
+                android:layout_gravity="center"
+                style="@style/Widget.CarUi.Toolbar.Logo"/>
+        </FrameLayout>
+
+        <LinearLayout android:layout_height="wrap_content"
+                      android:layout_width="0dp"
+                      android:id="@+id/car_ui_toolbar_title_container"
+                      android:orientation="vertical"
+                      android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
+                      app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
+                      app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+                      app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+                      app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_title_logo_container"
+                      app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_menu_items_container">
+            <TextView android:id="@+id/car_ui_toolbar_title"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:singleLine="true"
+                      style="@style/Widget.CarUi.Toolbar.Title"/>
+            <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:visibility="gone"
+                      style="@style/Widget.CarUi.Toolbar.Subtitle"/>
+        </LinearLayout>
+
+        <FrameLayout
+            android:id="@+id/car_ui_toolbar_search_view_container"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/car_ui_toolbar_search_height"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
+
+        <LinearLayout
+            android:id="@+id/car_ui_toolbar_menu_items_container"
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            android:orientation="horizontal"
+            style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
+            app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_end_guideline"/>
+
+        <com.android.car.ui.toolbar.TabLayout
+            android:id="@+id/car_ui_toolbar_tabs"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_second_row_height"
+            app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"/>
+
+        <View
+            android:id="@+id/car_ui_toolbar_bottom_styleable"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
+            style="@style/Widget.CarUi.Toolbar.BottomView"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ProgressBar
+            android:id="@+id/car_ui_toolbar_progress_bar"
+            style="@style/Widget.CarUi.Toolbar.ProgressBar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_styleable"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            android:indeterminate="true"
+            android:visibility="gone"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</com.android.car.ui.FocusArea>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_two_action_preference.xml b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_two_action_preference.xml
new file mode 100644
index 0000000..7c633e0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/layout/car_ui_two_action_preference.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2018 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:background="@android:color/transparent"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall">
+    <LinearLayout
+        android:id="@+id/car_ui_preference_container_without_widget"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="?android:attr/selectableItemBackground"
+        android:clipToPadding="false"
+        android:gravity="start|center_vertical"
+        android:paddingBottom="@dimen/car_ui_preference_content_margin_bottom"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingTop="@dimen/car_ui_preference_content_margin_top">
+        <androidx.preference.internal.PreferenceImageView
+            android:id="@android:id/icon"
+            android:layout_width="@dimen/car_ui_preference_icon_size"
+            android:layout_height="@dimen/car_ui_preference_icon_size"
+            android:layout_marginEnd="@dimen/car_ui_preference_icon_margin_end"/>
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:orientation="vertical">
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ellipsize="end"
+                android:singleLine="true"
+                android:textAppearance="@style/TextAppearance.CarUi.PreferenceTitle"/>
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.CarUi.PreferenceSummary"/>
+        </LinearLayout>
+    </LinearLayout>
+    <LinearLayout
+        android:id="@+id/action_widget_container"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent">
+        <View
+            android:layout_width="@dimen/car_ui_divider_width"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="@dimen/car_ui_preference_content_margin_bottom"
+            android:layout_marginTop="@dimen/car_ui_preference_content_margin_top"
+            style="@style/Preference.CarUi.Divider"/>
+        <!-- Preference should place its actual preference widget here. -->
+        <FrameLayout
+            android:id="@android:id/widget_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:background="?android:attr/selectableItemBackground"
+            android:minWidth="?android:attr/listPreferredItemHeightSmall"
+            android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+            android:paddingStart="?android:attr/listPreferredItemPaddingStart"/>
+    </LinearLayout>
+</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-af/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-af/strings.xml
new file mode 100644
index 0000000..2c00927
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-af/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Soek …"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Rollees af"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Rollees op"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Terug"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Soek"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Instellings"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Oorloop"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Aan"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Af"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Maak toe"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Rollees word beperk terwyl jy bestuur"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Kenmerk is nie beskikbaar terwyl jy bestuur nie"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-am/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000..0558e81
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-am/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ይፈልጉ…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"ወደ ታች ይሸብልሉ"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ወደ ላይ ይሸብልሉ"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ተመለስ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ፈልግ"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ቅንብሮች"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ትርፍ ፍሰት"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"አብራ"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ቅናሽ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"ዝጋ"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"እየነዱ ማሸብለል ተገድቧል"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"እየነዱ ሳለ ባህሪው አይገኝም"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ar/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000..4879cb5
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ar/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"بحث…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"التمرير للأسفل"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"التمرير للأعلى"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"رجوع"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"بحث"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"إعدادات"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"القائمة الكاملة"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"مفعّل"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"غير مفعَّل"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"إغلاق"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"هناك حد أقصى للتمرير على الشاشة أثناء القيادة."</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"لا تتوفَّر هذه الميزة أثناء القيادة."</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-as/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-as/strings.xml
new file mode 100644
index 0000000..060f64e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-as/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"সন্ধান কৰক…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"তললৈ স্ক্ৰ’ল কৰক"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ওপৰলৈ স্ক্ৰ’ল কৰক"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"উভতি যাওক"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"সন্ধান কৰক"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ছেটিংসমূহ"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"অভাৰফ্ল’"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"অন আছে"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"অফ আছে"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"বন্ধ কৰক"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"গাড়ী চলাই থকা সময়ত স্ক্ৰ’ল কৰাটো সীমিত কৰা হৈছে"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"গাড়ী চলাই থকা সময়ত এই সুবিধাটো উপলব্ধ নহয়"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-az/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-az/strings.xml
new file mode 100644
index 0000000..9f0472e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-az/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Axtarış…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Aşağı sürüşdürün"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Yuxarı sürüşdürün"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Geri"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Axtarış"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Ayarlar"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Kənara çıxma"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Aktiv"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Deaktiv"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Qapadın"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Sürüşdürmə avtomobil idarə edərkən məhdudlaşdırılır"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funksiya avtomobil idarə edərkən əlçatan deyil"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-b+sr+Latn/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..2584a57
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Pretražite…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Pomerite nadole"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Pomerite nagore"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Nazad"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Pretraži"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Podešavanja"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Preklopni meni"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Uključeno"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Isključeno"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Zatvori"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Pomeranje je ograničeno tokom vožnje"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkcija nije dostupna tokom vožnje"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-be/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000..c66577d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-be/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Пошук…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Прагартаць уніз"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Прагартаць уверх"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Назад"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Пошук"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Налады"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Дадатковае меню"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Уключана"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Выключана"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Закрыць"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Функцыя прагортвання абмежаваная, калі аўтамабіль рухаецца"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Функцыя недаступная, калі аўтамабіль рухаецца"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-bg/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000..64d1e0a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-bg/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Търсете…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Превъртане надолу"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Превъртане нагоре"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Назад"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Търсене"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Настройки"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Препълване"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Вкл."</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Изкл."</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Затваряне"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Превъртането е ограничено при шофиране"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Функцията не е налице по време на шофиране"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-bn/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-bn/strings.xml
new file mode 100644
index 0000000..7f09486
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-bn/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"সার্চ করুন…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"নিচের দিকে স্ক্রল করুন"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"উপরের দিকে স্ক্রল করুন"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ফিরুন"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"সার্চ মেনু"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"সেটিংস"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ওভারফ্লো মেনু"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"চালু"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"বন্ধ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"বন্ধ করুন"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"গাড়ি চালানোর সময় স্ক্রলিং ফিচার সীমিতভাবে ব্যবহার করা যাবে"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"গাড়ি চালানোর সময় এই ফিচার কাজ করবে না"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-bs/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000..7295dac
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-bs/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Pretražite…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Klizanje prema dolje"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Klizanje prema gore"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Nazad"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Pretraživanje"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Postavke"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Preklopni meni"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Uključeno"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Isključeno"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Zatvori"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Klizanje je ograničeno tokom vožnje"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkcija nije dostupna tokom vožnje"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ca/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000..a19a663
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ca/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Cerca…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Desplaça cap avall"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Desplaça cap amunt"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Enrere"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Cerca"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Configuració"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Menú addicional"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Activat"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Desactivat"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Tanca"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"El desplaçament està limitat mentre condueixes"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Aquesta funció no està disponible mentre condueixes"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-cs/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000..16ad755
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-cs/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Vyhledat…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Posunout dolů"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Posunout nahoru"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Zpět"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Hledat"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Nastavení"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Rozbalovací nabídka"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Zap"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Vyp"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Zavřít"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Posouvání zobrazení je při řízení omezeno"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkce při řízení není dostupná"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-da/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000..80d4a64
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-da/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Søg…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Rul ned"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Rul op"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Tilbage"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Søg"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Indstillinger"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overløb"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Til"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Fra"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Luk"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Rullefunktionen er begrænset under kørsel"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funktionen er ikke tilgængelig, mens du kører"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-de/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000..8a76bd3
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-de/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Suchen…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Nach unten scrollen"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Nach oben scrollen"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Zurück"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Suchen"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Einstellungen"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Dreipunkt-Menü"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"An"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Aus"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Schließen"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scrollen während der Fahrt eingeschränkt"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funktion während der Fahrt nicht verfügbar"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-el/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000..1819ec2
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-el/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Αναζήτηση…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Κύλιση προς τα κάτω"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Κύλιση προς τα επάνω"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Πίσω"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Αναζήτηση"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Ρυθμίσεις"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Υπερχείλιση"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Ενεργό"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Ανενεργή"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Κλείσιμο"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Η κύλιση είναι περιορισμένη κατά τη διάρκεια της οδήγησης."</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Η λειτουργία δεν διατίθεται κατά τη διάρκεια της οδήγησης."</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-en-rAU/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..fb25c85
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-en-rAU/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Search…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Scroll down"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Scroll up"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Back"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Search"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Settings"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overflow"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"On"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Off"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Close"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scrolling limited while driving"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Feature not available while driving"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-en-rCA/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..fb25c85
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Search…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Scroll down"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Scroll up"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Back"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Search"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Settings"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overflow"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"On"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Off"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Close"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scrolling limited while driving"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Feature not available while driving"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-en-rGB/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..fb25c85
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Search…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Scroll down"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Scroll up"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Back"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Search"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Settings"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overflow"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"On"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Off"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Close"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scrolling limited while driving"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Feature not available while driving"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-en-rIN/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..fb25c85
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-en-rIN/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Search…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Scroll down"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Scroll up"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Back"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Search"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Settings"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overflow"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"On"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Off"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Close"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scrolling limited while driving"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Feature not available while driving"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-en-rXC/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..82c6ca1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-en-rXC/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎Search…‎‏‎‎‏‎"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎Scroll down‎‏‎‎‏‎"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎Scroll up‎‏‎‎‏‎"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎Back‎‏‎‎‏‎"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‎Search‎‏‎‎‏‎"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎Settings‎‏‎‎‏‎"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎Overflow‎‏‎‎‏‎"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎On‎‏‎‎‏‎"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎Off‎‏‎‎‏‎"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎Close‎‏‎‎‏‎"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‎Scrolling limited while driving‎‏‎‎‏‎"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‎Feature not available while driving‎‏‎‎‏‎"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-es-rUS/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..4904ad4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-es-rUS/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Buscar…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Desplazamiento hacia abajo"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Desplazamiento hacia arriba"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Atrás"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Buscar"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Configuración"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Ampliado"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Sí"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"No"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Cerrar"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"La función de desplazamiento se limita al conducir"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Esta función no está disponible mientras conduces"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-es/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000..171134a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-es/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Realiza una búsqueda…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Desplazarse hacia abajo"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Desplazarse hacia arriba"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Atrás"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Buscar"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Ajustes"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Menú adicional"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Activado"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Desactivado"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Cerrar"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Desplazamiento limitado mientras conduces"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Función no disponible mientras conduces"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-et/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000..bb5092c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-et/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Otsing …"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Keri alla"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Keri üles"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Tagasi"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Otsi"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Seaded"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Ületäide"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Sees"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Väljas"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Sule"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Kerimine on sõitmise ajal piiratud"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funktsioon pole sõidu ajal saadaval"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-eu/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000..af4e757
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-eu/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Bilatu…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Egin behera"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Egin gora"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Atzera"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Bilaketa"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Ezarpenak"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Luzapena"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Aktibatuta"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Desaktibatuta"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Itxi"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Gora edo behera egiteko eginbidea mugatuta dago gidatu bitartean"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Eginbide hau ezin da erabili gidatu bitartean"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-fa/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000..1ddc1df
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-fa/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"جستجو…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"پیمایش به پایین"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"پیمایش به بالا"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"برگشت"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"جستجو"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"تنظیمات"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"لبریزشده"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"روشن"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"خاموش"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"بستن"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"پیمایش درحین رانندگی محدود شده است"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"این ویژگی هنگام رانندگی در دسترس نیست"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-fi/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000..31c1e62
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-fi/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Hae…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Vieritä alas"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Vieritä ylös"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Takaisin"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Haku"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Asetukset"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Ylivuoto"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Päällä"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Pois"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Sulje"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Vierittämistä rajoitettu ajon aikana"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Ominaisuus ei ole käytettävissä ajon aikana"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-fr-rCA/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..a894032
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-fr-rCA/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Rechercher…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Faire défiler vers le bas"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Faire défiler vers le haut"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Retour"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Rechercher"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Paramètres"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Menu déroulant"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Activé"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Désactivé"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Fermer"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Le défilement de l\'écran est limité durant la conduite"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Cette fonctionnalité n\'est pas accessible durant la conduite"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-fr/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000..8776859
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-fr/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Rechercher…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Défiler vers le bas"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Défiler vers le haut"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Retour"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Rechercher"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Paramètres"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Menu à développer"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Activé"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Désactivé"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Fermer"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Défilement limité lorsque vous conduisez"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Fonctionnalité non disponible lorsque vous conduisez"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-gl/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000..7882edf
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-gl/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Busca…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Desprazarse cara abaixo"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Desprazarse cara arriba"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Atrás"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Buscar"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Configuración"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Elemento do menú adicional"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Si"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Non"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Pechar"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"O desprazamento está limitado mentres conduces"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Esta función non está dispoñible mentres conduces"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-gu/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-gu/strings.xml
new file mode 100644
index 0000000..25d6fbc
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-gu/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"શોધો…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"નીચે સ્ક્રોલ કરો"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ઉપર સ્ક્રોલ કરો"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"પાછળ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"શોધો"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"સેટિંગ"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ઓવરફ્લો"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ચાલુ"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"બંધ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"બંધ કરો"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ડ્રાઇવિંગ કરતી વખતે સ્ક્રોલ કરવું મર્યાદિત છે"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ડ્રાઇવિંગ કરતી વખતે આ સુવિધા ઉપલબ્ધ રહેશે નહીં"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-hi/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-hi/strings.xml
new file mode 100644
index 0000000..21aaf3c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-hi/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"खोजें…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"नीचे की ओर स्क्रोल करें"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ऊपर की ओर स्क्रोल करें"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"वापस जाएं"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"खोजें"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"सेटिंग"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ओवरफ़्लो मेन्यू"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"चालू है"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"बंद है"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"बंद करें"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"गाड़ी चलाते समय इससे ज़्यादा स्क्रोल नहीं कर सकते"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"गाड़ी चलाते समय इस सुविधा का इस्तेमाल नहीं किया जा सकता"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-hr/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000..1bc74b5
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-hr/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Pretražite…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Pomak prema dolje"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Pomak prema gore"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Natrag"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Pretraži"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Postavke"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Dodatno"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Uključeno"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Isključeno"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Zatvori"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Pomicanje je ograničeno tijekom vožnje"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Značajka nije dostupna tijekom vožnje"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-hu/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000..912809b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-hu/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Keresés…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Görgetés lefelé"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Görgetés felfelé"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Vissza"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Keresés"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Beállítások"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"További elemeket tartalmazó menü"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Be"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Ki"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Bezárás"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Vezetés közben a görgetés korlátozott"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Vezetés közben nem áll rendelkezésre a funkció"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-hy/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-hy/strings.xml
new file mode 100644
index 0000000..bed2d2c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-hy/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Որոնում…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Ոլորել վար"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Ոլորել վեր"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Հետ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Որոնել"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Կարգավորումներ"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Լրացուցիչ ընտրացանկ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Միացված է"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Անջատված է"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Փակել"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Վարելու ընթացքում ոլորումը սահմանափակված է"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Վարելու ընթացքում գործառույթը հասանելի չէ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-in/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000..b3d7063
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-in/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Telusuri…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Scroll ke bawah"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Scroll ke atas"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Kembali"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Penelusuran"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Setelan"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Tambahan"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Aktif"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Nonaktif"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Tutup"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Men-scroll dibatasi saat mengemudi"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Fitur tidak tersedia saat mengemudi"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-is/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000..61d2891
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-is/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Leita…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Fletta niður"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Fletta upp"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Til baka"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Leit"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Stillingar"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Yfirflæði"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Kveikt"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Slökkt"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Loka"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Fletting er takmörkuð meðan á akstri stendur"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Þessi eiginleiki er ekki í boði meðan á akstri stendur"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-it/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000..2cb178a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-it/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Cerca…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Scorri verso il basso"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Scorri verso l\'alto"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Indietro"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Cerca"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Impostazioni"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Extra"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"On"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Off"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Chiudi"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scorrimento limitato durante la guida"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funzionalità non disponibile durante la guida"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-iw/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000..746dfbc
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-iw/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"חיפוש…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"גלילה למטה"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"גלילה למעלה"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"חזרה"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"חיפוש"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"הגדרות"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"אפשרויות נוספות"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"פועל"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"כבוי"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"סגירה"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"הגלילה מוגבלת בזמן הנהיגה"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"התכונה לא זמינה בזמן הנהיגה"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ja/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000..7d8eac1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ja/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"検索…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"下にスクロール"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"上にスクロール"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"戻る"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"検索"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"設定"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"オーバーフロー"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ON"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"OFF"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"閉じる"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"運転中のスクロール操作は制限されています"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"この機能は運転中は利用できません"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ka/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000..1350fe8
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ka/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ძიება…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"ქვემოთ გადაადგილება"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ზემოთ გადაადგილება"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"უკან"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ძიება"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"პარამეტრები"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"გადავსება"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ჩართულია"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"გამორთულია"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"დახურვა"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"გადაადგილება შეზღუდულია მანქანის მართვისას"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ფუნქცია მიუწვდომელია მანქანის მართვისას"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-kk/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000..ab8a259
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-kk/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Іздеу…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Төмен айналдыру"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Жоғары айналдыру"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Артқа"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Іздеу"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Параметрлер"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Қосымша мәзір"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Қосулы"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Өшірулі"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Жабу"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Көлік жүргізу кезінде айналдыру мүмкіндігі шектеледі."</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Көлік жүргізу кезінде бұл функция жұмыс істемейді."</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-km/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-km/strings.xml
new file mode 100644
index 0000000..17d3293
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-km/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ស្វែងរក…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"រំកិលចុះក្រោម"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"រំកិល​​ឡើង​លើ"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ថយក្រោយ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ស្វែងរក"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ការកំណត់"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ម៉ឺនុយបន្ថែម"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"បើក"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"បិទ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"បិទ"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ការរំកិលបានកំណត់ ខណៈពេលកំពុង​បើកបរ"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"មិនអាច​ប្រើមុខងារ​នេះបានទេ ខណៈពេល​កំពុង​បើកបរ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-kn/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-kn/strings.xml
new file mode 100644
index 0000000..3d312d1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-kn/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ಹುಡುಕಿ…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"ಕೆಳಗೆ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ಮೇಲೆ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ಹಿಂದಕ್ಕೆ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ಹುಡುಕಾಟ"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ಓವರ್‌ಫ್ಲೋ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ಆನ್ ಆಗಿದೆ"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ಆಫ್ ಆಗಿದೆ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"ಮುಚ್ಚಿ"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ಡ್ರೈವ್ ಮಾಡುವಾಗ ಸ್ಕ್ರಾಲ್ ಮಾಡುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸೀಮಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ಡ್ರೈವ್ ಮಾಡುವಾಗ ಈ ವೈಶಿಷ್ಟ್ಯ ಲಭ್ಯವಿಲ್ಲ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ko/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000..d992a45
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ko/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"검색…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"아래로 스크롤"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"위로 스크롤"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"뒤로"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"검색"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"설정"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"더보기"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"사용 설정됨"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"사용 중지됨"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"닫기"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"운전 중에는 스크롤이 제한됨"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"운전 중에 사용할 수 없는 기능입니다."</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ky/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ky/strings.xml
new file mode 100644
index 0000000..7340674
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ky/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Издөө…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Төмөн сыдыруу"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Жогору сыдыруу"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Артка"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Издөө"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Жөндөөлөр"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Кошумча меню"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Күйүк"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Өчүк"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Жабуу"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Унаа айдаганда сыдыруу чектелет"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Унаа айдаганда бул функция жеткиликтүү эмес"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-lo/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000..0422da3
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-lo/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ຊອກຫາ…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"ເລື່ອນລົງ"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ເລື່ອນຂຶ້ນ"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ກັບຄືນ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ຊອກຫາ"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ການຕັ້ງຄ່າ"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ລົ້ນ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ເປີດ"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ປິດ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"ປິດ"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ຈຳກັດການເລື່ອນໃນຂະນະທີ່ຂັບລົດ"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ຄຸນສົມບັດບໍ່ສາມາດໃຊ້ໄດ້ໃນເວລາຂັບລົດ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-lt/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000..09539cc
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-lt/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Ieškoti…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Slinkti žemyn"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Slinkti aukštyn"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Atgal"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Paieška"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Nustatymai"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Perpildymas"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Įjungta"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Išjungta"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Uždaryti"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Slinkimas apribotas vairuojant"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkcija nepasiekiama vairuojant"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-lv/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-lv/strings.xml
new file mode 100644
index 0000000..1df9318
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-lv/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Meklēt…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Ritināt uz leju"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Ritināt uz augšu"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Atpakaļ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Meklēšana"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Iestatījumi"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Pārpilde"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Ieslēgta"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Izslēgta"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Aizvērt"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Ritināšana ir ierobežota braukšanas laikā."</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkcija nav pieejama braukšanas laikā."</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-mk/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-mk/strings.xml
new file mode 100644
index 0000000..413e340
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-mk/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Пребарувајте…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Оди надолу"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Оди нагоре"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Назад"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Пребарување"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Поставки"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Прелевање"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Вклучено"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Исклучено"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Затвори"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Лизгањето е ограничено при возење"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Функцијата не е достапна при возење"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ml/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ml/strings.xml
new file mode 100644
index 0000000..f588c60
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ml/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"തിരയുക…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"താഴോട്ട് സ്‌ക്രോൾ ചെയ്യുക"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"മുകളിലോട്ട് സ്‌ക്രോൾ ചെയ്യുക"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"മടങ്ങുക"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"തിരയുക"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ക്രമീകരണം"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ഓവർഫ്ലോ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ഓണാണ്"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ഓഫാണ്"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"അടയ്‌ക്കുക"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ഡ്രൈവ് ചെയ്യുമ്പോൾ സ്ക്രോൾ ചെയ്യൽ പരിമിതപ്പെടുത്തിയിരിക്കുന്നു"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ഡ്രൈവ് ചെയ്യുമ്പോൾ ഫീച്ചർ ലഭ്യമല്ല"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-mn/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-mn/strings.xml
new file mode 100644
index 0000000..db34cd7
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-mn/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Хайх..."</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Доош гүйлгэх"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Дээш гүйлгэх"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Буцах"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Хайлт"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Тохиргоо"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Халих"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Асаалттай"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Унтраалттай"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Хаах"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Жолоо барьж байх үед гүйлгэхийг хязгаарласан"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Жолоо барьж байх үед онцлог боломжгүй"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-mr/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000..c8f7a42
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-mr/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"शोधा…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"खाली स्क्रोल करा"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"वर स्क्रोल करा"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"मागे जा"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Search"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"सेटिंग्ज"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ओव्हरफ्लो"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"सुरू आहे"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"बंद आहे"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"बंद करा"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ड्राइव्ह करताना स्क्रोलिंग मर्यादित केली आहे"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ड्राइव्ह करताना वैशिष्ट्य उपलब्ध नाही"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ms/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ms/strings.xml
new file mode 100644
index 0000000..7ea4fbb
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ms/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Cari…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Tatal ke bawah"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Tatal ke atas"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Kembali"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Cari"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Tetapan"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Limpahan"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Hidup"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Mati"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Tutup"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Penatalan terhad semasa memandu"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Ciri tidak tersedia semasa anda memandu"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-my/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000..55f37b1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-my/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ရှာဖွေရန်…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"အောက်သို့ လှိမ့်ရန်"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"အပေါ်သို့ လှိမ့်ရန်"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"နောက်သို့"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ရှာဖွေခြင်း"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ဆက်တင်များ"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"အပို"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ဖွင့်ထားသည်"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ပိတ်ထားသည်"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"ပိတ်ရန်"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ယာဉ်မောင်းနေစဉ် အပေါ်အောက်ရွှေ့ခြင်းကို ကန့်သတ်ထားသည်"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ကားမောင်းနေစဉ် ဝန်ဆောင်မှု မရနိုင်ပါ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-nb/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-nb/strings.xml
new file mode 100644
index 0000000..d490393
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-nb/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Søk"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Rull ned"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Rull opp"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Tilbake"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Søk"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Innstillinger"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overflyt"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"På"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Av"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Lukk"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Rullefunksjonen er begrenset mens du kjører"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funksjonen er ikke tilgjengelig når du kjører"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ne/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ne/strings.xml
new file mode 100644
index 0000000..90124de
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ne/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"खोज्नुहोस्…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"तलतिर स्क्रोल गर्नुहोस्"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"माथितिर स्क्रोल गर्नु…"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"पछाडि"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"खोज्नुहोस्"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"सेटिङ"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ओभरफ्लो"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"सुचारू छ"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"बन्द छ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"बन्द गर्नुहोस्"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"सवारी साधन चलाइरहेका बेला योभन्दा बढी स्क्रोल गर्न पाइँदैन"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"सवारी साधन चलाइरहेका बेला यो सुविधा उपलब्ध हुँदैन"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-nl/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000..fe36ab0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-nl/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Zoeken…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Omlaag scrollen"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Omhoog scrollen"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Terug"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Zoeken"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Instellingen"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overloop"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Aan"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Uit"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Sluiten"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scrollen is beperkt tijdens het rijden"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Functie niet beschikbaar tijdens het rijden"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-or/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-or/strings.xml
new file mode 100644
index 0000000..d84ae51
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-or/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ସନ୍ଧାନ କରନ୍ତୁ…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"ତଳକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ଉପରକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ପଛକୁ ଫେରନ୍ତୁ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ସନ୍ଧାନ କରନ୍ତୁ"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ସେଟିଂସ୍"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ଓଭରଫ୍ଲୋ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ଚାଲୁ ଅଛି"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ବନ୍ଦ ଅଛି"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ଗାଡ଼ି ଚଲାଇବା ସମୟରେ ସ୍କ୍ରୋଲିଂ ସୀମିତ ଅଟେ"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ଗାଡ଼ି ଚଲାଇବା ସମୟରେ ଫିଚର୍ ଉପଲବ୍ଧ ହେବ ନାହିଁ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-pa/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-pa/strings.xml
new file mode 100644
index 0000000..576c6d4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-pa/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ਖੋਜ…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"ਹੇਠਾਂ ਵੱਲ ਸਕ੍ਰੋਲ ਕਰੋ"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ਉੱਪਰ ਵੱਲ ਸਕ੍ਰੋਲ ਕਰੋ"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ਪਿੱਛੇ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ਖੋਜ"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ਓਵਰਫ਼ਲੋ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ਚਾਲੂ"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ਬੰਦ"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"ਬੰਦ ਕਰੋ"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ਚਲਦੀ ਗੱਡੀ ਵਿੱਚ ਸਕ੍ਰੋਲ ਕਰਨ ਨੂੰ ਸੀਮਤ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ਚੱਲਦੀ ਗੱਡੀ ਵਿੱਚ ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-pl/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000..85df36d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-pl/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Szukaj…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Przewiń w dół"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Przewiń w górę"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Wstecz"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Szukaj"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Ustawienia"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Rozszerzone menu"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Wł."</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Wył."</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Zamknij"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Podczas jazdy można przewijać tylko w ograniczonym zakresie"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkcja niedostępna podczas jazdy"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-port/bools.xml b/car-ui-lib/car-ui-lib/src/main/res/values-port/bools.xml
new file mode 100644
index 0000000..136b3e9
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-port/bools.xml
@@ -0,0 +1,26 @@
+<?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>
+   <!-- Toolbar -->
+
+   <!-- Normally no resources should live in any other resource folder than default configuration. -->
+   <!-- Because OEMs will have to always add them to their RROs. -->
+   <!-- But we can't remove this resource from -port folder, because it was used as part of an earlier release -->
+   <!-- Whether tabs should use flex layout or not -->
+   <bool name="car_ui_toolbar_tab_flexible_layout">true</bool>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-pt-rPT/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..ad969e8
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Pesquisar…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Deslocar para baixo"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Deslocar para cima"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Anterior"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Pesquisar"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Definições"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Menu adicional"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Ativado"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Desativado"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Fechar"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Deslocamento limitado durante a condução"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funcionalidade não disponível durante a condução."</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-pt/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-pt/strings.xml
new file mode 100644
index 0000000..98a3746
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-pt/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Pesquisar…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Rolar para baixo"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Rolar para cima"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Voltar"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Pesquisa"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Configurações"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Menu flutuante"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Ativada"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Desativada"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Fechar"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"O recurso de rolagem fica limitado enquanto você dirige"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Recurso indisponível enquanto você dirige"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ro/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ro/strings.xml
new file mode 100644
index 0000000..3433253
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ro/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Căutați…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Derulați în jos"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Derulați în sus"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Înapoi"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Căutați"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Setări"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Suplimentar"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Activat"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Dezactivat"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Închideți"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Derularea este restricționată în timp ce conduceți"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funcția nu este disponibilă când conduceți"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ru/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000..50c7efd
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ru/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Поиск…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Прокрутить вниз"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Прокрутить вверх"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Назад"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Поиск"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Настройки"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Дополнительное меню"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Включено"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Выключено"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Закрыть"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Функция прокручивания ограничена во время вождения."</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Функция недоступна во время вождения."</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-si/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000..3693869
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-si/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"සොයන්න…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"පහළට අනුචලනය කරන්න"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"ඉහළට අනුචලනය කරන්න"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"ආපසු"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"සෙවීම"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"සැකසීම්"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ඉතිරියනය"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ක්‍රියාත්මකයි"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ක්‍රියාවිරහිතයි"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"වසන්න"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"රිය පදවන අතරතුර සීමිත අනුචලනය"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"රිය පදවන අතරේ විශේෂාංගය නොමැත"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-sk/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000..a9c0565
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-sk/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Vyhľadať…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Posunúť nadol"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Posunúť nahor"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Späť"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Hľadať"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Nastavenia"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Rozšírená ponuka"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Zap."</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Vyp."</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Zavrieť"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Posúvanie zobrazenia je počas jazdy obmedzené"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkcia nie je k dispozícii počas jazdy"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-sl/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000..ac0940f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-sl/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Iskanje …"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Pomik navzdol"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Pomik navzgor"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Nazaj"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Išči"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Nastavitve"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Element menija z dodatnimi elementi"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Vklopljeno"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Izklopljeno"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Zapri"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Pomikanje je med vožnjo omejeno"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funkcija med vožnjo ni na voljo"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-sq/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000..9208197
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-sq/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Kërko…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Lëviz poshtë"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Lëviz lart"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Pas"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Kërko"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Cilësimet"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Tejkalo"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Aktiv"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Joaktiv"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Mbyll"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Lëvizja është e kufizuar gjatë drejtimit të makinës"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Veçoria nuk ofrohet gjatë drejtimit të makinës"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-sr/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000..6a6fb9b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-sr/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Претражите…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Померите надоле"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Померите нагоре"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Назад"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Претражи"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Подешавања"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Преклопни мени"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Укључено"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Искључено"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Затвори"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Померање је ограничено током вожње"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Функција није доступна током вожње"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-sv/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-sv/strings.xml
new file mode 100644
index 0000000..e14b299
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-sv/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Sök …"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Scrolla nedåt"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Scrolla uppåt"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Tillbaka"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Sök"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Inställningar"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Fler menyalternativ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"På"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Av"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Stäng"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Scrollning begränsas när du kör"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Funktionen är inte tillgänglig när du kör"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-sw/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-sw/strings.xml
new file mode 100644
index 0000000..3d6ed8a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-sw/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Tafuta…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Sogeza chini"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Sogeza juu"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Nyuma"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Tafuta"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Mipangilio"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Vipengee vya ziada"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Imewashwa"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Imezimwa"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Funga"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Umedhibitiwa kusogeza unapoendesha gari"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Kipengele hakipatikani unapoendesha gari"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ta/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000..abd4b98
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ta/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"தேடுக…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"கீழே செல்லும்"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"மேலே செல்லும்"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"பின்செல்வதற்கான பட்டன்"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"தேடு"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"அமைப்புகள்"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"ஓவர்ஃப்லோ"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ஆன்"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ஆஃப்"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"மூடுக"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"வாகனம் ஓட்டிக் கொண்டிருப்பதனால் இதற்குமேல் ஸ்க்ரோல் செய்ய முடியாது"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"வாகனம் ஓட்டும்போது இந்த அம்சத்தைப் பயன்படுத்த இயலாது"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-te/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-te/strings.xml
new file mode 100644
index 0000000..e3422b8
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-te/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"వెతకండి…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"కిందికి స్క్రోల్ చేయండి"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"పైకి స్క్రోల్ చేయండి"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"వెనుకకు"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"శోధన"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"సెట్టింగ్‌లు"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"అతివ్యాప్తి అంశాలు"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"ఆన్‌లో ఉంది"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ఆఫ్‌లో ఉంది"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"మూసివేయండి"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"డ్రైవింగ్ చేస్తున్నప్పుడు స్క్రోలింగ్ పరిమితంగా ఉంటుంది"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"డ్రైవింగ్ చేస్తున్నప్పుడు ఈ ఫీచర్ అందుబాటులో ఉండదు"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-th/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000..837ff9c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-th/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"ค้นหา…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"เลื่อนลง"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"เลื่อนขึ้น"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"กลับ"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"ค้นหา"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"การตั้งค่า"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"รายการเพิ่มเติม"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"เปิด"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"ปิด"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"ปิด"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"การเลื่อนถูกจำกัดไม่ให้ใช้งานขณะขับรถ"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ฟีเจอร์ไม่พร้อมใช้งานขณะขับรถ"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-tl/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000..3a8e981
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-tl/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Maghanap…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Mag-scroll pababa"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Mag-scroll pataas"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Bumalik"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Paghahanap"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Mga Setting"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Overflow"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"I-on"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"I-off"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Isara"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Limitado ang pag-scroll habang nagmamaneho"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Hindi available ang feature habang nagmamaneho"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-tr/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000..f9e923f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-tr/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Ara…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Aşağı kaydır"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Yukarı kaydır"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Geri"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Ara"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Ayarlar"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Taşma"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Açık"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Kapalı"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Kapat"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Sürüş sırasında ekran kaydırma işlevi sınırlandırılmıştır"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Sürüş sırasında bu özellik kullanılamaz"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-uk/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000..0ecec7e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-uk/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Пошук…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Прокрутити вниз"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Прокрутити вгору"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Назад"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Пошук"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Налаштування"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Додаткове меню"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Увімкнено"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Вимкнено"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Закрити"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Прокручування обмежено під час водіння"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Функція недоступна під час руху автомобіля"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-ur/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000..23b9033
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-ur/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"تلاش کریں…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"نیچے اسکرول کریں"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"اوپر اسکرول کریں"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"پیچھے"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"تلاش کریں"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"ترتیبات"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"اوورفلو"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"آن ہے"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"آف ہے"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"بند کریں"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"ڈرائیونگ کے دوران اسکرولنگ محدود ہے"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"ڈرائیونگ کے دوران یہ خصوصیت دستیاب نہیں ہے"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-uz/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000..9735f60
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-uz/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Qidirish…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Pastga surish"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Tepaga surish"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Orqaga"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Qidiruv"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Sozlamalar"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Kengaytirilgan"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Yoniq"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Yoqilmagan"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Yopish"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Avtomobilda harakatlanayotganda aylantirish funksiyasi cheklangan"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Avtomobilda harakatlanayotganda bu funksiya ishlamaydi"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-vi/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000..d0ebb04
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-vi/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Tìm kiếm…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Cuộn xuống"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Cuộn lên"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Quay lại"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Tìm kiếm"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Cài đặt"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Trình đơn mục bổ sung"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Đang bật"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Đang tắt"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Đóng"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Tính năng cuộn bị hạn chế khi đang lái xe"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Bạn không sử dụng được tính năng này khi đang lái xe"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-zh-rCN/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..7c5a5b0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"搜索…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"向下滚动"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"向上滚动"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"返回"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"搜索"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"设置"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"溢出菜单"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"开启"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"关闭"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"关闭"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"驾车时滚动操作受限"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"驾车时无法使用此功能"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-zh-rHK/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..2bd14e7
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-zh-rHK/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"搜尋…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"向下捲動"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"向上捲動"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"返回"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"搜尋"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"設定"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"展開式選單"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"已開啟"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"已關閉"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"關閉"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"捲動功能在駕駛時受限制"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"無法在駕駛時使用此功能"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-zh-rTW/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..1fc26f4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"搜尋…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"向下捲動"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"向上捲動"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"返回"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"搜尋"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"設定"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"溢位"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"開啟"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"關閉"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"關閉"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"系統會限制開車時的捲動操作"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"開車時無法使用這項功能"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values-zu/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values-zu/strings.xml
new file mode 100644
index 0000000..8955377
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values-zu/strings.xml
@@ -0,0 +1,31 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="car_ui_toolbar_default_search_hint" msgid="8339474149462104372">"Sesha…"</string>
+    <string name="car_ui_scrollbar_page_down_button" msgid="746830252244551947">"Skrolela phansi"</string>
+    <string name="car_ui_scrollbar_page_up_button" msgid="965431866383176249">"Skrolela phezulu"</string>
+    <string name="car_ui_toolbar_nav_icon_content_description" msgid="6116610935599234725">"Emuva"</string>
+    <string name="car_ui_toolbar_menu_item_search_title" msgid="2988075382498202155">"Sesha"</string>
+    <string name="car_ui_toolbar_menu_item_settings_title" msgid="5206858558664840197">"Izilungiselelo"</string>
+    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="9132512843297732890">"Ukuphuphuma"</string>
+    <string name="car_ui_preference_switch_on" msgid="2091385466752081649">"Vuliwe"</string>
+    <string name="car_ui_preference_switch_off" msgid="511096411523593697">"Valiwe"</string>
+    <string name="car_ui_alert_dialog_default_button" msgid="399078418913970003">"Vala"</string>
+    <string name="car_ui_scrolling_limited_message" msgid="5978003166159186378">"Ukuskrola kukhawulelwe uma ushayela"</string>
+    <string name="car_ui_restricted_while_driving" msgid="7490306547860308268">"Isici asitholakali ngenkathi ushayela"</string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/attrs.xml b/car-ui-lib/car-ui-lib/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..f38522f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/attrs.xml
@@ -0,0 +1,247 @@
+<?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>
+    <!-- Global theme options for CarUi -->
+    <declare-styleable name="CarUi">
+        <!-- When set to true, the window decor will contain an OEM-customizable layout -->
+        <attr name="carUiBaseLayout" format="boolean"/>
+        <!-- When set to true, a CarUi Toolbar will be provided in the window decor -->
+        <attr name="carUiToolbar" format="boolean"/>
+    </declare-styleable>
+
+    <declare-styleable name="CarUiToolbar">
+        <!-- Title of the toolbar, only displayed in certain conditions -->
+        <attr name="title" format="string"/>
+        <!-- Logo drawable for the toolbar. Appears when there's no back/close button shown -->
+        <attr name="logo" format="reference"/>
+        <!-- Hint for the search bar in the toolbar -->
+        <attr name="searchHint" format="string"/>
+        <!-- Whether or not to show the MenuItems while searching. Default false. -->
+        <attr name="showMenuItemsWhileSearching" format="boolean"/>
+        <!-- Initial state of the toolbar. See the Toolbar.State enum for more information -->
+        <attr name="car_ui_state" format="enum">
+            <enum name="home" value="0"/>
+            <enum name="subpage" value="1"/>
+            <enum name="search" value="2"/>
+        </attr>
+        <!-- Whether or not the toolbar should have a background. Default true. -->
+        <attr name="showBackground" format="boolean"/>
+        <!-- Mode of the navigation button See the Toolbar.NavButtonMode enum for more information -->
+        <attr name="car_ui_navButtonMode" format="enum">
+            <enum name="back" value="0"/>
+            <enum name="close" value="1"/>
+            <enum name="down" value="2"/>
+        </attr>
+        <!-- XML resource of MenuItems. See Toolbar.setMenuItems(int) for more information. -->
+        <attr name="menuItems" format="reference"/>
+        <!-- Whether or not to show tabs in the SUBPAGE state. Default false -->
+        <attr name="showTabsInSubpage" format="boolean"/>
+    </declare-styleable>
+
+    <declare-styleable name="CarUiToolbarMenuItem">
+        <!-- Id of MenuItem, used to differentiate them -->
+        <attr name="id" format="reference"/>
+        <!-- Show/hide the MenuItem -->
+        <attr name="visible" format="boolean"/>
+        <!-- Set this to true to make a search MenuItem. This will override every other property except id, visible, and onclick. -->
+        <attr name="search" format="boolean"/>
+        <!-- Set this to true to make a settings MenuItem. This will override every other property except id, visible, and onclick. -->
+        <attr name="settings" format="boolean"/>
+        <!-- Title -->
+        <attr name="title"/>
+        <!-- Icon -->
+        <attr name="icon" format="reference"/>
+        <!-- True to tint the icon to a consistent color. Default true, all the other booleans default to false -->
+        <attr name="tinted" format="boolean"/>
+        <!-- Show both the icon and title at the same time -->
+        <attr name="showIconAndTitle" format="boolean"/>
+        <!-- True if this MenuItem should be a switch -->
+        <attr name="checkable" format="boolean"/>
+        <!-- Whether the switch should be checked or not. Setting this implies checkable=true -->
+        <attr name="checked" format="boolean"/>
+        <!-- True if this MenuItem should be activatable, in which case it will visually toggle states when clicked -->
+        <attr name="activatable" format="boolean"/>
+        <!-- Whether the MenuItem starts activated. Setting this implies activatable=true -->
+        <attr name="activated" format="boolean"/>
+        <!-- How to display the MenuItem. "always" means always show it on the toolbar, "never" means never show it on the toolbar and instead show it in the overflow menu -->
+        <attr name="displayBehavior" format="enum">
+            <enum name="always" value="0"/>
+            <enum name="never" value="1"/>
+        </attr>
+        <!-- Ux restrictions required to interact with this MenuItem -->
+        <attr name="uxRestrictions">
+            <!-- Values are copied from android.car.drivingstate.CarUxRestrictions. Note:
+            UX_RESTRICTIONS_BASELINE is not allowed here because it's useless and confusing. -->
+            <flag name="UX_RESTRICTIONS_NO_DIALPAD" value="1"/>
+            <flag name="UX_RESTRICTIONS_NO_FILTERING" value="2"/>
+            <flag name="UX_RESTRICTIONS_LIMIT_STRING_LENGTH" value="4"/>
+            <flag name="UX_RESTRICTIONS_NO_KEYBOARD" value="8"/>
+            <flag name="UX_RESTRICTIONS_NO_VIDEO" value="16"/>
+            <flag name="UX_RESTRICTIONS_LIMIT_CONTENT" value="32"/>
+            <flag name="UX_RESTRICTIONS_NO_SETUP" value="64"/>
+            <flag name="UX_RESTRICTIONS_NO_TEXT_MESSAGE" value="128"/>
+            <flag name="UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION" value="256"/>
+            <flag name="UX_RESTRICTIONS_FULLY_RESTRICTED" value="511"/>
+        </attr>
+        <!-- The name of a method that takes a MenuItem as an argument in you'r toolbar's Activity. Will be called when the MenuItem is clicked -->
+        <attr name="onClick" format="string"/>
+    </declare-styleable>
+
+    <!-- Theme attribute to specifying a default style for all CarUiToolbars -->
+    <attr name="CarUiToolbarStyle" format="reference"/>
+
+    <declare-styleable name="CarUiRecyclerView">
+        <!-- Whether to enable the dividers or not. Linear and grid layout uses
+        car_ui_recyclerview_divider.xml and car_ui_divider.xml drawables
+        respectively for styling dividers. -->
+        <attr name="enableDivider" format="boolean" />
+        <!-- Top offset for car ui recycler view. -->
+        <attr name="topOffset" format="integer" />
+        <!-- Bottom offset for car ui recycler view for linear layout. -->
+        <attr name="bottomOffset" format="integer" />
+
+        <!-- Number of columns in a grid layout. -->
+        <attr name="numOfColumns" format="integer" />
+
+        <!-- car ui recycler view layout. -->
+        <attr name="layoutStyle" format="enum">
+            <!-- linear layout -->
+            <enum name="linear" value="0" />
+            <!-- grid layout -->
+            <enum name="grid" value="1" />
+        </attr>
+    </declare-styleable>
+
+    <declare-styleable name="CarUiPreference">
+        <!-- Toggle for showing chevron -->
+        <attr name="showChevron" format="boolean" />
+        <!-- Show ripple when disabled preference is clicked -->
+        <attr name="showRippleOnDisabledPreference" format="boolean" />
+    </declare-styleable>
+
+    <declare-styleable name="CarUiTwoActionPreference">
+        <!-- Determines if the secondary action is initially shown -->
+        <attr name="actionShown" format="boolean"/>
+    </declare-styleable>
+
+    <!-- Theme attribute to specify a default style for all CarUiPreferences -->
+    <attr name="carUiPreferenceStyle" format="reference" />
+
+    <!-- Theme attribute to specify a default style for all CarUiRecyclerViews -->
+    <attr name="carUiRecyclerViewStyle" format="reference" />
+
+    <attr name="state_ux_restricted" format="boolean" />
+
+    <!-- Attributes for FocusArea. -->
+    <declare-styleable name="FocusArea">
+        <!-- The ID of the default focus view. The view will be prioritized when searching for a
+             focus target.
+             (1) When the user nudges the rotary controller, it will search for a target FocusArea,
+                 then search for a target view within the target FocusArea, and focus on the target
+                 view. The target view is chosen in the following order:
+                   1. the "android:focusedByDefault" view, if any
+                   2. the "app:defaultFocus" view, if any
+                   3. the first focusable item in a scrollable container, if any
+                   4. previously focused view, if any and the cache is not stale
+                   5. the first focusable view, if any
+                 Note that 4 will be prioritized over 1&2&3 when
+                 car_ui_focus_area_default_focus_overrides_history is false.
+             (2) When it needs to initialize the focus (such as when a window is opened), it will
+                 search for a view in the window and focus on it. The view is chosen in the
+                 following order:
+                   1. the first "android:focusedByDefault" view, if any
+                   2. the first "app:defaultFocus" view, if any
+                   3. the first focusable item in a scrollable container, if any
+                   4. the first focusable view that is not a FocusParkingView, if any
+             If there is only one FocusArea that needs to set default focus, you can use either
+             "app:defaultFocus" or "android:focusedByDefault". If there are more than one, you
+             should use "android:focusedByDefault" in the primary FocusArea, and use
+             "app:defaultFocus" in other FocusAreas. -->
+
+        <attr name="defaultFocus" format="reference"/>
+
+        <!-- The paddings of FocusArea highlight. It does't impact the paddings on its child views,
+             or vice versa. -->
+        <!-- The start padding of the FocusArea highlight. -->
+        <attr name="highlightPaddingStart" format="dimension"/>
+        <!-- The end padding of the FocusArea highlight. -->
+        <attr name="highlightPaddingEnd" format="dimension"/>
+        <!-- The top padding of the FocusArea highlight. -->
+        <attr name="highlightPaddingTop" format="dimension"/>
+        <!-- The bottom padding of the FocusArea highlight. -->
+        <attr name="highlightPaddingBottom" format="dimension"/>
+        <!-- The horizontal padding of the FocusArea highlight. It can be overridden by
+             highlightPaddingStart or highlightPaddingEnd. -->
+        <attr name="highlightPaddingHorizontal" format="dimension"/>
+        <!-- The vertical padding of the FocusArea highlight.  It can be overridden by
+             highlightPaddingTop or highlightPaddingBottom. -->
+        <attr name="highlightPaddingVertical" format="dimension"/>
+
+        <!-- The offset of the FocusArea's bounds. It only affects the perceived bounds for the
+             purposes of finding the nudge target. It doesn't affect the FocusArea's view bounds or
+             highlight bounds. The offset should only be used when FocusAreas are overlapping and
+             nudge interaction is ambiguous. -->
+        <!-- The offset of the FocusArea's start bound. -->
+        <attr name="startBoundOffset" format="dimension"/>
+        <!-- The offset of the FocusArea's end bound. -->
+        <attr name="endBoundOffset" format="dimension"/>
+        <!-- The offset of the FocusArea's top bound. -->
+        <attr name="topBoundOffset" format="dimension"/>
+        <!-- The offset of the FocusArea's bottom bound. -->
+        <attr name="bottomBoundOffset" format="dimension"/>
+        <!-- The offset of the FocusArea's horizontal bounds. It can be overridden by
+             startBoundOffset or endBoundOffset. -->
+        <attr name="horizontalBoundOffset" format="dimension"/>
+        <!-- The offset of the FocusArea's vertical bounds. It can be overridden by topBoundOffset
+             or bottomBoundOffset. -->
+        <attr name="verticalBoundOffset" format="dimension"/>
+
+        <!-- Attributes for nudge shortcut. Usually nudge is used to navigate to another FocusArea,
+             but when a nudge shortcut is specified, it's used to navigate to the given view within
+             the same FocusArea. The 2 attributes must be specified together. -->
+        <!-- The ID of the nudge shortcut view. -->
+        <attr name="nudgeShortcut" format="reference"/>
+        <!-- The direction of the nudge shortcut. -->
+        <attr name="nudgeShortcutDirection">
+            <!-- View.FOCUS_LEFT -->
+            <flag name="left" value="0x11" />
+            <!-- View.FOCUS_RIGHT -->
+            <flag name="right" value="0x42" />
+            <!-- View.FOCUS_UP -->
+            <flag name="up" value="0x21" />
+            <!-- View.FOCUS_DOWN -->
+            <flag name="down" value="0x82" />
+        </attr>
+
+        <!-- Attributes to specify the target FocusArea for a nudge. -->
+        <!-- The ID of the target FocusArea when nudging to the left. -->
+        <attr name="nudgeLeft" format="reference"/>
+        <!-- The ID of the target FocusArea when nudging to the right. -->
+        <attr name="nudgeRight" format="reference"/>
+        <!-- The ID of the target FocusArea when nudging up. -->
+        <attr name="nudgeUp" format="reference"/>
+        <!-- The ID of the target FocusArea when nudging down. -->
+        <attr name="nudgeDown" format="reference"/>
+    </declare-styleable>
+
+    <!-- Attributes for FocusParkingView. -->
+    <declare-styleable name="FocusParkingView">
+        <!-- Whether to restore focus when the frameworks wants to focus the FocusParkingView. When
+             false, the FocusParkingView allows itself to be focused instead. This should be false
+             for the FocusParkingView in an ActivityView. The default value is true. -->
+        <attr name="shouldRestoreFocus" format="boolean"/>
+    </declare-styleable>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/bools.xml b/car-ui-lib/car-ui-lib/src/main/res/values/bools.xml
new file mode 100644
index 0000000..f53ee3f
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/bools.xml
@@ -0,0 +1,69 @@
+<?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>
+    <!-- Toolbar -->
+
+    <!-- Whether tabs should use flex layout or not -->
+    <bool name="car_ui_toolbar_tab_flexible_layout">false</bool>
+    <!-- Whether the space for nav icon should be reserved, even if the nav icon is not visible -->
+    <bool name="car_ui_toolbar_nav_icon_reserve_space">true</bool>
+    <!-- Whether the logo (if provided) should be used in place of the nav icon when nav icon is
+         not visible -->
+    <bool name="car_ui_toolbar_logo_fills_nav_icon_space">true</bool>
+    <!-- Whether logo should be displayed. If set to false, logo won't be shown even if provided -->
+    <bool name="car_ui_toolbar_show_logo">true</bool>
+    <!-- Whether tabs should be displayed on a second row, or they should be placed in the first
+         row, replacing the title -->
+    <bool name="car_ui_toolbar_tabs_on_second_row">false</bool>
+
+    <!-- CarUiRecyclerView -->
+
+    <!-- Whether to display the Scroll Bar or not. Defaults to true. If this is set to false,
+         the CarUiRecyclerView will behave exactly like the RecyclerView. -->
+    <bool name="car_ui_scrollbar_enable">true</bool>
+
+    <!-- Preferences -->
+
+    <!-- Whether list, edit, dropdown and intent preferences should show a chevron or not -->
+    <bool name="car_ui_preference_show_chevron">false</bool>
+    <!-- whether list preference should be shown in full screen or as a dialog -->
+    <bool name="car_ui_preference_list_show_full_screen">true</bool>
+
+    <!-- List items -->
+
+    <bool name="car_ui_list_item_single_line_title">true</bool>
+
+    <!-- FocusArea -->
+
+    <!-- Whether to draw highlight (car_ui_focus_area_foreground_highlight) on top of the FocusArea
+         and its children when the FocusArea's descendant gets focused. -->
+    <bool name="car_ui_enable_focus_area_foreground_highlight">false</bool>
+    <!-- Whether to draw highlight (car_ui_focus_area_background_highlight) on top of the FocusArea
+         but behind its children when the FocusArea's descendant gets focused. -->
+    <bool name="car_ui_enable_focus_area_background_highlight">false</bool>
+    <!-- Whether to focus on the app:defaultFocus view when nudging to the FocusArea, even if there
+         was another view focused in the FocusArea. -->
+    <bool name="car_ui_focus_area_default_focus_overrides_history">true</bool>
+    <!-- Whether to clear FocusArea history when the user rotates the rotary controller. -->
+    <bool name="car_ui_clear_focus_area_history_when_rotating">true</bool>
+
+    <!--  Whether to log the escrow components check automatically for all the activities or not.  -->
+    <bool name="car_ui_escrow_check_components_automatically">false</bool>
+
+    <!-- If there is no positive/negative/neutral button, should we add one that says "dismiss"? -->
+    <bool name="car_ui_alert_dialog_force_dismiss_button">true</bool>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/colors.xml b/car-ui-lib/car-ui-lib/src/main/res/values/colors.xml
new file mode 100644
index 0000000..326dcfb
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/colors.xml
@@ -0,0 +1,55 @@
+<?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>
+    <!-- General -->
+
+    <!-- Background color to use on full screen activities -->
+    <color name="car_ui_activity_background_color">#000000</color>
+    <!-- The ripple color. -->
+    <color name="car_ui_ripple_color">#27ffffff</color>
+
+    <!-- Toolbar -->
+
+    <!-- Color used on the navigation icon -->
+    <color name="car_ui_toolbar_nav_icon_color">@color/car_ui_text_color_primary</color>
+    <!-- Text color applied to the hint displayed inside the search box -->
+    <color name="car_ui_toolbar_search_hint_text_color">@color/car_ui_text_color_hint</color>
+    <!-- Tab selected color -->
+    <color name="car_ui_toolbar_tab_selected_color">@color/car_ui_text_color_primary</color>
+    <!-- Tab normal color -->
+    <color name="car_ui_toolbar_tab_unselected_color">@color/car_ui_text_color_secondary</color>
+
+    <!-- Recycler View  -->
+
+    <!-- Color of the scroll bar indicator in the CarUiRecyclerView. -->
+    <color name="car_ui_scrollbar_thumb">#99ffffff</color>
+    <!-- Color of the divider views between CarUiRecyclerView items -->
+    <color name="car_ui_recyclerview_divider_color">@android:color/transparent</color>
+
+    <!-- Preferences -->
+
+    <color name="car_ui_preference_icon_color">@color/car_ui_text_color_primary</color>
+    <color name="car_ui_preference_two_action_divider_color">#1fffffff</color>
+
+    <!-- Rotary focus -->
+
+    <color name="car_ui_rotary_focus_stroke_color">#94CBFF</color>
+    <color name="car_ui_rotary_focus_fill_color">#3D94CBFF</color>
+    <color name="car_ui_rotary_focus_pressed_stroke_color">#94CBFF</color>
+    <color name="car_ui_rotary_focus_pressed_fill_color">#8A94CBFF</color>
+    <color name="car_ui_rotary_focus_stroke_secondary_color">#0059B3</color>
+    <color name="car_ui_rotary_focus_fill_secondary_color">#3D0059B3</color>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/dimens.xml b/car-ui-lib/car-ui-lib/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..b2eaadc
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/dimens.xml
@@ -0,0 +1,215 @@
+<?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>
+    <!-- General resources -->
+
+    <dimen name="car_ui_touch_target_size">76dp</dimen>
+    <dimen name="car_ui_touch_target_width">@dimen/car_ui_touch_target_size</dimen>
+    <dimen name="car_ui_touch_target_height">@dimen/car_ui_touch_target_size</dimen>
+
+    <dimen name="car_ui_primary_icon_size">44dp</dimen>
+
+    <!-- Horizontal margin between screen content and display border. In reference
+     implementation, this value matches the CarUiRecyclerView scrollbar width -->
+    <dimen name="car_ui_margin">112dp</dimen>
+
+    <!-- Paddings -->
+    <dimen name="car_ui_padding_0">4dp</dimen>
+    <dimen name="car_ui_padding_1">8dp</dimen>
+    <dimen name="car_ui_padding_2">16dp</dimen>
+    <dimen name="car_ui_padding_3">24dp</dimen>
+    <dimen name="car_ui_padding_4">32dp</dimen>
+    <dimen name="car_ui_padding_5">64dp</dimen>
+    <dimen name="car_ui_padding_6">96dp</dimen>
+
+    <!-- Type Sizings -->
+    <dimen name="car_ui_body1_size">32sp</dimen>
+    <dimen name="car_ui_body2_size">28sp</dimen>
+    <dimen name="car_ui_body3_size">24sp</dimen>
+    <dimen name="car_ui_sub1_size">22sp</dimen>
+    <dimen name="car_ui_sub2_size">20sp</dimen>
+    <dimen name="car_ui_sub3_size">18sp</dimen>
+
+    <!-- Tabs -->
+
+    <!-- Exact size of the tab textbox. Use @dimen/wrap_content if this must be flexible -->
+    <dimen name="car_ui_toolbar_tab_text_width">135dp</dimen>
+    <!-- Horizontal padding between tabs -->
+    <dimen name="car_ui_toolbar_tab_padding_x">12dp</dimen>
+    <!-- Tab icon width (if icons are enabled) -->
+    <dimen name="car_ui_toolbar_tab_icon_width">36dp</dimen>
+    <!-- Tab icon height (if icons are enabled) -->
+    <dimen name="car_ui_toolbar_tab_icon_height">36dp</dimen>
+
+    <!-- Toolbar -->
+
+    <!-- Default height for both toolbar rows. See car_ui_toolbar_first_row_height and
+     car_ui_toolbar_second_row_height -->
+    <dimen name="car_ui_toolbar_row_height">96dp</dimen>
+    <!-- Height of the top toolbar row. This can be customized independently. -->
+    <dimen name="car_ui_toolbar_first_row_height">@dimen/car_ui_toolbar_row_height</dimen>
+    <!-- Height of the bottom toolbar row (if the toolbar is used in two-rows mode. -->
+    <dimen name="car_ui_toolbar_second_row_height">@dimen/car_ui_toolbar_row_height</dimen>
+    <!-- Padding on the toolbar start (e.g.: distance between the container start and the start of
+    nav icon or logo) -->
+    <dimen name="car_ui_toolbar_start_inset">0dp</dimen>
+    <!-- End padding (e.g.: distance between the container end and the end of the menu items) -->
+    <dimen name="car_ui_toolbar_end_inset">0dp</dimen>
+    <!-- Top padding -->
+    <dimen name="car_ui_toolbar_top_inset">0dp</dimen>
+    <!-- Bottom padding -->
+    <dimen name="car_ui_toolbar_bottom_inset">0dp</dimen>
+    <!-- Toolbar title/tabs start margin. Toolbar navigation icon (or logo if no navigation icon is
+    used) will be centered in this space, and the title will start from here -->
+    <dimen name="car_ui_toolbar_margin">@dimen/car_ui_margin</dimen>
+    <!-- Navigation icon -->
+    <dimen name="car_ui_toolbar_nav_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+    <!-- Logo -->
+    <dimen name="car_ui_toolbar_logo_size">@dimen/car_ui_primary_icon_size</dimen>
+    <!-- Margin between the logo and the title, when both logo and navigation icons are used -->
+    <dimen name="car_ui_toolbar_title_logo_padding">0dp</dimen>
+    <!-- Margin at the start of the title -->
+    <dimen name="car_ui_toolbar_title_margin_start">@dimen/car_ui_padding_2</dimen>
+    <!-- Margin at the start of the title when there is no logo present -->
+    <dimen name="car_ui_toolbar_title_no_logo_margin_start">0dp</dimen>
+    <!-- Space at the end and in between menu items -->
+    <dimen name="car_ui_toolbar_menu_item_margin">@dimen/car_ui_padding_2</dimen>
+    <!-- Ripple effect radius for icon menu items -->
+    <dimen name="car_ui_toolbar_menu_item_icon_ripple_radius">48dp</dimen>
+    <!-- Icon size for icon menu items -->
+    <dimen name="car_ui_toolbar_menu_item_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+    <!-- Icon background size for icon menu items -->
+    <dimen name="car_ui_toolbar_menu_item_icon_background_size">54dp</dimen>
+    <!-- Height of the decoration view between the two rows of the toolbar (or below the toolbar
+    if this is a single row one -->
+    <!-- can't use 0dp for layout_height or the constraintlayout effect kicks in -->
+    <dimen name="car_ui_toolbar_separator_height">0.1dp</dimen>
+    <!-- Height of the decoration view below the toolbar -->
+    <!-- can't use 0dp for layout_height or the constraintlayout effect kicks in -->
+    <dimen name="car_ui_toolbar_bottom_view_height">0.1dp</dimen>
+    <!-- Height of the search box -->
+    <dimen name="car_ui_toolbar_search_height">0dp</dimen>
+    <!-- Space before the text search area, where the search icon is located -->
+    <dimen name="car_ui_toolbar_search_search_icon_container_width">@dimen/car_ui_touch_target_width</dimen>
+    <!-- Space after the text search area, where the cancel icon is located -->
+    <dimen name="car_ui_toolbar_search_close_icon_container_width">@dimen/car_ui_touch_target_width</dimen>
+    <!-- Size of the search icon inside the search box -->
+    <dimen name="car_ui_toolbar_search_search_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+    <!-- Size of the close icon inside the search box -->
+    <dimen name="car_ui_toolbar_search_close_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+
+    <!-- Internal artifacts. Do not overlay -->
+    <item name="wrap_content" format="integer" type="dimen">-2</item>
+
+    <!-- CarUiRecyclerView -->
+
+    <dimen name="car_ui_recyclerview_divider_height">0dp</dimen>
+    <dimen name="car_ui_recyclerview_divider_start_margin">0dp</dimen>
+    <dimen name="car_ui_recyclerview_divider_end_margin">0dp</dimen>
+    <dimen name="car_ui_recyclerview_divider_top_margin">0dp</dimen>
+    <dimen name="car_ui_recyclerview_divider_bottom_margin">0dp</dimen>
+
+    <!-- CarUiRecyclerView default scrollbar -->
+
+    <dimen name="car_ui_scrollbar_container_width">@dimen/car_ui_margin</dimen>
+    <dimen name="car_ui_scrollbar_button_size">@dimen/car_ui_touch_target_width</dimen>
+    <dimen name="car_ui_scrollbar_thumb_width">7dp</dimen>
+    <dimen name="car_ui_scrollbar_min_thumb_height">56dp</dimen>
+    <dimen name="car_ui_scrollbar_separator_margin">16dp</dimen>
+    <dimen name="car_ui_scrollbar_margin">@dimen/car_ui_margin</dimen>
+    <dimen name="car_ui_scrollbar_thumb_radius">100dp</dimen>
+
+    <item name="car_ui_button_disabled_alpha" format="float" type="dimen">0.2</item>
+    <item name="car_ui_scrollbar_milliseconds_per_inch" format="float" type="dimen">150.0</item>
+    <item name="car_ui_scrollbar_deceleration_times_divisor" format="float" type="dimen">0.45</item>
+    <item name="car_ui_scrollbar_decelerate_interpolator_factor" format="float" type="dimen">1.8</item>
+
+    <dimen name="car_ui_scrollbar_padding_top">0dp</dimen>
+    <dimen name="car_ui_scrollbar_padding_bottom">0dp</dimen>
+
+    <!-- Preferences -->
+
+    <dimen name="car_ui_divider_width">1dp</dimen>
+
+    <dimen name="car_ui_preference_content_margin_top">16dp</dimen>
+    <dimen name="car_ui_preference_content_margin_bottom">16dp</dimen>
+    <dimen name="car_ui_preference_icon_size">44dp</dimen>
+    <dimen name="car_ui_preference_icon_margin_end">16dp</dimen>
+
+    <dimen name="car_ui_preference_category_min_height">76dp</dimen>
+    <dimen name="car_ui_preference_category_icon_size">44dp</dimen>
+    <dimen name="car_ui_preference_category_icon_margin_end">16dp</dimen>
+
+    <dimen name="car_ui_preference_dropdown_padding_start">112dp</dimen>
+
+    <dimen name="car_ui_preference_edit_text_dialog_margin_top">32dp</dimen>
+    <dimen name="car_ui_preference_edit_text_dialog_margin_bottom">32dp</dimen>
+    <dimen name="car_ui_preference_edit_text_dialog_message_margin_bottom">32dp</dimen>
+    <dimen name="car_ui_preference_edit_text_dialog_message_margin_start">24dp</dimen>
+    <dimen name="car_ui_preference_edit_text_dialog_message_margin_end">24dp</dimen>
+    <dimen name="car_ui_preference_edit_text_dialog_text_margin_start">24dp</dimen>
+    <dimen name="car_ui_preference_edit_text_dialog_text_margin_end">24dp</dimen>
+
+    <!-- Alert dialog   -->
+
+    <dimen name="car_ui_dialog_edittext_height">50dp</dimen>
+    <dimen name="car_ui_dialog_edittext_margin_top">10dp</dimen>
+    <dimen name="car_ui_dialog_edittext_margin_bottom">10dp</dimen>
+    <dimen name="car_ui_dialog_edittext_margin_start">22dp</dimen>
+    <dimen name="car_ui_dialog_edittext_margin_end">22dp</dimen>
+    <dimen name="car_ui_dialog_icon_size">56dp</dimen>
+    <dimen name="car_ui_dialog_title_margin">24dp</dimen>
+
+    <!-- List item  -->
+
+    <dimen name="car_ui_list_item_height">116dp</dimen>
+    <dimen name="car_ui_list_item_header_height">76dp</dimen>
+    <dimen name="car_ui_list_item_header_start_inset">0dp</dimen>
+    <dimen name="car_ui_list_item_start_inset">0dp</dimen>
+    <dimen name="car_ui_list_item_end_inset">0dp</dimen>
+    <dimen name="car_ui_header_list_item_text_start_margin">0dp</dimen>
+    <dimen name="car_ui_list_item_text_start_margin">24dp</dimen>
+    <dimen name="car_ui_list_item_text_no_icon_start_margin">24dp</dimen>
+
+    <!-- List item icons  -->
+
+    <dimen name="car_ui_list_item_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+    <dimen name="car_ui_list_item_content_icon_width">@dimen/car_ui_list_item_icon_container_width</dimen>
+    <dimen name="car_ui_list_item_content_icon_height">@dimen/car_ui_list_item_icon_container_width</dimen>
+    <dimen name="car_ui_list_item_avatar_icon_width">@dimen/car_ui_primary_icon_size</dimen>
+    <dimen name="car_ui_list_item_avatar_icon_height">@dimen/car_ui_primary_icon_size</dimen>
+    <dimen name="car_ui_list_item_supplemental_icon_size">@dimen/car_ui_primary_icon_size</dimen>
+    <dimen name="car_ui_list_item_icon_container_width">112dp</dimen>
+    <dimen name="car_ui_list_item_action_divider_width">1dp</dimen>
+    <dimen name="car_ui_list_item_action_divider_height">60dp</dimen>
+
+    <!-- List item actions  -->
+
+    <dimen name="car_ui_list_item_radio_button_height">@dimen/car_ui_list_item_height</dimen>
+    <dimen name="car_ui_list_item_radio_button_start_inset">@dimen/car_ui_list_item_start_inset</dimen>
+    <dimen name="car_ui_list_item_radio_button_end_inset">@dimen/car_ui_list_item_end_inset</dimen>
+    <dimen name="car_ui_list_item_radio_button_icon_container_width">@dimen/car_ui_list_item_icon_container_width</dimen>
+    <dimen name="car_ui_list_item_check_box_height">@dimen/car_ui_list_item_height</dimen>
+    <dimen name="car_ui_list_item_check_box_start_inset">@dimen/car_ui_list_item_start_inset</dimen>
+    <dimen name="car_ui_list_item_check_box_end_inset">@dimen/car_ui_list_item_end_inset</dimen>
+    <dimen name="car_ui_list_item_check_box_icon_container_width">@dimen/car_ui_list_item_icon_container_width</dimen>
+
+    <!-- Rotary focus highlight  -->
+
+    <dimen name="car_ui_rotary_focus_stroke_width">8dp</dimen>
+    <dimen name="car_ui_rotary_focus_pressed_stroke_width">4dp</dimen>
+
+</resources>
diff --git a/car-ui-lib/res/values/drawables.xml b/car-ui-lib/car-ui-lib/src/main/res/values/drawables.xml
similarity index 100%
rename from car-ui-lib/res/values/drawables.xml
rename to car-ui-lib/car-ui-lib/src/main/res/values/drawables.xml
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/ids.xml b/car-ui-lib/car-ui-lib/src/main/res/values/ids.xml
new file mode 100644
index 0000000..3f0c9b1
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/ids.xml
@@ -0,0 +1,22 @@
+<?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>
+    <!-- Id used for the search button when using Toolbar.createSearch() method -->
+    <item name="search" type="id"/>
+
+    <!-- Id used for in car_ui_toolbar_menu_item.xml -->
+    <item name="car_ui_toolbar_menu_item_text_container" type="id"/>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/integers.xml b/car-ui-lib/car-ui-lib/src/main/res/values/integers.xml
new file mode 100644
index 0000000..976a634
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/integers.xml
@@ -0,0 +1,37 @@
+<?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>
+    <!-- Default max string length -->
+    <integer name="car_ui_default_max_string_length">120</integer>
+    <integer name="car_ui_scrollbar_longpress_initial_delay">1000</integer>
+    <integer name="car_ui_scrollbar_longpress_repeat_interval">100</integer>
+
+    <!-- Type of FocusHistoryCache. The values are defined in RotaryCache. 1 means the cache
+    is disabled, 2 means entries in the cache will expire after a period of time, and 3 means
+    elements in the cache will never expire. -->
+    <integer name="car_ui_focus_history_cache_type">2</integer>
+    <!-- How many milliseconds before the entry in FocusHistoryCache expires. Must be positive value
+     when car_ui_focus_history_cache_type is 2. -->
+    <integer name="car_ui_focus_history_expiration_period_ms">300000</integer>
+
+    <!-- Type of FocusAreaHistoryCache. The values are defined in RotaryCache. 1 means the
+    cache is disabled, 2 means entries in the cache will expire after a period of time, and 3 means
+    elements in the cache will never expire. -->
+    <integer name="car_ui_focus_area_history_cache_type">2</integer>
+    <!-- How many milliseconds before an entry in FocusAreaHistoryCache expires. Must be positive
+    value when car_ui_focus_area_history_cache_type is 2. -->
+    <integer name="car_ui_focus_area_history_expiration_period_ms">3000</integer>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/strings.xml b/car-ui-lib/car-ui-lib/src/main/res/values/strings.xml
new file mode 100644
index 0000000..46a29fe
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/strings.xml
@@ -0,0 +1,64 @@
+<?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>
+    <!--
+    Configuration for a default scrollbar for the CarUiRecyclerView. This component must inherit
+    abstract class ScrollBar. If the ScrollBar is enabled, the component will be initialized from
+    CarUiRecyclerView#createScrollBarFromConfig(). If no component is provided,
+    {@link DefaultScrollbar} class will be used.
+    -->
+    <string name="car_ui_scrollbar_component" translatable="false"/>
+    <!-- Search hint, displayed inside the search box [CHAR LIMIT=50] -->
+    <string name="car_ui_toolbar_default_search_hint">Search&#8230;</string>
+    <!-- CarUxRestrictions Utility -->
+    <string name="car_ui_ellipsis" translatable="false">&#8230;</string>
+    <!-- Content description for car ui recycler view scroll bar down arrow [CHAR LIMIT=30] -->
+    <string name="car_ui_scrollbar_page_down_button">Scroll down</string>
+    <!-- Content description for car ui recycler view scroll bar up arrow [CHAR LIMIT=30] -->
+    <string name="car_ui_scrollbar_page_up_button">Scroll up</string>
+    <!-- The content description on the toolbar back button -->
+    <string name="car_ui_toolbar_nav_icon_content_description">Back</string>
+    <!-- Title of the search menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
+    <string name="car_ui_toolbar_menu_item_search_title">Search</string>
+    <!-- Title of the settings menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
+    <string name="car_ui_toolbar_menu_item_settings_title">Settings</string>
+    <!-- Title of the overflow menu item. Only used for content descriptions. [CHAR_LIMIT=50] -->
+    <string name="car_ui_toolbar_menu_item_overflow_title">Overflow</string>
+
+    <!-- Positive option for a preference dialog. [CHAR_LIMIT=30] -->
+    <string name="car_ui_dialog_preference_positive" translatable="false">@android:string/ok</string>
+    <!-- Negative option for a preference dialog. [CHAR_LIMIT=30] -->
+    <string name="car_ui_dialog_preference_negative" translatable="false">@android:string/cancel</string>
+    <!-- Text to show when a preference switch is on. [CHAR_LIMIT=30] -->
+    <string name="car_ui_preference_switch_on">On</string>
+    <!-- Text to show when a preference switch is off. [CHAR_LIMIT=30] -->
+    <string name="car_ui_preference_switch_off">Off</string>
+
+    <!-- Text to show when no button is provided and a default button is used. -->
+    <string name="car_ui_alert_dialog_default_button">Close</string>
+
+    <!-- Shown at the bottom of a content limited list when user has scrolled past the limit while driving -->
+    <string name="car_ui_scrolling_limited_message">Scrolling limited while driving</string>
+
+    <!-- Shown in a toast when the user attempts to do something distracting while driving [CHAR_LIMIT=200] -->
+    <string name="car_ui_restricted_while_driving">Feature not available while driving</string>
+
+    <!-- Mostly used for GMSCore, this attribute is used to launch CarUiInstaller in a process -->
+    <!-- that can register to Application.ActivityLifecycleCallbacks. -->
+    <!-- Clients should override this value instead of changing the process name -->
+    <!-- from manifest file. -->
+    <string name="car_ui_installer_process_name" translatable="false"></string>
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/styles.xml b/car-ui-lib/car-ui-lib/src/main/res/values/styles.xml
new file mode 100644
index 0000000..00cb56e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/styles.xml
@@ -0,0 +1,324 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- Styles for CarUi tab view -->
+
+    <style name="Widget.CarUi" parent="android:Widget.DeviceDefault"/>
+
+    <style name="Widget.CarUi.Button.Borderless.Colored"
+           parent="android:Widget.DeviceDefault.Button.Borderless.Colored"/>
+
+    <style name="Widget.CarUi.Button" parent="android:Widget.DeviceDefault.Button"/>
+
+    <style name="Widget.CarUi.Toolbar"/>
+
+    <style name="Widget.CarUi.SeekbarPreference"/>
+
+    <style name="Widget.CarUi.Toolbar.Container"/>
+
+    <style name="Widget.CarUi.Toolbar.NavIconContainer"/>
+
+    <style name="Widget.CarUi.Toolbar.Logo"/>
+
+    <style name="Widget.CarUi.Toolbar.LogoContainer">
+        <item name="android:paddingEnd">@dimen/car_ui_toolbar_title_logo_padding</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.ProgressBar"
+           parent="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal">
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.NavIcon">
+        <item name="android:tint">@color/car_ui_toolbar_nav_icon_color</item>
+        <item name="android:src">@drawable/car_ui_icon_arrow_back</item>
+        <item name="android:background">@drawable/car_ui_toolbar_menu_item_icon_ripple</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.Title">
+        <item name="android:textAppearance">@style/TextAppearance.CarUi.Widget.Toolbar.Title</item>
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.Subtitle">
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.TextButton" parent="Widget.CarUi.Button.Borderless.Colored">
+        <item name="android:drawableTint">@color/car_ui_toolbar_menu_item_icon_color</item>
+        <item name="android:drawablePadding">10dp</item>
+        <item name="android:maxWidth">350dp</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.TextButton.WithIcon">
+        <item name="android:textColor">@color/car_ui_toolbar_menu_item_icon_color</item>
+    </style>
+
+    <!-- Style applied to the seekbar widget within the seekbar preference -->
+    <style name="Widget.CarUi.SeekbarPreference.Seekbar">
+        <item name="android:background">@null</item>
+        <item name="android:clickable">false</item>
+        <item name="android:focusable">false</item>
+    </style>
+
+    <!-- Style applied to the decoration view between toolbar rows -->
+    <style name="Widget.CarUi.Toolbar.SeparatorView">
+        <item name="android:height">0.01dp</item>
+        <item name="android:background">@android:color/transparent</item>
+    </style>
+
+    <!-- Style applied to the decoration view below the toolbar -->
+    <style name="Widget.CarUi.Toolbar.BottomView">
+        <item name="android:height">0.01dp</item>
+        <item name="android:background">@android:color/transparent</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.MenuItem"/>
+
+    <style name="Widget.CarUi.Toolbar.MenuItem.Container">
+        <item name="android:divider">@drawable/car_ui_toolbar_menu_item_divider</item>
+        <item name="android:showDividers">beginning|middle|end</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.MenuItem.IndividualContainer">
+        <item name="android:minHeight">@dimen/car_ui_touch_target_height</item>
+        <item name="android:minWidth">@dimen/car_ui_touch_target_width</item>
+        <item name="android:layout_gravity">center_vertical</item>
+    </style>
+
+    <!-- Style applied to the edit box inside the toolbar search area -->
+    <style name="Widget.CarUi.Toolbar.Search.EditText"
+        parent="android:Widget.DeviceDefault.EditText"/>
+
+    <style name="Widget.CarUi.Toolbar.Search.SearchIcon" parent="Widget.CarUi.Toolbar"/>
+
+    <style name="Widget.CarUi.Toolbar.Search.CloseIcon" parent="Widget.CarUi.Toolbar">
+        <item name="android:background">@drawable/car_ui_toolbar_menu_item_icon_ripple</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.Tab"/>
+
+    <style name="Widget.CarUi.Toolbar.Tab.Container">
+        <item name="android:orientation">vertical</item>
+        <item name="android:paddingStart">@dimen/car_ui_toolbar_tab_padding_x</item>
+        <item name="android:paddingEnd">@dimen/car_ui_toolbar_tab_padding_x</item>
+        <item name="android:gravity">center</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.Tab.Icon">
+        <item name="android:scaleType">fitCenter</item>
+        <item name="android:tint">@color/car_ui_toolbar_tab_item_selector</item>
+        <item name="android:tintMode">src_in</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.Tab.Text">
+        <item name="android:singleLine">true</item>
+        <item name="android:gravity">center</item>
+        <item name="android:textAppearance">@style/TextAppearance.CarUi.Widget.Toolbar.Tab</item>
+    </style>
+
+    <style name="Widget.CarUi.CarUiRecyclerView">
+        <item name="android:scrollbars">vertical</item>
+    </style>
+
+    <style name="Widget.CarUi.AlertDialog"/>
+
+    <style name="Widget.CarUi.AlertDialog.HeaderContainer">
+        <item name="android:orientation">horizontal</item>
+        <item name="android:gravity">center_vertical|start</item>
+        <item name="android:paddingTop">18dp</item>
+        <item name="android:paddingBottom">18dp</item>
+    </style>
+
+    <style name="Widget.CarUi.AlertDialog.TitleContainer">
+        <item name="android:layout_marginStart">@dimen/car_ui_dialog_title_margin</item>
+        <item name="android:layout_marginEnd">@dimen/car_ui_dialog_title_margin</item>
+        <item name="android:orientation">vertical</item>
+    </style>
+
+    <style name="Widget.CarUi.AlertDialog.Icon">
+        <item name="android:layout_marginStart">@dimen/car_ui_dialog_title_margin</item>
+        <item name="android:scaleType">fitCenter</item>
+    </style>
+
+    <!-- Preference Styles -->
+
+    <style name="Preference.CarUi">
+        <item name="allowDividerBelow">false</item>
+        <item name="allowDividerAbove">false</item>
+        <item name="android:layout">@layout/car_ui_preference</item>
+    </style>
+
+    <style name="Preference.CarUi.Category">
+        <item name="android:layout">@layout/car_ui_preference_category</item>
+        <!-- The title should not dim if the category is disabled, instead only the preference children should dim. -->
+        <item name="android:shouldDisableView">false</item>
+        <item name="android:selectable">false</item>
+    </style>
+
+    <style name="Preference.CarUi.CheckBoxPreference">
+        <item name="android:widgetLayout">@layout/car_ui_preference_widget_checkbox</item>
+    </style>
+
+    <style name="Preference.CarUi.DialogPreference">
+        <item name="android:positiveButtonText">@string/car_ui_dialog_preference_positive</item>
+        <item name="android:negativeButtonText">@string/car_ui_dialog_preference_negative</item>
+    </style>
+
+    <style name="Preference.CarUi.DialogPreference.EditTextPreference">
+        <item name="android:dialogLayout">@layout/car_ui_preference_dialog_edittext</item>
+    </style>
+
+    <style name="Preference.CarUi.Divider">
+        <item name="android:background">@color/car_ui_preference_two_action_divider_color</item>
+    </style>
+
+    <style name="Preference.CarUi.DropDown">
+        <item name="android:layout">@layout/car_ui_preference_dropdown</item>
+    </style>
+
+    <style name="Preference.CarUi.Icon"/>
+
+    <style name="Preference.CarUi.Information">
+        <item name="android:enabled">false</item>
+        <item name="android:shouldDisableView">false</item>
+    </style>
+
+    <style name="Preference.CarUi.Preference"/>
+
+    <style name="Preference.CarUi.PreferenceScreen"/>
+
+    <style name="Preference.CarUi.SeekBarPreference">
+        <item name="android:layout">@layout/car_ui_preference_widget_seekbar</item>
+        <item name="adjustable">true</item>
+        <item name="showSeekBarValue">false</item>
+    </style>
+
+    <style name="Preference.CarUi.DialogSeekBarPreference"/>
+
+    <style name="Preference.CarUi.DialogSeekBarPreference.Seekbar"/>
+
+    <style name="Preference.CarUi.DialogSeekBarPreference.TopText"/>
+    <style name="Preference.CarUi.DialogSeekBarPreference.RightText"/>
+    <style name="Preference.CarUi.DialogSeekBarPreference.LeftText"/>
+
+    <style name="Preference.CarUi.SwitchPreference">
+        <item name="android:widgetLayout">@layout/car_ui_preference_widget_switch</item>
+        <item name="android:switchTextOn">@string/car_ui_preference_switch_on</item>
+        <item name="android:switchTextOff">@string/car_ui_preference_switch_off</item>
+    </style>
+
+    <style name="PreferenceFragment.CarUi">
+        <item name="android:divider">?android:attr/listDivider</item>
+        <!-- TODO(b/150230923) change this to car_ui_preference_fragment -->
+        <item name="android:layout">@layout/car_ui_preference_fragment_with_toolbar</item>
+    </style>
+
+    <!-- TODO(b/150230923) remove this when other apps are ready -->
+    <style name="PreferenceFragment.CarUi.WithToolbar">
+        <item name="android:layout">@layout/car_ui_preference_fragment</item>
+    </style>
+
+    <style name="PreferenceFragmentList.CarUi">
+        <item name="android:paddingTop">0dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:paddingLeft">0dp</item>
+        <item name="android:paddingStart">0dp</item>
+        <item name="android:paddingRight">0dp</item>
+        <item name="android:paddingEnd">0dp</item>
+    </style>
+
+    <!-- TextAppearance -->
+
+    <style name="TextAppearance.CarUi" parent="android:TextAppearance.DeviceDefault">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Body1">
+        <item name="android:textSize">@dimen/car_ui_body1_size</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Body2">
+        <item name="android:textSize">@dimen/car_ui_body2_size</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Body3">
+        <item name="android:textSize">@dimen/car_ui_body3_size</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Sub1">
+        <item name="android:textSize">@dimen/car_ui_sub1_size</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Sub2">
+        <item name="android:textSize">@dimen/car_ui_sub2_size</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Sub3">
+        <item name="android:textSize">@dimen/car_ui_sub3_size</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.PreferenceCategoryTitle" parent="TextAppearance.CarUi.Body3">
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:textColor">@color/car_ui_color_accent</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.PreferenceSummary" parent="TextAppearance.CarUi.Body3">
+        <item name="android:textColor">@color/car_ui_text_color_secondary</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.PreferenceTitle" parent="TextAppearance.CarUi.Body1"/>
+
+    <style name="TextAppearance.CarUi.PreferenceEditTextDialogMessage" parent="TextAppearance.CarUi.Body3"/>
+
+    <style name="TextAppearance.CarUi.AlertDialog.Title" parent="TextAppearance.CarUi.Body3"/>
+    <style name="TextAppearance.CarUi.AlertDialog.Subtitle" parent="TextAppearance.CarUi.Sub3"/>
+
+    <style name="TextAppearance.CarUi.Widget" parent="android:TextAppearance.DeviceDefault.Widget">
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar"/>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar.Title" parent="TextAppearance.CarUi.Body1">
+        <item name="android:singleLine">true</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar.Tab" parent="TextAppearance.CarUi.Body3">
+        <item name="android:textColor">@color/car_ui_toolbar_tab_item_selector</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textFontWeight">400</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar.Tab.Selected">
+        <item name="android:textFontWeight">500</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.ListItem.Header" parent="TextAppearance.CarUi.Body3">
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:textColor">@color/car_ui_color_accent</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.ListItem" parent="TextAppearance.CarUi.Body1"/>
+
+    <style name="TextAppearance.CarUi.ListItem.Body" parent="TextAppearance.CarUi.Body3">
+        <item name="android:textColor">@color/car_ui_text_color_secondary</item>
+    </style>
+
+</resources>
diff --git a/car-ui-lib/car-ui-lib/src/main/res/values/themes.xml b/car-ui-lib/car-ui-lib/src/main/res/values/themes.xml
new file mode 100644
index 0000000..a599fa0
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res/values/themes.xml
@@ -0,0 +1,246 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- TODO: for internal TODOs, expand theme/style to leaf resources as necessary -->
+    <style name="Theme.CarUi" parent="@android:style/Theme.DeviceDefault.NoActionBar">
+        <!-- TODO(b/150230923) change to true when other apps are ready -->
+        <item name="carUiBaseLayout">false</item>
+        <item name="carUiToolbar">false</item>
+
+        <!-- Attributes from: Base.V7.Theme.AppCompat -->
+
+        <item name="windowNoTitle">true</item>
+        <item name="windowActionBar">false</item>
+        <item name="windowActionBarOverlay">false</item>
+        <item name="windowActionModeOverlay">false</item>
+        <item name="actionBarPopupTheme">@null</item>
+
+        <item name="colorBackgroundFloating">?android:attr/colorBackgroundFloating</item>
+
+        <!-- Used by MediaRouter -->
+        <item name="isLightTheme">false</item>
+
+        <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
+        <item name="selectableItemBackgroundBorderless">?android:attr/selectableItemBackgroundBorderless</item>
+        <item name="borderlessButtonStyle">?android:attr/borderlessButtonStyle</item>
+        <item name="homeAsUpIndicator">?android:attr/homeAsUpIndicator</item>
+
+        <item name="dividerVertical">?android:attr/dividerVertical</item>
+        <item name="dividerHorizontal">?android:attr/dividerHorizontal</item>
+
+        <!-- Action Bar Styles -->
+        <item name="actionBarTabStyle">?android:attr/actionBarTabStyle</item>
+        <item name="actionBarTabBarStyle">?android:attr/actionBarTabBarStyle</item>
+        <item name="actionBarTabTextStyle">?android:attr/actionBarTabTextStyle</item>
+        <item name="actionButtonStyle">?android:attr/actionButtonStyle</item>
+        <item name="actionOverflowButtonStyle">?android:attr/actionOverflowButtonStyle</item>
+        <item name="actionOverflowMenuStyle">?android:attr/actionOverflowMenuStyle</item>
+        <item name="actionBarStyle">?android:attr/actionBarStyle</item>
+        <item name="actionBarSplitStyle">?android:attr/actionBarSplitStyle</item>
+        <item name="actionBarWidgetTheme">?android:attr/actionBarWidgetTheme</item>
+        <item name="actionBarTheme">?android:attr/actionBarTheme</item>
+        <item name="actionBarSize">?android:attr/actionBarSize</item>
+        <item name="actionBarDivider">?android:attr/actionBarDivider</item>
+        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
+        <item name="actionMenuTextAppearance">?android:attr/actionMenuTextAppearance</item>
+        <item name="actionMenuTextColor">?android:attr/actionMenuTextColor</item>
+
+        <!-- Dropdown Spinner Attributes -->
+        <item name="actionDropDownStyle">?android:attr/actionDropDownStyle</item>
+
+        <!-- Action Mode -->
+        <item name="actionModeStyle">?android:attr/actionModeStyle</item>
+        <item name="actionModeBackground">?android:attr/actionModeBackground</item>
+        <item name="actionModeSplitBackground">?android:attr/actionModeSplitBackground</item>
+        <item name="actionModeCloseDrawable">?android:attr/actionModeCloseDrawable</item>
+        <item name="actionModeCloseButtonStyle">?android:attr/actionModeCloseButtonStyle</item>
+
+        <item name="actionModeCutDrawable">?android:attr/actionModeCutDrawable</item>
+        <item name="actionModeCopyDrawable">?android:attr/actionModeCopyDrawable</item>
+        <item name="actionModePasteDrawable">?android:attr/actionModePasteDrawable</item>
+        <item name="actionModeSelectAllDrawable">?android:attr/actionModeSelectAllDrawable</item>
+        <item name="actionModeShareDrawable">?android:attr/actionModeShareDrawable</item>
+
+        <!-- Panel attributes -->
+        <!-- TODO: panelMenuListWidth -->
+        <item name="panelMenuListWidth">@dimen/abc_panel_menu_list_width</item>
+        <!-- TODO: panelMenuListTheme -->
+        <item name="panelMenuListTheme">@style/Theme.AppCompat.CompactMenu</item>
+        <item name="panelBackground">?android:attr/panelBackground</item>
+        <item name="listChoiceBackgroundIndicator">?android:attr/listChoiceBackgroundIndicator</item>
+
+        <!-- List attributes -->
+        <item name="textAppearanceListItem">?android:attr/textAppearanceListItem</item>
+        <item name="textAppearanceListItemSmall">?android:attr/textAppearanceListItemSmall</item>
+        <item name="textAppearanceListItemSecondary">?android:attr/textAppearanceListItemSecondary</item>
+        <item name="listPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
+        <item name="listPreferredItemHeightSmall">?android:attr/listPreferredItemHeightSmall</item>
+        <item name="listPreferredItemHeightLarge">?android:attr/listPreferredItemHeightLarge</item>
+        <item name="listPreferredItemPaddingLeft">?android:attr/listPreferredItemPaddingLeft</item>
+        <item name="listPreferredItemPaddingRight">?android:attr/listPreferredItemPaddingRight</item>
+
+        <!-- Spinner styles -->
+        <item name="spinnerStyle">?android:attr/spinnerStyle</item>
+
+        <!-- Required for use of support_simple_spinner_dropdown_item.xml -->
+        <item name="spinnerDropDownItemStyle">?android:attr/spinnerDropDownItemStyle</item>
+        <item name="dropdownListPreferredItemHeight">?attr/listPreferredItemHeightSmall</item>
+
+        <!-- Popup Menu styles -->
+        <item name="popupMenuStyle">?android:attr/popupMenuStyle</item>
+        <item name="textAppearanceLargePopupMenu">?android:attr/textAppearanceLargePopupMenu</item>
+        <item name="textAppearanceSmallPopupMenu">?android:attr/textAppearanceSmallPopupMenu</item>
+        <item name="textAppearancePopupMenuHeader">?android:attr/textAppearancePopupMenuHeader</item>
+        <item name="listPopupWindowStyle">?android:attr/listPopupWindowStyle</item>
+        <item name="dropDownListViewStyle">?android:attr/dropDownListViewStyle</item>
+        <item name="listMenuViewStyle">?android:attr/listMenuViewStyle</item>
+
+        <!-- SearchView attributes -->
+        <item name="searchViewStyle">?android:attr/searchViewStyle</item>
+        <!-- TODO: textColorSearchUrl -->
+        <item name="textColorSearchUrl">@color/abc_search_url_text</item>
+        <item name="textAppearanceSearchResultTitle">?android:attr/textAppearanceSearchResultTitle</item>
+        <item name="textAppearanceSearchResultSubtitle">?android:attr/textAppearanceSearchResultSubtitle</item>
+
+        <!-- ShareActionProvider attributes -->
+        <!-- TODO: activityChooserViewStyle -->
+        <item name="activityChooserViewStyle">@style/Widget.AppCompat.ActivityChooserView</item>
+
+        <!-- Toolbar styles -->
+        <item name="toolbarStyle">?android:attr/toolbarStyle</item>
+        <!-- TODO: toolbarNavigationButtonStyle -->
+        <item name="toolbarNavigationButtonStyle">@style/Widget.AppCompat.Toolbar.Button.Navigation</item>
+
+        <item name="editTextStyle">?android:attr/editTextStyle</item>
+        <item name="editTextBackground">?android:attr/editTextBackground</item>
+        <item name="editTextColor">?android:attr/editTextColor</item>
+        <item name="autoCompleteTextViewStyle">?android:attr/autoCompleteTextViewStyle</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimaryDark">?android:attr/colorPrimaryDark</item>
+        <item name="colorPrimary">?android:attr/colorPrimary</item>
+        <item name="colorAccent">?android:attr/colorAccent</item>
+
+        <item name="colorControlNormal">?android:attr/colorControlNormal</item>
+        <item name="colorControlActivated">?android:attr/colorControlActivated</item>
+        <item name="colorControlHighlight">?android:attr/colorControlHighlight</item>
+        <item name="colorButtonNormal">?android:attr/colorButtonNormal</item>
+        <!-- TODO: colorSwitchThumbNormal -->
+        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
+        <item name="controlBackground">?attr/selectableItemBackgroundBorderless</item>
+
+        <!-- TODO: drawerArrowStyle -->
+        <item name="drawerArrowStyle">@style/Widget.AppCompat.DrawerArrowToggle</item>
+
+        <item name="checkboxStyle">?android:attr/checkboxStyle</item>
+        <item name="radioButtonStyle">?android:attr/radioButtonStyle</item>
+        <item name="switchStyle">?android:attr/switchStyle</item>
+
+        <item name="ratingBarStyle">?android:attr/ratingBarStyle</item>
+        <item name="ratingBarStyleIndicator">?android:attr/ratingBarStyleIndicator</item>
+        <item name="ratingBarStyleSmall">?android:attr/ratingBarStyleSmall</item>
+        <item name="seekBarStyle">?android:attr/seekBarStyle</item>
+
+        <!-- Button styles -->
+        <item name="android:buttonStyle">@style/Widget.CarUi.Button</item>
+        <item name="buttonStyle">?android:attr/buttonStyle</item>
+        <item name="buttonStyleSmall">?android:attr/buttonStyleSmall</item>
+
+        <item name="imageButtonStyle">?android:attr/imageButtonStyle</item>
+
+        <item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
+        <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
+        <item name="buttonBarPositiveButtonStyle">?android:attr/buttonBarPositiveButtonStyle</item>
+        <item name="buttonBarNegativeButtonStyle">?android:attr/buttonBarNegativeButtonStyle</item>
+        <item name="buttonBarNeutralButtonStyle">?android:attr/buttonBarNeutralButtonStyle</item>
+
+        <!-- Dialog attributes -->
+        <item name="dialogTheme">?android:attr/dialogTheme</item>
+        <item name="dialogPreferredPadding">?android:attr/dialogPreferredPadding</item>
+        <item name="dialogCornerRadius">?android:attr/dialogCornerRadius</item>
+
+        <item name="alertDialogTheme">?android:attr/alertDialogTheme</item>
+        <item name="alertDialogStyle">?android:attr/alertDialogStyle</item>
+        <item name="alertDialogCenterButtons">false</item>
+        <item name="textColorAlertDialogListItem">?android:attr/textColorAlertDialogListItem</item>
+        <item name="listDividerAlertDialog">?android:attr/listDividerAlertDialog</item>
+
+        <!-- Define these here; ContextThemeWrappers around themes that define them should
+             always clear these values. -->
+        <item name="windowFixedWidthMajor">@null</item>
+        <item name="windowFixedWidthMinor">@null</item>
+        <item name="windowFixedHeightMajor">@null</item>
+        <item name="windowFixedHeightMinor">@null</item>
+
+        <!-- Tooltip attributes -->
+        <!-- TODO: tooltipFrameBackground -->
+        <item name="tooltipFrameBackground">@drawable/tooltip_frame_light</item>
+        <!-- TODO: tooltipForegroundColor -->
+        <item name="tooltipForegroundColor">@color/foreground_material_light</item>
+
+        <item name="colorError">?android:attr/colorError</item>
+
+        <!-- Attributes from: Platform.AppCompat -->
+
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowActionBar">false</item>
+
+        <item name="listChoiceIndicatorSingleAnimated">?android:attr/listChoiceIndicatorSingle</item>
+        <item name="listChoiceIndicatorMultipleAnimated">?android:attr/listChoiceIndicatorMultiple</item>
+
+        <item name="preferenceTheme">@style/CarUiPreferenceTheme</item>
+
+        <!-- Used by CarUiRecyclerView -->
+        <item name="carUiRecyclerViewStyle">@style/Widget.CarUi.CarUiRecyclerView</item>
+
+        <!-- textAppearance -->
+        <item name="android:textAppearance">@style/TextAppearance.CarUi</item>
+    </style>
+
+    <!-- TODO(b/150230923) remove this when other apps are ready -->
+    <style name="Theme.CarUi.WithToolbar">
+        <item name="carUiBaseLayout">true</item>
+        <item name="carUiToolbar">true</item>
+        <item name="preferenceTheme">@style/CarUiPreferenceTheme.WithToolbar</item>
+    </style>
+
+    <style name="Theme.CarUi.NoToolbar">
+        <item name="carUiBaseLayout">true</item>
+        <item name="carUiToolbar">false</item>
+    </style>
+
+    <style name="CarUiPreferenceTheme">
+        <item name="checkBoxPreferenceStyle">@style/Preference.CarUi.CheckBoxPreference</item>
+        <item name="dialogPreferenceStyle">@style/Preference.CarUi.DialogPreference</item>
+        <item name="dropdownPreferenceStyle">@style/Preference.CarUi.DropDown</item>
+        <item name="editTextPreferenceStyle">@style/Preference.CarUi.DialogPreference.EditTextPreference</item>
+        <item name="preferenceCategoryStyle">@style/Preference.CarUi.Category</item>
+        <item name="preferenceFragmentCompatStyle">@style/PreferenceFragment.CarUi</item>
+        <item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.CarUi</item>
+        <item name="preferenceFragmentStyle">@style/PreferenceFragment.CarUi</item>
+        <item name="preferenceScreenStyle">@style/Preference.CarUi.PreferenceScreen</item>
+        <item name="preferenceStyle">@style/Preference.CarUi</item>
+        <item name="seekBarPreferenceStyle">@style/Preference.CarUi.SeekBarPreference</item>
+        <item name="switchPreferenceStyle">@style/Preference.CarUi.SwitchPreference</item>
+    </style>
+
+    <!-- TODO(b/150230923) remove this when other apps are ready -->
+    <style name="CarUiPreferenceTheme.WithToolbar">
+        <item name="preferenceFragmentCompatStyle">@style/PreferenceFragment.CarUi.WithToolbar</item>
+        <item name="preferenceFragmentStyle">@style/PreferenceFragment.CarUi.WithToolbar</item>
+    </style>
+
+</resources>
diff --git a/car-ui-lib/res/values/values.xml b/car-ui-lib/car-ui-lib/src/main/res/values/values.xml
similarity index 100%
rename from car-ui-lib/res/values/values.xml
rename to car-ui-lib/car-ui-lib/src/main/res/values/values.xml
diff --git a/car-ui-lib/car-ui-lib/src/test/Android.bp b/car-ui-lib/car-ui-lib/src/test/Android.bp
new file mode 100644
index 0000000..5c48329
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2020 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.
+
+//###########################################################
+// CarUi lib just for Robolectric test target.     #
+//###########################################################
+android_app {
+    name: "CarUiRobolectricTestApp",
+    resource_dirs: ["res"],
+    platform_apis: true,
+    privileged: true,
+    libs: ["android.car"],
+    static_libs: ["car-ui-lib"],
+}
+
diff --git a/car-ui-lib/car-ui-lib/src/test/AndroidManifest.xml b/car-ui-lib/car-ui-lib/src/test/AndroidManifest.xml
new file mode 100644
index 0000000..eb83765
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2020 Google Inc.
+
+    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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui">
+</manifest>
diff --git a/car-ui-lib/car-ui-lib/src/test/java/Android.bp b/car-ui-lib/car-ui-lib/src/test/java/Android.bp
new file mode 100644
index 0000000..551d985
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2020 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.
+
+
+//###############################################
+// Car Ui Robolectric test target. #
+//###############################################
+android_robolectric_test {
+    name: "CarUiRoboTests",
+    srcs: ["**/*.java"],
+    libs: [
+        "android.car",
+        "testng",
+    ],
+    instrumentation_for: "CarUiRobolectricTestApp",
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiListItemTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiListItemTest.java
new file mode 100644
index 0000000..cf28632
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiListItemTest.java
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.car.ui.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class CarUiListItemTest {
+
+    private CarUiRecyclerView mListView;
+    private Context mContext;
+
+    @Mock
+    CarUiContentListItem.OnCheckedChangeListener mOnCheckedChangeListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mListView = new CarUiRecyclerView(mContext);
+    }
+
+    private CarUiListItemAdapter.ListItemViewHolder getListItemViewHolderAtPosition(int position) {
+        return (CarUiListItemAdapter.ListItemViewHolder) mListView.findViewHolderForAdapterPosition(
+                position);
+    }
+
+    private View getListItemTitleAtPosition(int position) {
+        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.title);
+    }
+
+    private View getListItemBodyAtPosition(int position) {
+        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.body);
+    }
+
+    private View getListItemIconContainerAtPosition(int position) {
+        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.icon_container);
+    }
+
+    private View getListItemActionContainerAtPosition(int position) {
+        return getListItemViewHolderAtPosition(position)
+                .itemView.findViewById(R.id.action_container);
+    }
+
+    private Switch getListItemSwitchAtPosition(int position) {
+        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.switch_widget);
+    }
+
+    private CheckBox getListItemCheckBoxAtPosition(int position) {
+        return getListItemViewHolderAtPosition(position)
+                .itemView.findViewById(R.id.checkbox_widget);
+    }
+
+    private View getListItemIconAtPosition(int position) {
+        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.icon);
+    }
+
+    private CarUiListItemAdapter.HeaderViewHolder getHeaderViewHolderAtPosition(int position) {
+        return (CarUiListItemAdapter.HeaderViewHolder) mListView.findViewHolderForAdapterPosition(
+                position);
+    }
+
+    private TextView getHeaderViewHolderTitleAtPosition(int position) {
+        return getHeaderViewHolderAtPosition(position).itemView.findViewById(R.id.title);
+    }
+
+    private TextView getHeaderViewHolderBodyAtPosition(int position) {
+        return getHeaderViewHolderAtPosition(position).itemView.findViewById(R.id.body);
+    }
+
+    private void updateRecyclerViewAdapter(CarUiListItemAdapter adapter) {
+        mListView.setAdapter(adapter);
+
+        // Force CarUiRecyclerView and the nested RecyclerView to be laid out.
+        mListView.measure(0, 0);
+        mListView.layout(0, 0, 100, 10000);
+
+        if (mListView != null) {
+            mListView.measure(0, 0);
+            mListView.layout(0, 0, 100, 10000);
+        }
+
+        // Required to init nested RecyclerView
+        mListView.getViewTreeObserver().dispatchOnGlobalLayout();
+    }
+
+    @Test
+    public void testItemVisibility_withTitle() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        items.add(item);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemActionContainerAtPosition(0).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void testItemVisibility_withTitle_withBody() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        item.setBody("Test body");
+        items.add(item);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemBodyAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemActionContainerAtPosition(0).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void testItemVisibility_withTitle_withIcon() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        item.setIcon(mContext.getDrawable(R.drawable.car_ui_icon_close));
+        items.add(item);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemIconContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemIconAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemActionContainerAtPosition(0).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void testItemVisibility_withTitle_withCheckbox() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
+        item.setTitle("Test title");
+        items.add(item);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemActionContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemSwitchAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemCheckBoxAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemCheckBoxAtPosition(0).isChecked()).isEqualTo(false);
+    }
+
+    @Test
+    public void testItemVisibility_withTitle_withBody_withSwitch() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
+        item.setTitle("Test title");
+        item.setBody("Body text");
+        items.add(item);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemBodyAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(getListItemActionContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemSwitchAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getListItemSwitchAtPosition(0).isChecked()).isEqualTo(false);
+        assertThat(getListItemCheckBoxAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void testCheckedState_switch() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
+        item.setTitle("Test title");
+        item.setOnCheckedChangeListener(mOnCheckedChangeListener);
+        item.setChecked(true);
+        items.add(item);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        Switch switchWidget = getListItemSwitchAtPosition(0);
+
+        assertThat(switchWidget.isChecked()).isEqualTo(true);
+        switchWidget.performClick();
+        assertThat(switchWidget.isChecked()).isEqualTo(false);
+        verify(mOnCheckedChangeListener, times(1))
+                .onCheckedChanged(item, false);
+    }
+
+    @Test
+    public void testCheckedState_checkbox() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
+        item.setTitle("Test title");
+        item.setOnCheckedChangeListener(mOnCheckedChangeListener);
+        items.add(item);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        CheckBox checkBox = getListItemCheckBoxAtPosition(0);
+
+        assertThat(checkBox.isChecked()).isEqualTo(false);
+        checkBox.performClick();
+        assertThat(checkBox.isChecked()).isEqualTo(true);
+        verify(mOnCheckedChangeListener, times(1))
+                .onCheckedChanged(item, true);
+    }
+
+    @Test
+    public void testHeader_onlyTitle() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CharSequence title = "Test header";
+        CarUiHeaderListItem header = new CarUiHeaderListItem(title);
+        items.add(header);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        assertThat(getHeaderViewHolderTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(getHeaderViewHolderTitleAtPosition(0).getText()).isEqualTo(title);
+        assertThat(getHeaderViewHolderBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void testHeader_titleAndBody() {
+        List<CarUiListItem> items = new ArrayList<>();
+
+        CharSequence title = "Test header";
+        CharSequence body = "With body text";
+
+        CarUiHeaderListItem header = new CarUiHeaderListItem(title, body);
+        items.add(header);
+
+        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
+
+        TextView titleView = getHeaderViewHolderTitleAtPosition(0);
+        TextView bodyView = getHeaderViewHolderBodyAtPosition(0);
+
+        assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(titleView.getText()).isEqualTo(title);
+        assertThat(bodyView.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(bodyView.getText()).isEqualTo(body);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
new file mode 100644
index 0000000..4d21851
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.ViewGroup;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class CarUiRecyclerViewAdapterTest {
+
+    private Context mContext;
+    private CarUiRecyclerViewAdapter mCarUiRecyclerViewAdapter;
+
+    @Mock
+    private ViewGroup mParent;
+    @Mock
+    private ViewGroup.LayoutParams mLayoutParams;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mCarUiRecyclerViewAdapter = new CarUiRecyclerViewAdapter();
+    }
+
+    @Test
+    public void getItemCount_shouldAlwaysBeOne() {
+        assertThat(mCarUiRecyclerViewAdapter.getItemCount()).isEqualTo(1);
+    }
+
+    @Test
+    public void onCreateViewHolder_frameLayoutNotNull() {
+
+        when(mParent.getContext()).thenReturn(mContext);
+        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+        CarUiRecyclerViewAdapter.NestedRowViewHolder nestedRowViewHolder =
+                mCarUiRecyclerViewAdapter.onCreateViewHolder(mParent, 0);
+
+        assertThat(nestedRowViewHolder.frameLayout).isNotNull();
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
new file mode 100644
index 0000000..648a3a4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import com.android.car.ui.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class CarUiRecyclerViewTest {
+
+    private Context mContext;
+    private View mView;
+    private CarUiRecyclerView mCarUiRecyclerView;
+    private Resources mResources;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mResources = mContext.getResources();
+    }
+
+    @Test
+    public void setAdapter_shouldInitializeLinearLayoutManager() {
+        mView = LayoutInflater.from(mContext)
+                .inflate(mResources.getIdentifier("test_linear_car_ui_recycler_view", "layout",
+                        mContext.getPackageName()), null);
+
+        mCarUiRecyclerView = mView.findViewById(
+                mResources.getIdentifier("test_prv", "id", mContext.getPackageName()));
+
+        assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
+                LinearLayoutManager.class);
+    }
+
+    @Test
+    public void setAdapter_shouldInitializeGridLayoutManager() {
+        mView = LayoutInflater.from(mContext)
+                .inflate(mResources.getIdentifier("test_grid_car_ui_recycler_view", "layout",
+                        mContext.getPackageName()), null);
+
+        mCarUiRecyclerView = mView.findViewById(
+                mResources.getIdentifier("test_prv", "id", mContext.getPackageName()));
+
+        assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
+                GridLayoutManager.class);
+    }
+
+    @Test
+    public void init_shouldContainRecyclerView() {
+        mView = LayoutInflater.from(mContext)
+                .inflate(mResources.getIdentifier("test_linear_car_ui_recycler_view", "layout",
+                        mContext.getPackageName()), null);
+
+        mCarUiRecyclerView = mView.findViewById(
+                mResources.getIdentifier("test_prv", "id", mContext.getPackageName()));
+
+        assertThat(mCarUiRecyclerView).isNotNull();
+    }
+
+    @Test
+    public void init_shouldHaveGridLayout() {
+        mCarUiRecyclerView = new CarUiRecyclerView(mContext,
+                Robolectric.buildAttributeSet().addAttribute(R.attr.layoutStyle, "grid").build());
+        assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
+                GridLayoutManager.class);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
new file mode 100644
index 0000000..c5dc78b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static androidx.recyclerview.widget.LinearSmoothScroller.SNAP_TO_START;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class CarUiSmoothScrollerTest {
+
+    private Context mContext;
+    private CarUiSmoothScroller mCarUiSmoothScroller;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mCarUiSmoothScroller = new CarUiSmoothScroller(mContext);
+    }
+
+    @Test
+    public void calculateTimeForScrolling_shouldInitializeAllValues() {
+        assertThat(mCarUiSmoothScroller.mMillisecondsPerInch).isNotEqualTo(0);
+        assertThat(mCarUiSmoothScroller.mDecelerationTimeDivisor).isNotEqualTo(0);
+        assertThat(mCarUiSmoothScroller.mMillisecondsPerPixel).isNotEqualTo(0);
+        assertThat(mCarUiSmoothScroller.mInterpolator).isNotNull();
+        assertThat(mCarUiSmoothScroller.mDensityDpi).isNotEqualTo(0);
+    }
+
+    @Test
+    public void getVerticalSnapPreference_shouldReturnSnapToStart() {
+        assertThat(mCarUiSmoothScroller.getVerticalSnapPreference()).isEqualTo(SNAP_TO_START);
+    }
+
+    @Test
+    public void calculateTimeForScrolling_shouldReturnMultiplierOfMillisecondsPerPixel() {
+        assertThat(mCarUiSmoothScroller.calculateTimeForScrolling(20)).isEqualTo(
+                (int) Math.ceil(Math.abs(20) * mCarUiSmoothScroller.mMillisecondsPerPixel));
+    }
+
+    @Test
+    public void calculateTimeForDeceleration_shouldReturnNotBeZero() {
+        assertThat(mCarUiSmoothScroller.calculateTimeForDeceleration(20)).isNotEqualTo(0);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
new file mode 100644
index 0000000..62edd3d
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.View;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class CarUiSnapHelperTest {
+
+    private Context mContext;
+    private CarUiSnapHelper mCarUiSnapHelper;
+
+    @Mock
+    private RecyclerView mRecyclerView;
+    @Mock
+    private LinearLayoutManager mLayoutManager;
+    @Mock
+    private RecyclerView.Adapter mAdapter;
+    @Mock
+    private View mChild;
+    @Mock
+    private RecyclerView.LayoutParams mLayoutParams;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+
+        mCarUiSnapHelper = new CarUiSnapHelper(mContext);
+
+        when(mRecyclerView.getContext()).thenReturn(mContext);
+        mCarUiSnapHelper.attachToRecyclerView(mRecyclerView);
+    }
+
+    @Test
+    public void calculateDistanceToFinalSnap_shouldReturnTopMarginDifference() {
+        when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+        when(mRecyclerView.isInTouchMode()).thenReturn(true);
+        when(mLayoutManager.getItemCount()).thenReturn(1);
+        when(mLayoutManager.canScrollVertically()).thenReturn(true);
+        when(mLayoutManager.getChildCount()).thenReturn(1);
+        // some delta
+        when(mLayoutManager.getDecoratedTop(any())).thenReturn(10);
+        when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
+
+        int[] distance = mCarUiSnapHelper.calculateDistanceToFinalSnap(mLayoutManager, mChild);
+
+        assertThat(distance[1]).isEqualTo(10);
+    }
+
+    @Test
+    public void calculateScrollDistance_shouldScrollHeightOfView() {
+        when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+        when(mLayoutManager.getItemCount()).thenReturn(1);
+        when(mLayoutManager.canScrollVertically()).thenReturn(true);
+        when(mLayoutManager.getChildCount()).thenReturn(1);
+        // some delta
+        when(mLayoutManager.getDecoratedTop(any())).thenReturn(10);
+        when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
+        when(mLayoutManager.getChildAt(0)).thenReturn(mChild);
+        when(mLayoutManager.getHeight()).thenReturn(-50);
+
+        int[] distance = mCarUiSnapHelper.calculateScrollDistance(0, 10);
+
+        assertThat(distance[1]).isEqualTo(50);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/DefaultScrollBarTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
new file mode 100644
index 0000000..1cd59df
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.recyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class DefaultScrollBarTest {
+
+    private Context mContext;
+    private ScrollBar mScrollBar;
+
+    @Mock
+    private RecyclerView mRecyclerView;
+    @Mock
+    private FrameLayout mParent;
+    @Mock
+    private FrameLayout.LayoutParams mLayoutParams;
+    @Mock
+    private RecyclerView.RecycledViewPool mRecycledViewPool;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+
+        mScrollBar = new DefaultScrollBar();
+    }
+
+    @Test
+    public void initialize_shouldInitializeScrollListener() {
+        when(mRecyclerView.getContext()).thenReturn(mContext);
+        when(mRecyclerView.getParent()).thenReturn(mParent);
+        when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+        View scrollView = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_recyclerview_scrollbar, null);
+        mScrollBar.initialize(mRecyclerView, scrollView);
+
+        // called once in DefaultScrollBar and once in SnapHelper while setting up the call backs
+        // when we use attachToRecyclerView(recyclerview)
+        verify(mRecyclerView, times(2)).addOnScrollListener(
+                any(RecyclerView.OnScrollListener.class));
+    }
+
+    @Test
+    public void initialize_shouldSetMaxRecyclerViews() {
+        when(mRecyclerView.getContext()).thenReturn(mContext);
+        when(mRecyclerView.getParent()).thenReturn(mParent);
+        when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+        View scrollView = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_recyclerview_scrollbar, null);
+        mScrollBar.initialize(mRecyclerView, scrollView);
+
+        verify(mRecycledViewPool).setMaxRecycledViews(0, 12);
+    }
+
+    @Test
+    public void initialize_shouldNotHaveFlingListener() {
+        when(mRecyclerView.getContext()).thenReturn(mContext);
+        when(mRecyclerView.getParent()).thenReturn(mParent);
+        when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+        View scrollView = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_recyclerview_scrollbar, null);
+        mScrollBar.initialize(mRecyclerView, scrollView);
+
+        verify(mRecyclerView).setOnFlingListener(null);
+    }
+
+    @Test
+    public void setPadding_shouldSetStartAndEndPadding() {
+        when(mRecyclerView.getContext()).thenReturn(mContext);
+        when(mRecyclerView.getParent()).thenReturn(mParent);
+        when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+        View scrollView = LayoutInflater.from(mContext).inflate(
+                R.layout.car_ui_recyclerview_scrollbar, null);
+        mScrollBar.initialize(mRecyclerView, scrollView);
+        mScrollBar.setPadding(10, 20);
+
+        assertThat(scrollView.getPaddingTop()).isEqualTo(10);
+        assertThat(scrollView.getPaddingBottom()).isEqualTo(20);
+    }
+
+    @Test
+    public void setPadding_shouldThrowErrorWithoutInitialization() {
+        assertThrows(NullPointerException.class, () -> mScrollBar.setPadding(10, 20));
+    }
+
+    @Test
+    public void requestLayout_shouldThrowErrorWithoutInitialization() {
+        assertThrows(NullPointerException.class, () -> mScrollBar.requestLayout());
+    }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ExtendedShadowTypeface.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/ExtendedShadowTypeface.java
similarity index 100%
rename from car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ExtendedShadowTypeface.java
rename to car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/ExtendedShadowTypeface.java
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ShadowAsyncLayoutInflater.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/ShadowAsyncLayoutInflater.java
similarity index 100%
rename from car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ShadowAsyncLayoutInflater.java
rename to car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/ShadowAsyncLayoutInflater.java
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/TestActivity.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/TestActivity.java
new file mode 100644
index 0000000..b6fa3c4
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/TestActivity.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.toolbar;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/** An activity to use in the Toolbar tests */
+public class TestActivity extends Activity {
+
+    private int mTimesBackPressed = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(getResources().getIdentifier("test_toolbar", "layout", getPackageName()));
+    }
+
+    @Override
+    public void onBackPressed() {
+        mTimesBackPressed++;
+        super.onBackPressed();
+    }
+
+    public int getTimesBackPressed() {
+        return mTimesBackPressed;
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/ToolbarTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/ToolbarTest.java
new file mode 100644
index 0000000..330660b
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/toolbar/ToolbarTest.java
@@ -0,0 +1,520 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.toolbar;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+import com.android.car.ui.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ExtendedShadowTypeface.class, ShadowAsyncLayoutInflater.class},
+        qualifiers = "land")
+public class ToolbarTest {
+
+    private Context mContext;
+    private Resources mResources;
+    private ActivityController<TestActivity> mActivityController;
+    private TestActivity mActivity;
+    private Toolbar mToolbar;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mResources = mContext.getResources();
+        mActivityController = Robolectric.buildActivity(TestActivity.class);
+        mActivityController.setup();
+        mActivity = mActivityController.get();
+        mToolbar = mActivity.findViewById(R.id.toolbar);
+    }
+
+    private int getTestDrawableInt(String drawable) {
+        return mResources.getIdentifier(drawable, "drawable", mContext.getPackageName());
+    }
+
+    @Test
+    public void getters_nochanges_shouldReturnDefaults() {
+        assertThat(mToolbar.getBackgroundShown()).isEqualTo(true);
+        assertThat(mToolbar.getShowMenuItemsWhileSearching()).isEqualTo(false);
+        assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.HOME);
+        assertThat(mToolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
+                Toolbar.NavButtonMode.BACK);
+    }
+
+    @Test
+    public void setState_subpage_shouldCauseGetStateToReturnSubpage() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+
+        assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
+    }
+
+    @Test
+    public void setters_and_getters_test() {
+        mToolbar.setTitle("Foo");
+        mToolbar.setSearchHint("Foo2");
+        mToolbar.setBackgroundShown(false);
+        mToolbar.setShowMenuItemsWhileSearching(true);
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+        mToolbar.setNavButtonMode(Toolbar.NavButtonMode.CLOSE);
+
+        assertThat(mToolbar.getTitle().toString()).isEqualTo("Foo");
+        assertThat(mToolbar.getSearchHint().toString()).isEqualTo("Foo2");
+        assertThat(mToolbar.getBackgroundShown()).isEqualTo(false);
+        assertThat(mToolbar.getShowMenuItemsWhileSearching()).isEqualTo(true);
+        assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
+        assertThat(mToolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
+                Toolbar.NavButtonMode.CLOSE);
+    }
+
+    @Test
+    public void showLogo_whenSet_andStateIsHome() {
+        mToolbar.setState(Toolbar.State.HOME);
+        mToolbar.setLogo(getTestDrawableInt("test_ic_launcher"));
+
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isTrue();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isFalse();
+    }
+
+    @Test
+    public void hideLogo_andTitleLogo_whenSet_andStateIsHome_andLogoIsDisabled() {
+        mockResources();
+        when(mResources.getBoolean(R.bool.car_ui_toolbar_show_logo)).thenReturn(false);
+
+        Toolbar toolbar = new Toolbar(mContext);
+        toolbar.setState(Toolbar.State.HOME);
+        mToolbar.setLogo(getTestDrawableInt("test_ic_launcher"));
+
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_logo)).isFalse();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title_logo)).isFalse();
+    }
+
+    @Test
+    public void showTitleLogo_whenSet_andStateIsNotHome() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+        mToolbar.setLogo(getTestDrawableInt("test_ic_launcher"));
+
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isTrue();
+    }
+
+    @Test
+    public void hideLogo_andTitleLogo_whenNotSet_andStateIsHome() {
+        mToolbar.setState(Toolbar.State.HOME);
+        mToolbar.setLogo(0);
+
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isFalse();
+    }
+
+    @Test
+    public void hideLogo_andTitleLogo_whenNotSet_andStateIsNotHome() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+        mToolbar.setLogo(0);
+
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).isShown()).isFalse();
+        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).isShown()).isFalse();
+    }
+
+    @Test
+    public void registerOnBackListener_whenBackIsPressed_shouldCallListener() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+        Mutable<Integer> timesBackPressed = new Mutable<>(0);
+        Toolbar.OnBackListener listener = () -> {
+            timesBackPressed.value++;
+            return false;
+        };
+
+        mToolbar.registerOnBackListener(listener);
+        pressBack();
+
+        assertThat(timesBackPressed.value).isEqualTo(1);
+        assertThat(mActivity.getTimesBackPressed()).isEqualTo(1);
+    }
+
+    @Test
+    public void registerOnBackListener_whenAListenerReturnsTrue_shouldSuppressBack() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+
+        mToolbar.registerOnBackListener(() -> true);
+        pressBack();
+        mToolbar.registerOnBackListener(() -> false);
+        pressBack();
+
+        assertThat(mActivity.getTimesBackPressed()).isEqualTo(0);
+    }
+
+    @Test
+    public void testState_twoRow_withTitle_withTabs() {
+        mockResources();
+        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
+
+        Toolbar toolbar = new Toolbar(mContext);
+        assertThat(toolbar.isTabsInSecondRow()).isTrue();
+
+        // Set title and tabs for toolbar.
+        toolbar.setTitle("Test title");
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+
+        // Toolbar should display two rows, showing both title and tabs.
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
+    }
+
+    @Test
+    public void testState_twoRow_withTitle() {
+        mockResources();
+        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
+
+        Toolbar toolbar = new Toolbar(mContext);
+        assertThat(toolbar.isTabsInSecondRow()).isTrue();
+
+        toolbar.setTitle("Test title");
+
+        // Toolbar should display two rows, but no tabs are set so they should not be visible.
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isFalse();
+    }
+
+    @Test
+    public void testState_twoRow_withTabs() {
+        mockResources();
+        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
+
+        Toolbar toolbar = new Toolbar(mContext);
+        assertThat(toolbar.isTabsInSecondRow()).isTrue();
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+
+        // Toolbar should display two rows with an empty title and tabs.
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
+    }
+
+    @Test
+    public void testState_oneRow_withTitle_withTabs() {
+        mockResources();
+        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
+
+        Toolbar toolbar = new Toolbar(mContext);
+        assertThat(toolbar.isTabsInSecondRow()).isFalse();
+
+        // Set title and tabs for toolbar.
+        toolbar.setTitle("Test title");
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+
+        // With only one row available, toolbar will only show tabs and not the title.
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isFalse();
+    }
+
+    @Test
+    public void testState_oneRow_withTitle() {
+        mockResources();
+        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
+
+        Toolbar toolbar = new Toolbar(mContext);
+        assertThat(toolbar.isTabsInSecondRow()).isFalse();
+
+        toolbar.setTitle("Test title");
+
+        // Toolbar should display one row with the title and no tabs.
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isFalse();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isTrue();
+    }
+
+    @Test
+    public void testState_oneRow_withTabs() {
+        mockResources();
+        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
+
+        Toolbar toolbar = new Toolbar(mContext);
+        assertThat(toolbar.isTabsInSecondRow()).isFalse();
+
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+        toolbar.addTab(
+                new TabLayout.Tab(mContext.getDrawable(getTestDrawableInt("test_ic_launcher")),
+                        "Foo"));
+
+        // Toolbar should display one row with only tabs.
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_tabs)).isTrue();
+        assertThat(isViewInToolbarShown(toolbar, R.id.car_ui_toolbar_title)).isFalse();
+    }
+
+    @Test
+    public void registerOnBackListener_whenListenerRegisteredTwice_shouldntCallListenerTwice() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+        Mutable<Integer> timesBackPressed = new Mutable<>(0);
+        Toolbar.OnBackListener listener = () -> {
+            timesBackPressed.value++;
+            return false;
+        };
+
+        // Registering a second time shouldn't do anything
+        mToolbar.registerOnBackListener(listener);
+        mToolbar.registerOnBackListener(listener);
+        pressBack();
+
+        assertThat(timesBackPressed.value).isEqualTo(1);
+    }
+
+    @Test
+    public void unregisterOnBackListener_previouslyRegisteredListener_shouldUnregister() {
+        mToolbar.setState(Toolbar.State.SUBPAGE);
+        Mutable<Integer> timesBackPressed = new Mutable<>(0);
+        Toolbar.OnBackListener listener = () -> {
+            timesBackPressed.value++;
+            return false;
+        };
+
+        mToolbar.registerOnBackListener(listener);
+        mToolbar.unregisterOnBackListener(listener);
+        pressBack();
+
+        assertThat(timesBackPressed.value).isEqualTo(0);
+    }
+
+    @Test
+    public void menuItems_builder_id() {
+        MenuItem item = MenuItem.builder(mContext)
+                .setId(5)
+                .build();
+
+        assertThat(item.getId()).isEqualTo(5);
+    }
+
+    @Test
+    public void menuItems_setId_shouldWork() {
+        MenuItem item = MenuItem.builder(mContext).build();
+
+        assertThat(item.getId()).isEqualTo(View.NO_ID);
+
+        item.setId(7);
+
+        assertThat(item.getId()).isEqualTo(7);
+    }
+
+    @Test
+    public void menuItems_whenClicked_shouldCallListener() {
+        assertThat(getMenuItemCount()).isEqualTo(0);
+
+        Mutable<Boolean> button1Clicked = new Mutable<>(false);
+        Mutable<Boolean> button2Clicked = new Mutable<>(false);
+        mToolbar.setMenuItems(Arrays.asList(
+                createMenuItem(i -> button1Clicked.value = true),
+                createMenuItem(i -> button2Clicked.value = true)));
+
+        assertThat(getMenuItemCount()).isEqualTo(2);
+
+        getMenuItemView(0).performClick();
+
+        assertThat(button1Clicked.value).isTrue();
+
+        getMenuItemView(1).performClick();
+
+        assertThat(button2Clicked.value).isTrue();
+    }
+
+    @Test
+    public void menuItems_null_shouldRemoveExistingMenuItems() {
+        mToolbar.setMenuItems(Arrays.asList(
+                createMenuItem(i -> {
+                }),
+                createMenuItem(i -> {
+                })));
+
+        assertThat(getMenuItemCount()).isEqualTo(2);
+
+        mToolbar.setMenuItems(null);
+
+        assertThat(getMenuItemCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void menuItems_setVisibility_shouldDefaultToShown() {
+        MenuItem item = createMenuItem(i -> {
+        });
+        mToolbar.setMenuItems(Collections.singletonList(item));
+
+        assertThat(getMenuItemView(0).isShown()).isTrue();
+    }
+
+    @Test
+    public void menuItems_setVisibility_shouldHide() {
+        MenuItem item = createMenuItem(i -> {
+        });
+        mToolbar.setMenuItems(Collections.singletonList(item));
+
+        item.setVisible(false);
+        assertThat(getMenuItemView(0).isShown()).isFalse();
+    }
+
+    @Test
+    public void menuItems_setVisibility_shouldReshowAfterHiding() {
+        MenuItem item = createMenuItem(i -> {
+        });
+        mToolbar.setMenuItems(Collections.singletonList(item));
+
+        item.setVisible(false);
+        item.setVisible(true);
+        assertThat(getMenuItemView(0).isShown()).isTrue();
+    }
+
+    @Test
+    public void menuItems_equalItems_shouldntRecreateViews() {
+        List<MenuItem> menuItems = Arrays.asList(
+                createMenuItem(i -> {
+                }),
+                createMenuItem(i -> {
+                }));
+        mToolbar.setMenuItems(menuItems);
+
+        assertThat(getMenuItemCount()).isEqualTo(2);
+
+        View firstMenuItemView = getMenuItemView(0);
+
+        mToolbar.setMenuItems(menuItems);
+
+        assertThat(firstMenuItemView).isSameAs(getMenuItemView(0));
+    }
+
+    @Test
+    public void menuItems_searchScreen_shouldHideMenuItems() {
+        mToolbar.setMenuItems(Arrays.asList(
+                MenuItem.builder(mContext).setToSearch().build(),
+                createMenuItem(i -> {
+                })));
+
+        mToolbar.setShowMenuItemsWhileSearching(false);
+        mToolbar.setState(Toolbar.State.SEARCH);
+
+        assertThat(getMenuItemView(0).isShown()).isFalse();
+        assertThat(getMenuItemView(1).isShown()).isFalse();
+    }
+
+    @Test
+    public void menuItems_showMenuItemsWhileSearching() {
+        mToolbar.setMenuItems(Arrays.asList(
+                MenuItem.builder(mContext).setToSearch().build(),
+                createMenuItem(i -> {
+                })));
+
+        mToolbar.setShowMenuItemsWhileSearching(true);
+        mToolbar.setState(Toolbar.State.SEARCH);
+
+        assertThat(getMenuItemView(0).isShown()).isFalse();
+        assertThat(getMenuItemView(1).isShown()).isTrue();
+    }
+
+    private MenuItem createMenuItem(MenuItem.OnClickListener listener) {
+        return MenuItem.builder(mContext)
+                .setTitle("Button!")
+                .setOnClickListener(listener)
+                .build();
+    }
+
+    private void mockResources() {
+        mContext = spy(RuntimeEnvironment.application);
+        mResources = spy(mContext.getResources());
+        when(mContext.getResources()).thenReturn(mResources);
+    }
+
+    private int getMenuItemCount() {
+        return mToolbar.getMenuItems().size();
+    }
+
+    /**
+     * IsShown() will return false for views that are not attached to an activity.
+     * This altered version will return true for that case.
+     */
+    private boolean isViewInToolbarShown(Toolbar toolbar, int id) {
+        View current = toolbar.findViewById(id);
+        //noinspection ConstantConditions
+        do {
+            if (current.getVisibility() != View.VISIBLE) {
+                return false;
+            }
+            ViewParent parent = current.getParent();
+            if (parent == null) {
+                return false; // We are not attached to the view root
+            }
+            if (parent == toolbar || !(parent instanceof View)) {
+                // Return true if we hit the toolbar, or this parent isn't a view.
+                // The parent wouldn't be a view if it was a ViewRootImpl, the parent
+                // of a whole view hierarchy
+                return true;
+            }
+            current = (View) parent;
+        } while (current != null);
+        return false;
+    }
+
+    private View getMenuItemView(int index) {
+        return ((ViewGroup) mToolbar
+                .findViewById(R.id.car_ui_toolbar_menu_items_container))
+                .getChildAt(index);
+    }
+
+    private void pressBack() {
+        mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).performClick();
+    }
+
+    private static class Mutable<T> {
+        public T value;
+
+        Mutable(T value) {
+            this.value = value;
+        }
+    }
+
+}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
new file mode 100644
index 0000000..ea62ee5
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.car.drivingstate.CarUxRestrictions;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class CarUxRestrictionsUtilTest {
+    private int[] mRestrictionsArray;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mRestrictionsArray = new int[]{
+                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD,
+                CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
+                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
+                        | CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
+                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED
+        };
+    }
+
+    @Test
+    public void testNullActiveRestriction() {
+        CarUxRestrictions activeRestrictions = null;
+        boolean[] expectedResults = {true, true, true, true};
+        for (int i = 0; i < mRestrictionsArray.length; i++) {
+            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
+                    activeRestrictions);
+            assertThat(actualResult == expectedResults[i]).isTrue();
+        }
+    }
+
+    @Test
+    public void testOneActiveRestriction() {
+        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
+                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD, /* timestamp= */0).build();
+        boolean[] expectedResults = {true, false, true, true};
+        for (int i = 0; i < mRestrictionsArray.length; i++) {
+            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
+                    activeRestrictions);
+            assertThat(actualResult == expectedResults[i]).isTrue();
+        }
+    }
+
+    @Test
+    public void testMultipleActiveRestrictions() {
+        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
+                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
+                        | CarUxRestrictions.UX_RESTRICTIONS_NO_TEXT_MESSAGE, /* timestamp= */
+                0).build();
+        boolean[] expectedResults = {true, false, true, true};
+        for (int i = 0; i < mRestrictionsArray.length; i++) {
+            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
+                    activeRestrictions);
+            assertThat(actualResult == expectedResults[i]).isTrue();
+        }
+    }
+}
diff --git a/car-ui-lib/tests/robotests/res/drawable/test_ic_launcher.png b/car-ui-lib/car-ui-lib/src/test/res/drawable/test_ic_launcher.png
similarity index 100%
rename from car-ui-lib/tests/robotests/res/drawable/test_ic_launcher.png
rename to car-ui-lib/car-ui-lib/src/test/res/drawable/test_ic_launcher.png
Binary files differ
diff --git a/car-ui-lib/tests/robotests/res/layout/test_custom_view.xml b/car-ui-lib/car-ui-lib/src/test/res/layout/test_custom_view.xml
similarity index 100%
rename from car-ui-lib/tests/robotests/res/layout/test_custom_view.xml
rename to car-ui-lib/car-ui-lib/src/test/res/layout/test_custom_view.xml
diff --git a/car-ui-lib/car-ui-lib/src/test/res/layout/test_grid_car_ui_recycler_view.xml b/car-ui-lib/car-ui-lib/src/test/res/layout/test_grid_car_ui_recycler_view.xml
new file mode 100644
index 0000000..e5bf7a3
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/res/layout/test_grid_car_ui_recycler_view.xml
@@ -0,0 +1,28 @@
+<?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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/test_prv"
+        app:layoutStyle="grid"
+        app:numOfColumns="4"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/test/res/layout/test_linear_car_ui_recycler_view.xml b/car-ui-lib/car-ui-lib/src/test/res/layout/test_linear_car_ui_recycler_view.xml
new file mode 100644
index 0000000..8f7f2ad
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/res/layout/test_linear_car_ui_recycler_view.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/test_prv"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/test/res/layout/test_toolbar.xml b/car-ui-lib/car-ui-lib/src/test/res/layout/test_toolbar.xml
new file mode 100644
index 0000000..19a1111
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/test/res/layout/test_toolbar.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+</FrameLayout>
diff --git a/car-ui-lib/documentation/images/android_project_view.png b/car-ui-lib/documentation/images/android_project_view.png
new file mode 100644
index 0000000..9b82bc2
--- /dev/null
+++ b/car-ui-lib/documentation/images/android_project_view.png
Binary files differ
diff --git a/car-ui-lib/documentation/images/launch_paintbooth.png b/car-ui-lib/documentation/images/launch_paintbooth.png
new file mode 100644
index 0000000..ba901b6
--- /dev/null
+++ b/car-ui-lib/documentation/images/launch_paintbooth.png
Binary files differ
diff --git a/car-ui-lib/documentation/images/navigating_to_car_ui_lib.png b/car-ui-lib/documentation/images/navigating_to_car_ui_lib.png
new file mode 100644
index 0000000..4897ad6
--- /dev/null
+++ b/car-ui-lib/documentation/images/navigating_to_car_ui_lib.png
Binary files differ
diff --git a/car-ui-lib/documentation/images/open_existing_android_studio_project.png b/car-ui-lib/documentation/images/open_existing_android_studio_project.png
new file mode 100644
index 0000000..29c2f96
--- /dev/null
+++ b/car-ui-lib/documentation/images/open_existing_android_studio_project.png
Binary files differ
diff --git a/car-ui-lib/documentation/images/running_tests.png b/car-ui-lib/documentation/images/running_tests.png
new file mode 100644
index 0000000..796bf3a
--- /dev/null
+++ b/car-ui-lib/documentation/images/running_tests.png
Binary files differ
diff --git a/car-ui-lib/findviewbyid-preupload-hook.sh b/car-ui-lib/findviewbyid-preupload-hook.sh
index e520eb2..6478802 100755
--- a/car-ui-lib/findviewbyid-preupload-hook.sh
+++ b/car-ui-lib/findviewbyid-preupload-hook.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 if grep -rq --exclude=CarUiUtils.java "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/; then
-    grep -r --exclude=CarUiUtils.java "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/;
+    grep -r --exclude-CarUiUtils.java "findViewById\|requireViewById" car-ui-lib/src/com/android/car/ui/;
     echo "Illegal use of findViewById or requireViewById in car-ui-lib. Please consider using CarUiUtils#findViewByRefId or CarUiUtils#requireViewByRefId" && false;
 fi
 
diff --git a/car-ui-lib/generate_rros.mk b/car-ui-lib/generate_rros.mk
index 4f67520..c0d2966 100644
--- a/car-ui-lib/generate_rros.mk
+++ b/car-ui-lib/generate_rros.mk
@@ -21,7 +21,8 @@
 define generate-rro
   include $$(CLEAR_VARS)
 
-  rro_package_name := $(2)-$(subst .,-,$(1))
+  rro_package_name := $(subst .,-,$(2))-$(subst .,-,$(1))
+  manifest_file := $(4)
   LOCAL_RESOURCE_DIR := $(3)
   LOCAL_RRO_THEME := $$(rro_package_name)
   LOCAL_PACKAGE_NAME := $$(rro_package_name)
@@ -34,7 +35,7 @@
   LOCAL_AAPT_FLAGS := --no-resource-deduping
 
   gen := $$(call intermediates-dir-for,ETC,$$(rro_package_name))/AndroidManifest.xml
-  $$(gen): $(LOCAL_PATH)/AndroidManifest.xml
+  $$(gen): $$(manifest_file)
 	@echo Generate $$@
 	$$(hide) mkdir -p $$(dir $$@)
 	$$(hide) sed -e "s/{{TARGET_PACKAGE_NAME}}/$(1)/" \
@@ -44,11 +45,17 @@
   include $$(BUILD_RRO_PACKAGE)
 endef
 
+ifndef CAR_UI_RRO_MANIFEST_FILE
+CAR_UI_RRO_MANIFEST_FILE = $(LOCAL_PATH)/AndroidManifest.xml
+endif
+
 $(foreach t,\
   $(CAR_UI_RRO_TARGETS),\
-  $(eval $(call generate-rro,$(t),$(CAR_UI_RRO_SET_NAME),$(CAR_UI_RESOURCE_DIR))))
+  $(eval $(call generate-rro,$(t),$(CAR_UI_RRO_SET_NAME),$(CAR_UI_RESOURCE_DIR),$(CAR_UI_RRO_MANIFEST_FILE))) \
+  )
 
 # Clear variables
 CAR_UI_RRO_SET_NAME :=
+CAR_UI_RRO_MANIFEST_FILE :=
 CAR_UI_RESOURCE_DIR :=
 CAR_UI_RRO_TARGETS :=
diff --git a/car-ui-lib/paintbooth/AndroidManifest-gradle.xml b/car-ui-lib/paintbooth/AndroidManifest-gradle.xml
new file mode 100644
index 0000000..3184bd7
--- /dev/null
+++ b/car-ui-lib/paintbooth/AndroidManifest-gradle.xml
@@ -0,0 +1,88 @@
+<?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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.car.ui.paintbooth">
+
+  <application
+      android:supportsRtl="true"
+      android:icon="@drawable/ic_launcher"
+      android:label="@string/app_name"
+      android:theme="@style/Theme.CarUi.WithToolbar">
+    <activity
+        android:name=".MainActivity"
+        android:exported="true">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN"/>
+        <category android:name="android.intent.category.LAUNCHER"/>
+      </intent-filter>
+    </activity>
+
+    <activity
+        android:name=".dialogs.DialogsActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".caruirecyclerview.CarUiRecyclerViewActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".caruirecyclerview.GridCarUiRecyclerViewActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".preferences.PreferenceActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".toolbar.ToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity">
+      <meta-data android:name="distractionOptimized" android:value="true"/>
+    </activity>
+    <activity
+        android:name=".toolbar.OldToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"
+        android:theme="@style/Theme.CarUi">
+      <meta-data android:name="distractionOptimized" android:value="true"/>
+    </activity>
+    <activity
+        android:name=".overlays.OverlayActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity">
+      <meta-data android:name="distractionOptimized" android:value="true"/>
+    </activity>
+    <activity
+        android:name=".widgets.WidgetActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".caruirecyclerview.CarUiListItemActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+
+    <service
+        android:label="Current Activity Service"
+        android:exported="false"
+        android:name=".currentactivity.CurrentActivityService"/>
+    <service
+        android:label="Visible Bounds Simulator"
+        android:exported="false"
+        android:name=".VisibleBoundsSimulator"/>
+  </application>
+</manifest>
diff --git a/car-ui-lib/paintbooth/AndroidManifest.xml b/car-ui-lib/paintbooth/AndroidManifest.xml
new file mode 100644
index 0000000..c277ff5
--- /dev/null
+++ b/car-ui-lib/paintbooth/AndroidManifest.xml
@@ -0,0 +1,114 @@
+<?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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.car.ui.paintbooth">
+
+  <uses-sdk
+      android:minSdkVersion="28"
+      android:targetSdkVersion="28"/>
+
+  <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
+  <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+  <uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
+  <uses-permission android:name="android.permission.MANAGE_USERS"/>
+  <!-- Required to use the TYPE_DISPLAY_OVERLAY layout param for the current activity overlay -->
+  <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
+  <!-- Required for listening to android task stack changes -->
+  <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
+  <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+  <!-- Required for using TYPE_APPLICATION_OVERLAY to display overlays -->
+  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+  <!-- Required to test permission dialogs -->
+  <uses-permission android:name="android.permission.CAMERA"/>
+  <uses-permission android:name="android.permission.READ_CONTACTS"/>
+  <uses-permission android:name="android.permission.SEND_SMS"/>
+  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
+
+  <application
+      android:supportsRtl="true"
+      android:icon="@drawable/ic_launcher"
+      android:label="@string/app_name"
+      android:theme="@style/Theme.CarUi.WithToolbar">
+    <activity
+        android:name=".MainActivity"
+        android:exported="true">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN"/>
+        <category android:name="android.intent.category.LAUNCHER"/>
+      </intent-filter>
+    </activity>
+
+    <activity
+        android:name=".dialogs.DialogsActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".caruirecyclerview.CarUiRecyclerViewActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".caruirecyclerview.GridCarUiRecyclerViewActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".preferences.PreferenceActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".toolbar.ToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity">
+      <meta-data android:name="distractionOptimized" android:value="true"/>
+    </activity>
+    <activity
+        android:name=".toolbar.NoCarUiToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"
+        android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
+    <activity
+        android:name=".toolbar.OldToolbarActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"
+        android:theme="@style/Theme.CarUi"/>
+    <activity
+        android:name=".overlays.OverlayActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity">
+      <meta-data android:name="distractionOptimized" android:value="true"/>
+    </activity>
+    <activity
+        android:name=".widgets.WidgetActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+    <activity
+        android:name=".caruirecyclerview.CarUiListItemActivity"
+        android:exported="false"
+        android:parentActivityName=".MainActivity"/>
+
+    <service
+        android:label="Current Activity Service"
+        android:exported="false"
+        android:name=".currentactivity.CurrentActivityService"/>
+    <service
+        android:label="Visible Bounds Simulator"
+        android:exported="false"
+        android:name=".VisibleBoundsSimulator"/>
+  </application>
+</manifest>
diff --git a/car-ui-lib/paintbooth/build.gradle b/car-ui-lib/paintbooth/build.gradle
new file mode 100644
index 0000000..94ab49e
--- /dev/null
+++ b/car-ui-lib/paintbooth/build.gradle
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 30
+    defaultConfig {
+        applicationId "com.android.car.ui.paintbooth"
+        minSdkVersion 28
+        targetSdkVersion 30
+        versionCode 1
+        versionName "1.0"
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest-gradle.xml'
+            java {
+                filter.excludes = [
+                        "com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java",
+                        "com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java",
+                ]
+            }
+        }
+    }
+}
+
+dependencies {
+    implementation project(':car-ui-lib')
+    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0'
+    api 'androidx.annotation:annotation:1.1.0'
+    api 'androidx.constraintlayout:constraintlayout:1.1.3'
+    api 'androidx.recyclerview:recyclerview:1.0.0'
+}
diff --git a/car-ui-lib/tests/paintbooth/gradlew b/car-ui-lib/paintbooth/gradlew
similarity index 100%
rename from car-ui-lib/tests/paintbooth/gradlew
rename to car-ui-lib/paintbooth/gradlew
diff --git a/car-ui-lib/tests/paintbooth/gradlew.bat b/car-ui-lib/paintbooth/gradlew.bat
similarity index 100%
rename from car-ui-lib/tests/paintbooth/gradlew.bat
rename to car-ui-lib/paintbooth/gradlew.bat
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/MainActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/MainActivity.java
new file mode 100644
index 0000000..02b8088
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/MainActivity.java
@@ -0,0 +1,332 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.Switch;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.paintbooth.caruirecyclerview.CarUiListItemActivity;
+import com.android.car.ui.paintbooth.caruirecyclerview.CarUiRecyclerViewActivity;
+import com.android.car.ui.paintbooth.caruirecyclerview.GridCarUiRecyclerViewActivity;
+import com.android.car.ui.paintbooth.currentactivity.CurrentActivityService;
+import com.android.car.ui.paintbooth.dialogs.DialogsActivity;
+import com.android.car.ui.paintbooth.overlays.OverlayActivity;
+import com.android.car.ui.paintbooth.preferences.PreferenceActivity;
+import com.android.car.ui.paintbooth.toolbar.NoCarUiToolbarActivity;
+import com.android.car.ui.paintbooth.toolbar.OldToolbarActivity;
+import com.android.car.ui.paintbooth.toolbar.ToolbarActivity;
+import com.android.car.ui.paintbooth.widgets.WidgetActivity;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Paint booth app
+ */
+public class MainActivity extends Activity implements InsetsChangedListener {
+
+    public static final String STOP_SERVICE = "com.android.car.ui.paintbooth.StopService";
+
+    /**
+     * List of all sample activities.
+     */
+    private final List<ListElement> mActivities = Arrays.asList(
+            new ServiceElement("Show foreground activities", CurrentActivityService.class),
+            new ServiceElement("Simulate Screen Bounds", VisibleBoundsSimulator.class),
+            new ActivityElement("Dialogs sample", DialogsActivity.class),
+            new ActivityElement("List sample", CarUiRecyclerViewActivity.class),
+            new ActivityElement("Grid sample", GridCarUiRecyclerViewActivity.class),
+            new ActivityElement("Preferences sample", PreferenceActivity.class),
+            new ActivityElement("Overlays", OverlayActivity.class),
+            new ActivityElement("Toolbar sample", ToolbarActivity.class),
+            new ActivityElement("Old toolbar sample", OldToolbarActivity.class),
+            new ActivityElement("No CarUiToolbar sample", NoCarUiToolbarActivity.class),
+            new ActivityElement("Widget sample", WidgetActivity.class),
+            new ActivityElement("ListItem sample", CarUiListItemActivity.class));
+
+    private abstract static class ViewHolder extends RecyclerView.ViewHolder {
+
+        ViewHolder(@NonNull View itemView) {
+            super(itemView);
+        }
+
+        public abstract void bind(ListElement element);
+    }
+
+    private class ActivityViewHolder extends ViewHolder {
+        private final Button mButton;
+
+        ActivityViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mButton = itemView.requireViewById(R.id.button);
+        }
+
+        @Override
+        public void bind(ListElement e) {
+            if (!(e instanceof ActivityElement)) {
+                throw new IllegalArgumentException("Expected an ActivityElement");
+            }
+            ActivityElement element = (ActivityElement) e;
+            mButton.setText(element.getText());
+            mButton.setOnClickListener(v ->
+                    startActivity(new Intent(itemView.getContext(), element.getActivity())));
+        }
+    }
+
+    private class ServiceViewHolder extends ViewHolder {
+        private final Switch mSwitch;
+
+        ServiceViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mSwitch = itemView.requireViewById(R.id.button);
+        }
+
+        @Override
+        public void bind(ListElement e) {
+            if (!(e instanceof ServiceElement)) {
+                throw new IllegalArgumentException("Expected an ActivityElement");
+            }
+            ServiceElement element = (ServiceElement) e;
+            mSwitch.setChecked(isServiceRunning(element.getService()));
+            mSwitch.setText(element.getText());
+            mSwitch.setOnClickListener(v -> {
+                Intent intent = new Intent(itemView.getContext(), element.getService());
+                if (isServiceRunning(element.getService())) {
+                    intent.setAction(STOP_SERVICE);
+                }
+                startForegroundService(intent);
+            });
+        }
+    }
+
+    private final RecyclerView.Adapter<ViewHolder> mAdapter =
+            new RecyclerView.Adapter<ViewHolder>() {
+                @NonNull
+                @Override
+                public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+                    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+                    if (viewType == ListElement.TYPE_ACTIVITY) {
+                        return new ActivityViewHolder(
+                                inflater.inflate(R.layout.list_item, parent, false));
+                    } else if (viewType == ListElement.TYPE_SERVICE) {
+                        return new ServiceViewHolder(
+                                inflater.inflate(R.layout.list_item_switch, parent, false));
+                    } else {
+                        throw new IllegalArgumentException("Unknown viewType: " + viewType);
+                    }
+                }
+
+                @Override
+                public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+                    holder.bind(mActivities.get(position));
+                }
+
+                @Override
+                public int getItemCount() {
+                    return mActivities.size();
+                }
+
+                @Override
+                public int getItemViewType(int position) {
+                    return mActivities.get(position).getType();
+                }
+            };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.car_ui_recycler_view_activity);
+
+        ToolbarController toolbar = CarUi.requireToolbar(this);
+        toolbar.setLogo(R.drawable.ic_launcher);
+        toolbar.setTitle(getTitle());
+
+        CarUiRecyclerView prv = findViewById(R.id.list);
+        prv.setAdapter(mAdapter);
+
+        initLeakCanary();
+    }
+
+    private void initLeakCanary() {
+        // This sets LeakCanary to report errors after a single leak instead of 5, and to ask for
+        // permission to use storage, which it needs to work.
+        //
+        // Equivalent to this non-reflection code:
+        //
+        // Config config = LeakCanary.INSTANCE.getConfig();
+        // LeakCanary.INSTANCE.setConfig(config.copy(config.getDumpHeap(),
+        //     config.getDumpHeapWhenDebugging(),
+        //     1,
+        //     config.getReferenceMatchers(),
+        //     config.getObjectInspectors(),
+        //     config.getOnHeapAnalyzedListener(),
+        //     config.getMetatadaExtractor(),
+        //     config.getComputeRetainedHeapSize(),
+        //     config.getMaxStoredHeapDumps(),
+        //     true,
+        //     config.getUseExperimentalLeakFinders()));
+        try {
+            Class<?> canaryClass = Class.forName("leakcanary.LeakCanary");
+            try {
+                Class<?> onHeapAnalyzedListenerClass =
+                        Class.forName("leakcanary.OnHeapAnalyzedListener");
+                Class<?> metadataExtractorClass = Class.forName("shark.MetadataExtractor");
+                Method getConfig = canaryClass.getMethod("getConfig");
+                Class<?> configClass = getConfig.getReturnType();
+                Method setConfig = canaryClass.getMethod("setConfig", configClass);
+                Method copy = configClass.getMethod("copy", boolean.class, boolean.class,
+                        int.class, List.class, List.class, onHeapAnalyzedListenerClass,
+                        metadataExtractorClass, boolean.class, int.class, boolean.class,
+                        boolean.class);
+
+                Object canary = canaryClass.getField("INSTANCE").get(null);
+                Object currentConfig = getConfig.invoke(canary);
+
+                Boolean dumpHeap = (Boolean) configClass
+                        .getMethod("getDumpHeap").invoke(currentConfig);
+                Boolean dumpHeapWhenDebugging = (Boolean) configClass
+                        .getMethod("getDumpHeapWhenDebugging").invoke(currentConfig);
+                List<?> referenceMatchers = (List<?>) configClass
+                        .getMethod("getReferenceMatchers").invoke(currentConfig);
+                List<?> objectInspectors = (List<?>) configClass
+                        .getMethod("getObjectInspectors").invoke(currentConfig);
+                Object onHeapAnalyzedListener = configClass
+                        .getMethod("getOnHeapAnalyzedListener").invoke(currentConfig);
+                // Yes, LeakCanary misspelled metadata
+                Object metadataExtractor = configClass
+                        .getMethod("getMetatadaExtractor").invoke(currentConfig);
+                Boolean computeRetainedHeapSize = (Boolean) configClass
+                        .getMethod("getComputeRetainedHeapSize").invoke(currentConfig);
+                Integer maxStoredHeapDumps = (Integer) configClass
+                        .getMethod("getMaxStoredHeapDumps").invoke(currentConfig);
+                Boolean useExperimentalLeakFinders = (Boolean) configClass
+                        .getMethod("getUseExperimentalLeakFinders").invoke(currentConfig);
+
+                setConfig.invoke(canary, copy.invoke(currentConfig,
+                        dumpHeap,
+                        dumpHeapWhenDebugging,
+                        1,
+                        referenceMatchers,
+                        objectInspectors,
+                        onHeapAnalyzedListener,
+                        metadataExtractor,
+                        computeRetainedHeapSize,
+                        maxStoredHeapDumps,
+                        true,
+                        useExperimentalLeakFinders));
+
+            } catch (ReflectiveOperationException e) {
+                Log.e("paintbooth", "Error initializing LeakCanary", e);
+                Toast.makeText(this, "Error initializing LeakCanary", Toast.LENGTH_LONG).show();
+            }
+        } catch (ClassNotFoundException e) {
+            // LeakCanary is not used in this build, do nothing.
+        }
+    }
+
+    private boolean isServiceRunning(Class<? extends Service> serviceClazz) {
+        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
+                Integer.MAX_VALUE)) {
+            if (serviceClazz.getName().equals(service.service.getClassName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        requireViewById(R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        requireViewById(android.R.id.content)
+                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+
+    private abstract static class ListElement {
+        static final int TYPE_ACTIVITY = 0;
+        static final int TYPE_SERVICE = 1;
+
+        private final String mText;
+
+        ListElement(String text) {
+            mText = text;
+        }
+
+        String getText() {
+            return mText;
+        }
+
+        abstract int getType();
+    }
+
+    private static class ActivityElement extends ListElement {
+        private final Class<? extends Activity> mActivityClass;
+
+        ActivityElement(String text, Class<? extends Activity> activityClass) {
+            super(text);
+            mActivityClass = activityClass;
+        }
+
+        Class<? extends Activity> getActivity() {
+            return mActivityClass;
+        }
+
+        @Override
+        int getType() {
+            return TYPE_ACTIVITY;
+        }
+    }
+
+    private static class ServiceElement extends ListElement {
+        private final Class<? extends Service> mServiceClass;
+
+        ServiceElement(String text, Class<? extends Service> serviceClass) {
+            super(text);
+            mServiceClass = serviceClass;
+        }
+
+        Class<? extends Service> getService() {
+            return mServiceClass;
+        }
+
+        @Override
+        int getType() {
+            return TYPE_SERVICE;
+        }
+    }
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/VisibleBoundsSimulator.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/VisibleBoundsSimulator.java
new file mode 100644
index 0000000..63a2aed
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/VisibleBoundsSimulator.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 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.car.ui.paintbooth;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.os.IBinder;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.core.app.NotificationCompat;
+
+/**
+ * To start the service:
+ * adb shell am start-foreground-service com.android.car.ui.paintbooth/.DisplayService
+ *
+ * To stop the service:
+ * adb shell am stopservice com.android.car.ui.paintbooth/.DisplayService
+ *
+ * When the service is started it will draw a overlay view on top of the screen displayed. This
+ * overlay comes from a SVG file that can be modified to take different shapes. This service will be
+ * used to display different screen styles from OEMs.
+ */
+public class VisibleBoundsSimulator extends Service {
+    private static final int FOREGROUND_SERVICE_ID = 222;
+    private View mContainer;
+
+    private WindowManager mWindowManager;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        throw new UnsupportedOperationException("Not yet implemented.");
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (MainActivity.STOP_SERVICE.equals(intent.getAction())) {
+            stopSelf();
+        }
+
+        return START_STICKY;
+    }
+
+    @Override
+    public void onCreate() {
+
+        Intent notificationIntent = new Intent(this, VisibleBoundsSimulator.class);
+
+        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+                notificationIntent, 0);
+
+        NotificationChannel channel = new NotificationChannel("DisplayService",
+                "Show overlay screen",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(channel);
+
+        Notification notification =
+                new NotificationCompat.Builder(this, "DisplayService")
+                        .setSmallIcon(R.drawable.ic_launcher)
+                        .setContentTitle("DisplayService")
+                        .setContentText("Show overlay screen")
+                        .setContentIntent(pendingIntent).build();
+
+        startForeground(FOREGROUND_SERVICE_ID, notification);
+        applyDisplayOverlay();
+    }
+
+    /**
+     * Creates a view overlay on top of a new window. The overlay gravity is set to left and
+     * bottom. If the width and height is not provided then the default is to take up the entire
+     * screen. Overlay will show bounds around the view and we can still click through the window.
+     */
+    private void applyDisplayOverlay() {
+        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
+
+        DisplayMetrics displayMetrics = new DisplayMetrics();
+
+        mWindowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
+        int screenHeight = displayMetrics.heightPixels;
+        int screenWidth = displayMetrics.widthPixels;
+        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                // WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY is a hidden api, so
+                // use its value here so we can still compile on gradle / google3
+                WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW + 26,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
+                PixelFormat.TRANSLUCENT);
+
+        params.packageName = this.getPackageName();
+        params.gravity = Gravity.BOTTOM | Gravity.LEFT;
+
+        Display display = mWindowManager.getDefaultDisplay();
+        Point size = new Point();
+        display.getSize(size);
+        int height = size.y;
+
+        params.x = 0;
+        // If the sysUI is showing and nav bar is taking up some space at the bottom we want to
+        // offset the height of the navBar so that the overlay starts from the bottom left.
+        params.y = -(screenHeight - height);
+
+        float overlayWidth = getApplicationContext().getResources().getDimension(
+                R.dimen.screen_shape_container_width);
+        float overlayHeight = getApplicationContext().getResources().getDimension(
+                R.dimen.screen_shape_container_height);
+
+
+        params.width = (int) (overlayWidth == 0 ? screenWidth : overlayHeight);
+        params.height = (int) (overlayHeight == 0 ? screenHeight : overlayHeight);
+        params.setTitle("Simulated display bound");
+
+        mContainer = inflater.inflate(R.layout.simulated_screen_shape_container, null);
+        mContainer.setLayoutParams(params);
+
+        mWindowManager.addView(mContainer, params);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mWindowManager.removeView(mContainer);
+        stopSelf();
+    }
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
new file mode 100644
index 0000000..1819427
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.caruirecyclerview;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiHeaderListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import java.util.ArrayList;
+
+/**
+ * Activity that shows {@link CarUiRecyclerView} with sample {@link CarUiContentListItem} entries
+ */
+public class CarUiListItemActivity extends Activity implements InsetsChangedListener {
+
+    private final ArrayList<CarUiListItem> mData = new ArrayList<>();
+    private CarUiListItemAdapter mAdapter;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.car_ui_recycler_view_activity);
+
+        ToolbarController toolbar = CarUi.requireToolbar(this);
+        toolbar.setTitle(getTitle());
+        toolbar.setState(Toolbar.State.SUBPAGE);
+
+        CarUiRecyclerView recyclerView = findViewById(R.id.list);
+        mAdapter = new CarUiListItemAdapter(generateSampleData());
+        recyclerView.setAdapter(mAdapter);
+    }
+
+    private ArrayList<CarUiListItem> generateSampleData() {
+        Context context = this;
+
+        CarUiHeaderListItem header = new CarUiHeaderListItem("First header");
+        mData.add(header);
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title");
+        item.setBody("Test body");
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test title with no body");
+        mData.add(item);
+
+        header = new CarUiHeaderListItem("Random header", "with header body");
+        mData.add(header);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setBody("Test body with no title");
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test Title");
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test Title");
+        item.setBody("Test body text");
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test Title -- with content icon");
+        item.setPrimaryIconType(CarUiContentListItem.IconType.CONTENT);
+        item.setIcon(getDrawable(R.drawable.ic_sample_logo));
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test Title");
+        item.setBody("With avatar icon.");
+        item.setIcon(getDrawable(R.drawable.ic_sample_logo));
+        item.setPrimaryIconType(CarUiContentListItem.IconType.AVATAR);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Test Title");
+        item.setBody("Displays toast on click");
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        item.setOnItemClickedListener(item1 -> {
+            Toast.makeText(context, "Item clicked", Toast.LENGTH_SHORT).show();
+        });
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        item.setTitle("Title -- Item with checkbox");
+        item.setBody("Will present toast on change of selection state.");
+        item.setOnCheckedChangeListener(
+                (listItem, isChecked) -> Toast.makeText(context,
+                        "Item checked state is: " + isChecked, Toast.LENGTH_SHORT).show());
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        item.setEnabled(false);
+        item.setTitle("Title -- Checkbox that is disabled");
+        item.setBody("Clicks should not have any affect");
+        item.setOnCheckedChangeListener(
+                (listItem, isChecked) -> Toast.makeText(context,
+                        "Item checked state is: " + isChecked, Toast.LENGTH_SHORT).show());
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        item.setBody("Body -- Item with switch  -- with click listener");
+        item.setOnItemClickedListener(item1 -> {
+            Toast.makeText(context, "Click on item with switch", Toast.LENGTH_SHORT).show();
+        });
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        item.setTitle("Title -- Item with checkbox");
+        item.setBody("Item is initially checked");
+        item.setChecked(true);
+        mData.add(item);
+
+        CarUiContentListItem radioItem1 = new CarUiContentListItem(
+                CarUiContentListItem.Action.RADIO_BUTTON);
+        CarUiContentListItem radioItem2 = new CarUiContentListItem(
+                CarUiContentListItem.Action.RADIO_BUTTON);
+
+        radioItem1.setTitle("Title -- Item with radio button");
+        radioItem1.setBody("Item is initially unchecked checked");
+        radioItem1.setChecked(false);
+        radioItem1.setOnCheckedChangeListener((listItem, isChecked) -> {
+            if (isChecked) {
+                radioItem2.setChecked(false);
+                mAdapter.notifyItemChanged(mData.indexOf(radioItem2));
+            }
+        });
+        mData.add(radioItem1);
+
+        radioItem2.setIcon(getDrawable(R.drawable.ic_launcher));
+        radioItem2.setTitle("Item is mutually exclusive with item above");
+        radioItem2.setChecked(true);
+        radioItem2.setOnCheckedChangeListener((listItem, isChecked) -> {
+            if (isChecked) {
+                radioItem1.setChecked(false);
+                mAdapter.notifyItemChanged(mData.indexOf(radioItem1));
+            }
+        });
+        mData.add(radioItem2);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        item.setTitle("Title");
+        item.setBody("Random body text -- with action divider");
+        item.setActionDividerVisible(true);
+        item.setSupplementalIcon(getDrawable(R.drawable.ic_launcher));
+        item.setChecked(true);
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
+        item.setIcon(getDrawable(R.drawable.ic_launcher));
+        item.setTitle("Null supplemental icon");
+        item.setChecked(true);
+        mData.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
+        item.setTitle("Supplemental icon with listener");
+        item.setSupplementalIcon(getDrawable(R.drawable.ic_launcher),
+                v -> Toast.makeText(context, "Clicked supplemental icon",
+                        Toast.LENGTH_SHORT).show());
+        item.setChecked(true);
+        mData.add(item);
+
+        return mData;
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        requireViewById(R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        requireViewById(android.R.id.content)
+                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java
new file mode 100644
index 0000000..b7032c0
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.caruirecyclerview;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import java.util.ArrayList;
+
+/**
+ * Activity that shows CarUiRecyclerView example with sample data.
+ */
+public class CarUiRecyclerViewActivity extends Activity implements InsetsChangedListener {
+    private final ArrayList<String> mData = new ArrayList<>();
+    private final int mDataToGenerate = 100;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.car_ui_recycler_view_activity);
+
+        ToolbarController toolbar = CarUi.requireToolbar(this);
+        toolbar.setTitle(getTitle());
+        toolbar.setState(Toolbar.State.SUBPAGE);
+
+        CarUiRecyclerView recyclerView = findViewById(R.id.list);
+        recyclerView.setLayoutManager(new LinearLayoutManager(this));
+
+        RecyclerViewAdapter adapter = new RecyclerViewAdapter(generateSampleData());
+        recyclerView.setAdapter(adapter);
+    }
+
+    private ArrayList<String> generateSampleData() {
+        for (int i = 0; i <= mDataToGenerate; i++) {
+            mData.add("data" + i);
+        }
+        return mData;
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        requireViewById(R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        requireViewById(android.R.id.content)
+                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+}
+
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java
new file mode 100644
index 0000000..5d51d4c
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.caruirecyclerview;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import java.util.ArrayList;
+
+/** Activity that shows GridCarUiRecyclerView example with sample data. */
+public class GridCarUiRecyclerViewActivity extends Activity implements
+        InsetsChangedListener {
+    private final ArrayList<String> mData = new ArrayList<>();
+    private final int mDataToGenerate = 200;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.grid_car_ui_recycler_view_activity);
+
+        ToolbarController toolbar = CarUi.requireToolbar(this);
+        toolbar.setTitle(getTitle());
+        toolbar.setState(Toolbar.State.SUBPAGE);
+
+        CarUiRecyclerView recyclerView = findViewById(R.id.list);
+
+        RecyclerViewAdapter adapter = new RecyclerViewAdapter(generateSampleData());
+        recyclerView.setAdapter(adapter);
+    }
+
+    private ArrayList<String> generateSampleData() {
+        for (int i = 1; i <= mDataToGenerate; i++) {
+            mData.add("data" + i);
+        }
+        return mData;
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        requireViewById(R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        requireViewById(android.R.id.content)
+                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java
new file mode 100644
index 0000000..07dea21
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.caruirecyclerview;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.paintbooth.R;
+
+import java.util.ArrayList;
+
+/**
+ * Implementation of {@link RecyclerViewAdapter} that can be used with RecyclerViews.
+ */
+public class RecyclerViewAdapter extends
+        RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
+
+    private ArrayList<String> mData;
+
+    public RecyclerViewAdapter(ArrayList<String> data) {
+        this.mData = data;
+    }
+
+    @NonNull
+    @Override
+    public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        LayoutInflater inflator = LayoutInflater.from(parent.getContext());
+        View view = inflator.inflate(R.layout.car_ui_recycler_view_list_item, parent, false);
+        return new RecyclerViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
+        String title = mData.get(position);
+        holder.mTextTitle.setText(title);
+    }
+
+    @Override
+    public int getItemCount() {
+        return mData.size();
+    }
+
+
+    /**
+     * Holds views for each element in the list.
+     */
+    public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
+        TextView mTextTitle;
+
+        RecyclerViewHolder(@NonNull View itemView) {
+            super(itemView);
+            mTextTitle = itemView.findViewById(R.id.textTitle);
+        }
+    }
+}
+
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManager.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManager.java
new file mode 100644
index 0000000..e05fab8
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManager.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.currentactivity;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+/**
+ * Interface for wrappers around {@link android.app.ActivityTaskManager} so that we can exclude them
+ * from non-system builds like gradle and google3.
+ */
+interface ActivityTaskManager {
+
+    interface TaskStackListener {
+        void onTaskCreated(int taskId, ComponentName componentName);
+
+        void onTaskRemoved(int taskId);
+
+        void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo);
+
+        void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo);
+    }
+
+    List<RunningTaskInfo> getTasks(int maxNum) throws RemoteException;
+
+    void registerTaskStackListener(TaskStackListener listener) throws RemoteException;
+
+    void unregisterTaskStackListener(TaskStackListener listener) throws RemoteException;
+
+    final class ActivityTaskManagerStub implements ActivityTaskManager {
+        @Override
+        public List<RunningTaskInfo> getTasks(int num) throws RemoteException {
+            throw new RemoteException("ActivityTaskManager is not available");
+        }
+
+        @Override
+        public void registerTaskStackListener(TaskStackListener listener) throws RemoteException {
+            throw new RemoteException("ActivityTaskManager is not available");
+        }
+
+        @Override
+        public void unregisterTaskStackListener(TaskStackListener listener) throws RemoteException {
+            throw new RemoteException("ActivityTaskManager is not available");
+        }
+    }
+
+    @NonNull
+    static ActivityTaskManager getService() {
+        try {
+            Class<?> clazz = Class.forName(
+                    "com.android.car.ui.paintbooth.currentactivity.ActivityTaskManagerImpl");
+            Constructor<?> constructor = clazz.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            return (ActivityTaskManager) constructor.newInstance();
+        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException
+                | NoSuchMethodException | InvocationTargetException e) {
+            Log.e("paintbooth", "ActivityTaskManager is not available", e);
+            return new ActivityTaskManagerStub();
+        }
+    }
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java
new file mode 100644
index 0000000..8adbdad
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/ActivityTaskManagerImpl.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.currentactivity;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.IActivityTaskManager;
+import android.content.ComponentName;
+import android.os.RemoteException;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is a wrapper around {@link android.app.ActivityTaskManager} that is excluded from
+ * the gradle and google3 builds.
+ */
+class ActivityTaskManagerImpl implements ActivityTaskManager {
+
+    IActivityTaskManager mActivityTaskManager = android.app.ActivityTaskManager.getService();
+
+    Map<TaskStackListener, android.app.TaskStackListener> mListenerMapping = new HashMap<>();
+
+    @Override
+    public List<RunningTaskInfo> getTasks(int maxNum) throws RemoteException {
+        return mActivityTaskManager.getTasks(maxNum);
+    }
+
+    @Override
+    public void registerTaskStackListener(TaskStackListener listener) throws RemoteException {
+        mListenerMapping.put(listener, new android.app.TaskStackListener() {
+            @Override
+            public void onTaskCreated(int taskId, ComponentName componentName) {
+                listener.onTaskCreated(taskId, componentName);
+            }
+
+            @Override
+            public void onTaskRemoved(int taskId) {
+                listener.onTaskRemoved(taskId);
+            }
+
+            @Override
+            public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
+                listener.onTaskDescriptionChanged(taskInfo);
+            }
+
+            @Override
+            public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+                listener.onTaskMovedToFront(taskInfo);
+            }
+        });
+
+        mActivityTaskManager.registerTaskStackListener(mListenerMapping.get(listener));
+    }
+
+    @Override
+    public void unregisterTaskStackListener(TaskStackListener listener) throws RemoteException {
+        mActivityTaskManager.unregisterTaskStackListener(mListenerMapping.get(listener));
+        mListenerMapping.remove(listener);
+    }
+
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/CurrentActivityService.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/CurrentActivityService.java
new file mode 100644
index 0000000..3c87f62
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/currentactivity/CurrentActivityService.java
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.currentactivity;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.core.app.NotificationCompat;
+import androidx.core.content.ContextCompat;
+
+import com.android.car.ui.paintbooth.MainActivity;
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.paintbooth.currentactivity.ActivityTaskManager.TaskStackListener;
+
+import java.util.List;
+
+/**
+ * To start the service:
+ * adb shell am start-foreground-service -n com.android.car.ui.paintbooth/.CurrentActivityService
+ *
+ * To stop the service:
+ * adb shell am start-foreground-service -n com.android.car.ui.paintbooth/.CurrentActivityService -a
+ * com.android.car.ui.paintbooth.StopService
+ */
+public class CurrentActivityService extends Service {
+    private static final int FOREGROUND_SERVICE_ID = 111;
+
+    private WindowManager mWindowManager;
+    private TextView mTextView;
+    private Handler mHandler;
+
+    @Override
+    public void onCreate() {
+        mHandler = new Handler(Looper.getMainLooper());
+
+        if (ContextCompat.checkSelfPermission(this, "android.permission.REAL_GET_TASKS")
+                != PackageManager.PERMISSION_GRANTED) {
+            Toast.makeText(this, "android.permission.REAL_GET_TASKS is not granted!",
+                    Toast.LENGTH_LONG).show();
+        }
+
+        Intent notificationIntent = new Intent(this, CurrentActivityService.class);
+
+        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+                notificationIntent, 0);
+
+        NotificationChannel channel = new NotificationChannel("CurrentActivityService",
+                "Show current activity",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(channel);
+
+        Notification notification =
+                new NotificationCompat.Builder(this, "CurrentActivityService")
+                        .setSmallIcon(R.drawable.ic_launcher)
+                        .setContentTitle("CurrentActivityService")
+                        .setContentText("Show current activity")
+                        .setContentIntent(pendingIntent).build();
+
+        startForeground(FOREGROUND_SERVICE_ID, notification);
+
+        try {
+            ActivityTaskManager.getService().registerTaskStackListener(mTaskStackListener);
+        } catch (RemoteException e) {
+            Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
+        }
+
+        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
+        final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
+                PixelFormat.TRANSLUCENT);
+
+        mTextView = new TextView(this);
+        layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
+        layoutParams.x = 0;
+        layoutParams.y = 100;
+        mTextView.setLayoutParams(layoutParams);
+        mTextView.setBackgroundColor(Color.argb(50, 0, 255, 0));
+
+        mTextView.setOnTouchListener(new View.OnTouchListener() {
+
+            private int mInitialX = 0;
+            private int mInitialY = 0;
+            private float mInitialTouchX;
+            private float mInitialTouchY;
+
+            @Override
+            public boolean onTouch(View view, MotionEvent event) {
+                switch (event.getAction() & MotionEvent.ACTION_MASK) {
+                    case MotionEvent.ACTION_DOWN:
+                        mInitialX = layoutParams.x;
+                        mInitialY = layoutParams.y;
+                        mInitialTouchX = event.getRawX();
+                        mInitialTouchY = event.getRawY();
+                        break;
+                    case MotionEvent.ACTION_MOVE:
+                        WindowManager.LayoutParams layoutParams =
+                                (WindowManager.LayoutParams) view.getLayoutParams();
+                        layoutParams.x = mInitialX + (int) (event.getRawX() - mInitialTouchX);
+                        layoutParams.y = mInitialY + (int) (event.getRawY() - mInitialTouchY);
+                        mWindowManager.updateViewLayout(view, layoutParams);
+                        return true;
+                    default:
+                        break;
+                }
+
+                return false;
+            }
+        });
+
+        try {
+            mWindowManager.addView(mTextView, layoutParams);
+        } catch (RuntimeException e) {
+            Toast.makeText(this, "Couldn't display overlay", Toast.LENGTH_SHORT)
+                .show();
+        }
+
+        showCurrentTask();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (MainActivity.STOP_SERVICE.equals(intent.getAction())) {
+            stopSelf();
+        }
+
+        return START_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        mHandler.removeCallbacksAndMessages(null);
+        mWindowManager.removeView(mTextView);
+        try {
+            ActivityTaskManager.getService().unregisterTaskStackListener(mTaskStackListener);
+        } catch (RemoteException e) {
+            Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
+        }
+    }
+
+    /**
+     * This requires system permissions or else it will only fetch the current app and the launcher
+     * app
+     */
+    private void showCurrentTask() {
+        try {
+            List<ActivityManager.RunningTaskInfo> tasks =
+                    ActivityTaskManager.getService().getTasks(1);
+            if (!tasks.isEmpty()) {
+                updateComponentName(tasks.get(0).topActivity);
+            }
+        } catch (RemoteException e) {
+            Toast.makeText(this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
+        }
+    }
+
+    private void updateComponentName(ComponentName componentName) {
+        mHandler.post(() -> {
+            if (mTextView != null && componentName != null) {
+                mTextView.setText(componentName.flattenToShortString().replace('/', '\n'));
+            }
+        });
+    }
+
+    private final TaskStackListener mTaskStackListener = new TaskStackListener() {
+        @Override
+        public void onTaskCreated(int taskId, ComponentName componentName) {
+            updateComponentName(componentName);
+        }
+
+        @Override
+        public void onTaskRemoved(int taskId) {
+            showCurrentTask();
+        }
+
+        @Override
+        public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
+            updateComponentName(taskInfo.topActivity);
+        }
+
+        @Override
+        public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+            updateComponentName(taskInfo.topActivity);
+        }
+    };
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java
new file mode 100644
index 0000000..fd70730
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.dialogs;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.AlertDialogBuilder;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
+import com.android.car.ui.recyclerview.CarUiRadioButtonListItem;
+import com.android.car.ui.recyclerview.CarUiRadioButtonListItemAdapter;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Activity that shows different dialogs from the device default theme.
+ */
+public class DialogsActivity extends Activity implements InsetsChangedListener {
+
+    private final List<Pair<Integer, View.OnClickListener>> mButtons = new ArrayList<>();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.car_ui_recycler_view_activity);
+        ToolbarController toolbar = CarUi.requireToolbar(this);
+        toolbar.setTitle(getTitle());
+        toolbar.setState(Toolbar.State.SUBPAGE);
+
+        mButtons.add(Pair.create(R.string.dialog_show_dialog,
+                v -> showDialog()));
+        mButtons.add(Pair.create(R.string.dialog_show_dialog_icon,
+                v -> showDialogWithIcon()));
+        mButtons.add(Pair.create(R.string.dialog_show_dialog_edit,
+                v -> showDialogWithTextBox()));
+        mButtons.add(Pair.create(R.string.dialog_show_dialog_only_positive,
+                v -> showDialogWithOnlyPositiveButton()));
+        mButtons.add(Pair.create(R.string.dialog_show_dialog_no_button,
+                v -> showDialogWithNoButtonProvided()));
+        mButtons.add(Pair.create(R.string.dialog_show_dialog_checkbox,
+                v -> showDialogWithCheckbox()));
+        mButtons.add(Pair.create(R.string.dialog_show_dialog_no_title,
+                v -> showDialogWithoutTitle()));
+        mButtons.add(Pair.create(R.string.dialog_show_toast,
+                v -> showToast()));
+        mButtons.add(Pair.create(R.string.dialog_show_subtitle,
+                v -> showDialogWithSubtitle()));
+        mButtons.add(Pair.create(R.string.dialog_show_subtitle_and_icon,
+                v -> showDialogWithSubtitleAndIcon()));
+        mButtons.add(Pair.create(R.string.dialog_show_long_subtitle_and_icon,
+                v -> showDialogWithLongSubtitleAndIcon()));
+        mButtons.add(Pair.create(R.string.dialog_show_single_choice,
+                v -> showDialogWithSingleChoiceItems()));
+        mButtons.add(Pair.create(R.string.dialog_show_list_items_without_default_button,
+                v -> showDialogWithListItemsWithoutDefaultButton()));
+        mButtons.add(Pair.create(R.string.dialog_show_permission_dialog,
+                v -> showPermissionDialog()));
+        mButtons.add(Pair.create(R.string.dialog_show_multi_permission_dialog,
+                v -> showMultiPermissionDialog()));
+        mButtons.add(Pair.create(R.string.dialog_show_foreground_permission_dialog,
+                v -> showForegroundPermissionDialog()));
+        mButtons.add(Pair.create(R.string.dialog_show_background_permission_dialog,
+                v -> showBackgroundPermissionDialog()));
+
+        CarUiRecyclerView recyclerView = requireViewById(R.id.list);
+        recyclerView.setAdapter(mAdapter);
+    }
+
+    private void showDialog() {
+        new AlertDialogBuilder(this)
+                .setTitle("Standard Alert Dialog")
+                .setMessage("With a message to show.")
+                .setNeutralButton("NEUTRAL", (dialogInterface, which) -> {
+                })
+                .setPositiveButton("OK", (dialogInterface, which) -> {
+                })
+                .setNegativeButton("CANCEL", (dialogInterface, which) -> {
+                })
+                .show();
+    }
+
+    private void showDialogWithIcon() {
+        new AlertDialogBuilder(this)
+                .setTitle("Alert dialog with icon")
+                .setMessage("The message body of the alert")
+                .setIcon(R.drawable.ic_tracklist)
+                .show();
+    }
+
+    private void showDialogWithNoButtonProvided() {
+        new AlertDialogBuilder(this)
+                .setTitle("Standard Alert Dialog")
+                .show();
+    }
+
+    private void showDialogWithCheckbox() {
+        new AlertDialogBuilder(this)
+                .setTitle("Custom Dialog Box")
+                .setMultiChoiceItems(
+                        new CharSequence[]{"I am a checkbox"},
+                        new boolean[]{false},
+                        (dialog, which, isChecked) -> {
+                        })
+                .setPositiveButton("OK", (dialogInterface, which) -> {
+                })
+                .setNegativeButton("CANCEL", (dialogInterface, which) -> {
+                })
+                .show();
+    }
+
+    private void showDialogWithTextBox() {
+        new AlertDialogBuilder(this)
+                .setTitle("Standard Alert Dialog")
+                .setEditBox("Edit me please", null, null)
+                .setPositiveButton("OK", (dialogInterface, i) -> {
+                })
+                .show();
+    }
+
+    private void showDialogWithOnlyPositiveButton() {
+        new AlertDialogBuilder(this)
+                .setTitle("Standard Alert Dialog").setMessage("With a message to show.")
+                .setPositiveButton("OK", (dialogInterface, i) -> {
+                })
+                .show();
+    }
+
+    private void showDialogWithoutTitle() {
+        new AlertDialogBuilder(this)
+                .setMessage("I dont have a title.")
+                .setPositiveButton("OK", (dialogInterface, i) -> {
+                })
+                .setNegativeButton("CANCEL", (dialogInterface, which) -> {
+                })
+                .show();
+    }
+
+    private void showToast() {
+        Toast.makeText(this, "Toast message looks like this", Toast.LENGTH_LONG).show();
+    }
+
+    private void showDialogWithSubtitle() {
+        new AlertDialogBuilder(this)
+                .setTitle("My Title!")
+                .setSubtitle("My Subtitle!")
+                .setMessage("My Message!")
+                .show();
+    }
+
+    private void showDialogWithSingleChoiceItems() {
+        ArrayList<CarUiRadioButtonListItem> data = new ArrayList<>();
+
+        CarUiRadioButtonListItem item = new CarUiRadioButtonListItem();
+        item.setTitle("First item");
+        data.add(item);
+
+        item = new CarUiRadioButtonListItem();
+        item.setTitle("Second item");
+        data.add(item);
+
+        item = new CarUiRadioButtonListItem();
+        item.setTitle("Third item");
+        data.add(item);
+
+        new AlertDialogBuilder(this)
+                .setTitle("Select one option.")
+                .setSubtitle("Ony one option may be selected at a time")
+                .setSingleChoiceItems(new CarUiRadioButtonListItemAdapter(data), null)
+                .show();
+    }
+
+
+    private void showDialogWithListItemsWithoutDefaultButton() {
+        ArrayList<CarUiContentListItem> data = new ArrayList<>();
+        AlertDialog[] dialog = new AlertDialog[1];
+
+        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("First item");
+        item.setOnItemClickedListener(i -> dialog[0].dismiss());
+        data.add(item);
+
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Second item");
+        item.setOnItemClickedListener(i -> dialog[0].dismiss());
+        data.add(item);
+
+        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+        item.setTitle("Third item");
+        item.setOnItemClickedListener(i -> dialog[0].dismiss());
+        data.add(item);
+
+        dialog[0] = new AlertDialogBuilder(this)
+                .setTitle("Select one option.")
+                .setSubtitle("Ony one option may be selected at a time")
+                .setAdapter(new CarUiListItemAdapter(data))
+                .setAllowDismissButton(false)
+                .show();
+    }
+
+    private void showDialogWithSubtitleAndIcon() {
+        new AlertDialogBuilder(this)
+                .setTitle("My Title!")
+                .setSubtitle("My Subtitle!")
+                .setMessage("My Message!")
+                .setIcon(R.drawable.ic_tracklist)
+                .show();
+    }
+
+    private void showDialogWithLongSubtitleAndIcon() {
+        new AlertDialogBuilder(this)
+                .setTitle("This is a very long title. It should likely span across "
+                            + "multiple lines or something. It shouldn't get cut off.")
+                .setSubtitle("This is a very long subtitle. It should likely span across "
+                        + "multiple lines or something. It shouldn't get cut off.")
+                .setMessage("My Message!")
+                .setIcon(R.drawable.ic_tracklist)
+                .show();
+    }
+
+    private void showPermissionDialog() {
+        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
+            Toast.makeText(this, "Permission already granted. Remove CAMERA permission from "
+                    + "Settings > All apps > PaintBooth", Toast.LENGTH_SHORT).show();
+            return;
+        }
+        requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
+    }
+
+    private void showMultiPermissionDialog() {
+        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
+                && checkSelfPermission(Manifest.permission.SEND_SMS)
+                    == PackageManager.PERMISSION_GRANTED
+                && checkSelfPermission(Manifest.permission.READ_CONTACTS)
+                    == PackageManager.PERMISSION_GRANTED) {
+            Toast.makeText(this, "Permissions are already granted. Remove CAMERA, SEND_SMS or "
+                    + "READ_CONTACTS permission from Settings > All apps > PaintBooth",
+                    Toast.LENGTH_SHORT).show();
+            return;
+        }
+        requestPermissions(new String[]{Manifest.permission.CAMERA,
+                Manifest.permission.READ_CONTACTS, Manifest.permission.SEND_SMS}, 1);
+    }
+
+    private void showForegroundPermissionDialog() {
+        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
+    }
+
+    private void showBackgroundPermissionDialog() {
+        requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 1);
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions,
+            int[] grantResults) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Permission ");
+        for (int i = 0; i < permissions.length; i++) {
+            sb.append(permissions[i]);
+            sb.append("=");
+            sb.append(grantResults[i] == PackageManager.PERMISSION_GRANTED ? "granted" : "denied");
+            sb.append("\n");
+        }
+        Toast.makeText(this, sb.toString(), Toast.LENGTH_SHORT).show();
+    }
+
+    private static class ViewHolder extends RecyclerView.ViewHolder {
+
+        private final Button mButton;
+
+        ViewHolder(View itemView) {
+            super(itemView);
+            mButton = itemView.requireViewById(R.id.button);
+        }
+
+        public void bind(Integer title, View.OnClickListener listener) {
+            mButton.setText(title);
+            mButton.setOnClickListener(listener);
+        }
+    }
+
+    private final RecyclerView.Adapter<ViewHolder> mAdapter =
+            new RecyclerView.Adapter<ViewHolder>() {
+                @Override
+                public int getItemCount() {
+                    return mButtons.size();
+                }
+
+                @Override
+                public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
+                    View item =
+                            LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,
+                                    parent, false);
+                    return new ViewHolder(item);
+                }
+
+                @Override
+                public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+                    Pair<Integer, View.OnClickListener> pair = mButtons.get(position);
+                    holder.bind(pair.first, pair.second);
+                }
+            };
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        requireViewById(R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        requireViewById(android.R.id.content)
+                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/overlays/OverlayActivity.java
similarity index 100%
rename from car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayActivity.java
rename to car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/overlays/OverlayActivity.java
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManager.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/overlays/OverlayManager.java
similarity index 100%
rename from car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManager.java
rename to car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/overlays/OverlayManager.java
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java
new file mode 100644
index 0000000..3a27534
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.overlays;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.om.IOverlayManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import androidx.annotation.NonNull;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * OverlayManager implementation. Exclude this file when building Paintbooth outside of the system
+ * image.
+ */
+public class OverlayManagerImpl implements OverlayManager {
+    private final IOverlayManager mOverlayManager;
+
+    public OverlayManagerImpl(Context context) {
+        mOverlayManager = IOverlayManager.Stub.asInterface(
+                ServiceManager.getService(Context.OVERLAY_SERVICE));
+    }
+
+    private OverlayInfo convertOverlayInfo(android.content.om.OverlayInfo info) {
+        return new OverlayInfo() {
+            @NonNull
+            @Override
+            public String getPackageName() {
+                return info.packageName;
+            }
+
+            @Override
+            public boolean isEnabled() {
+                return info.state == android.content.om.OverlayInfo.STATE_ENABLED;
+            }
+        };
+    }
+
+    @Override
+    @NonNull
+    public Map<String, List<OverlayManager.OverlayInfo>> getOverlays() throws RemoteException {
+        Map<String, List<android.content.om.OverlayInfo>> overlays =
+                mOverlayManager.getAllOverlays(ActivityManager.getCurrentUser());
+        return overlays.entrySet()
+                .stream()
+                .collect(toMap(Map.Entry::getKey, e -> e.getValue()
+                        .stream()
+                        .map(this::convertOverlayInfo)
+                        .collect(toList())));
+    }
+
+    @Override
+    public void applyOverlay(@NonNull String packageName, boolean enable) throws RemoteException {
+        mOverlayManager.setEnabled(packageName, enable, ActivityManager.getCurrentUser());
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/preferences/PreferenceActivity.java
similarity index 100%
rename from car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceActivity.java
rename to car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/preferences/PreferenceActivity.java
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
new file mode 100644
index 0000000..e9f990d
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package com.android.car.ui.paintbooth.preferences;
+
+import android.os.Bundle;
+
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.preference.CarUiPreference;
+import com.android.car.ui.preference.PreferenceFragment;
+
+/**
+ * Fragment to load preferences
+ */
+public class PreferenceDemoFragment extends PreferenceFragment {
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        // Load the preferences from an XML resource
+        setPreferencesFromResource(R.xml.preference_samples, rootKey);
+        CarUiPreference preferenceDisabledWithoutRipple = findPreference(
+                "preference_disabled_without_ripple");
+        preferenceDisabledWithoutRipple.setEnabled(false);
+        preferenceDisabledWithoutRipple.setMessageToShowWhenDisabledPreferenceClicked(
+                "I am disabled because...");
+        preferenceDisabledWithoutRipple.setShouldShowRippleOnDisabledPreference(false);
+
+        CarUiPreference preferenceDisabledWithRipple = findPreference(
+                "preference_disabled_with_ripple");
+        preferenceDisabledWithRipple.setEnabled(false);
+        preferenceDisabledWithRipple.setMessageToShowWhenDisabledPreferenceClicked(
+                "I am disabled because...");
+        preferenceDisabledWithRipple.setShouldShowRippleOnDisabledPreference(true);
+    }
+}
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/NoCarUiToolbarActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/NoCarUiToolbarActivity.java
new file mode 100644
index 0000000..39e1a18
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/NoCarUiToolbarActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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.car.ui.paintbooth.toolbar;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import com.android.car.ui.paintbooth.R;
+
+/**
+ * Activity that uses androidX toolbar. This is a blank activity used for testing.
+ */
+public class NoCarUiToolbarActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.no_car_ui_toolbar_activity);
+        Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
+        setSupportActionBar(myToolbar);
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        getSupportActionBar().setDisplayShowHomeEnabled(true);
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/OldToolbarActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/OldToolbarActivity.java
similarity index 100%
rename from car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/OldToolbarActivity.java
rename to car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/OldToolbarActivity.java
diff --git a/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
new file mode 100644
index 0000000..f32818a
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
@@ -0,0 +1,452 @@
+/*
+ * 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.
+ */
+package com.android.car.ui.paintbooth.toolbar;
+
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.AlertDialogBuilder;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.paintbooth.R;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
+import com.android.car.ui.toolbar.MenuItem;
+import com.android.car.ui.toolbar.TabLayout;
+import com.android.car.ui.toolbar.Toolbar;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ToolbarActivity extends AppCompatActivity implements InsetsChangedListener {
+
+    private List<MenuItem> mMenuItems = new ArrayList<>();
+    private List<Pair<CharSequence, View.OnClickListener>> mButtons = new ArrayList<>();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(getLayout());
+
+        ToolbarController toolbarNonFinal = CarUi.getToolbar(this);
+        if (toolbarNonFinal == null) {
+            toolbarNonFinal = requireViewById(R.id.toolbar);
+        }
+        ToolbarController toolbar = toolbarNonFinal;
+        toolbar.setTitle(getTitle());
+        toolbar.setState(Toolbar.State.SUBPAGE);
+        toolbar.setLogo(R.drawable.ic_launcher);
+        toolbar.registerOnBackListener(
+                () -> {
+                    if (toolbar.getState() == Toolbar.State.SEARCH
+                            || toolbar.getState() == Toolbar.State.EDIT) {
+                        toolbar.setState(Toolbar.State.SUBPAGE);
+                        return true;
+                    }
+                    return false;
+                });
+
+        mMenuItems.add(MenuItem.builder(this)
+                .setToSearch()
+                .setOnClickListener(i -> toolbar.setState(Toolbar.State.SEARCH))
+                .build());
+
+        toolbar.setMenuItems(mMenuItems);
+
+        mButtons.add(Pair.create("Toggle progress bar", v -> {
+            toolbar.getProgressBar().setVisible(!toolbar.getProgressBar().isVisible());
+        }));
+
+        mButtons.add(Pair.create("Change title", v ->
+                toolbar.setTitle(toolbar.getTitle() + " X")));
+
+        mButtons.add(Pair.create("Add/Change subtitle", v -> {
+            CharSequence subtitle = toolbar.getSubtitle();
+            if (TextUtils.isEmpty(subtitle)) {
+                toolbar.setSubtitle("Subtitle");
+            } else {
+                toolbar.setSubtitle(subtitle + " X");
+            }
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_set_xml_resource), v -> {
+            mMenuItems.clear();
+            toolbar.setMenuItems(R.xml.menuitems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_icon), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setToSettings()
+                    .setOnClickListener(i -> Toast.makeText(this, "Clicked",
+                            Toast.LENGTH_SHORT).show())
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_untined_icon), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setIcon(R.drawable.ic_tracklist)
+                    .setTinted(false)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_switch), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setCheckable()
+                    .setOnClickListener(
+                            i ->
+                                    Toast.makeText(this,
+                                            "Checked? " + i.isChecked(),
+                                            Toast.LENGTH_SHORT)
+                                            .show())
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_text), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setTitle("Baz")
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_icon_text), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setIcon(R.drawable.ic_tracklist)
+                    .setTitle("Bar")
+                    .setShowIconAndTitle(true)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_untinted_icon_and_text), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setIcon(R.drawable.ic_tracklist)
+                    .setTitle("Bar")
+                    .setShowIconAndTitle(true)
+                    .setTinted(false)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_activatable), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setIcon(R.drawable.ic_tracklist)
+                    .setActivatable()
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_morphing), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setTitle("Become icon")
+                    .setOnClickListener(i ->
+                            i.setIcon(i.getIcon() == null ? R.drawable.ic_tracklist : 0))
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        Mutable<Integer> overflowCounter = new Mutable<>(1);
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_overflow), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setTitle("Foo " + overflowCounter.value)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+            overflowCounter.value++;
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_overflow_switch), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setTitle("Foo " + overflowCounter.value)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this,
+                                    i.isChecked() ? "Checked" : "Unchecked",
+                                    Toast.LENGTH_SHORT)
+                                    .show())
+                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
+                    .setCheckable()
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+            overflowCounter.value++;
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_icon_text_overflow), v -> {
+            mMenuItems.add(MenuItem.builder(this)
+                    .setIcon(R.drawable.ic_tracklist)
+                    .setTitle("Bar")
+                    .setShowIconAndTitle(true)
+                    .setOnClickListener(
+                            i -> Toast.makeText(this, "Clicked",
+                                    Toast.LENGTH_SHORT).show())
+                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
+                    .build());
+            toolbar.setMenuItems(mMenuItems);
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_visibility),
+                v -> getMenuItem(item -> item.setVisible(!item.isVisible()))));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_enable),
+                v -> getMenuItem(item -> item.setEnabled(!item.isEnabled()))));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_perform_click),
+                v -> getMenuItem(MenuItem::performClick)));
+
+        final Drawable altIcon = getDrawable(R.drawable.ic_cut);
+        Map<MenuItem, Drawable> iconBackups = new HashMap<>();
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_icon), v ->
+                getMenuItem(item -> {
+                    Drawable currentIcon = item.getIcon();
+                    Drawable newIcon = altIcon;
+                    if (iconBackups.containsKey(item)) {
+                        newIcon = iconBackups.get(item);
+                    }
+                    item.setIcon(newIcon);
+                    iconBackups.put(item, currentIcon);
+                })));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_show_while_search), v ->
+                toolbar.setShowMenuItemsWhileSearching(
+                        !toolbar.getShowMenuItemsWhileSearching())));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_cycle_nav_button), v -> {
+            Toolbar.NavButtonMode mode = toolbar.getNavButtonMode();
+            if (mode == Toolbar.NavButtonMode.BACK) {
+                toolbar.setNavButtonMode(Toolbar.NavButtonMode.CLOSE);
+            } else if (mode == Toolbar.NavButtonMode.CLOSE) {
+                toolbar.setNavButtonMode(Toolbar.NavButtonMode.DOWN);
+            } else {
+                toolbar.setNavButtonMode(Toolbar.NavButtonMode.BACK);
+            }
+        }));
+
+        Mutable<Boolean> hasLogo = new Mutable<>(true);
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_logo), v -> {
+            toolbar.setLogo(hasLogo.value ? 0 : R.drawable.ic_launcher);
+            hasLogo.value = !hasLogo.value;
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_cycle_state), v -> {
+            if (toolbar.getState() == Toolbar.State.SUBPAGE) {
+                toolbar.setState(Toolbar.State.HOME);
+            } else if (toolbar.getState() == Toolbar.State.HOME) {
+                toolbar.setState(Toolbar.State.EDIT);
+            } else {
+                toolbar.setState(Toolbar.State.SUBPAGE);
+            }
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_search_hint), v -> {
+            if (toolbar.getSearchHint().toString().contentEquals("Foo")) {
+                toolbar.setSearchHint("Bar");
+            } else {
+                toolbar.setSearchHint("Foo");
+            }
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_background),
+                v -> toolbar.setBackgroundShown(!toolbar.getBackgroundShown())));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_tab), v -> toolbar.addTab(
+                new TabLayout.Tab(getDrawable(R.drawable.ic_launcher), "Foo"))));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_add_tab_with_custom_text), v -> {
+            SimpleTextWatcher textWatcher = new SimpleTextWatcher();
+            new AlertDialogBuilder(this)
+                    .setEditBox(null, textWatcher, null)
+                    .setTitle("Enter the text for the title")
+                    .setPositiveButton("Ok", (dialog, which) ->
+                            toolbar.addTab(
+                                    new TabLayout.Tab(
+                                            getDrawable(
+                                                    R.drawable.ic_launcher),
+                                            textWatcher.getText())))
+                    .show();
+        }));
+
+        mButtons.add(Pair.create(getString(R.string.toolbar_show_tabs_in_subpage), v ->
+                toolbar.setShowTabsInSubpage(!toolbar.getShowTabsInSubpage())));
+
+        Mutable<Boolean> showingLauncherIcon = new Mutable<>(false);
+        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_search_icon), v -> {
+            if (showingLauncherIcon.value) {
+                toolbar.setSearchIcon(null);
+            } else {
+                toolbar.setSearchIcon(R.drawable.ic_launcher);
+            }
+            showingLauncherIcon.value = !showingLauncherIcon.value;
+        }));
+
+        CarUiRecyclerView prv = requireViewById(R.id.list);
+        prv.setAdapter(mAdapter);
+    }
+
+    /** Override in subclasses to change the layout */
+    protected int getLayout() {
+        return R.layout.car_ui_recycler_view_activity;
+    }
+
+    @Override
+    public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        requireViewById(R.id.list)
+                .setPadding(0, insets.getTop(), 0, insets.getBottom());
+        requireViewById(android.R.id.content)
+                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
+    }
+
+    public void xmlMenuItemClicked(MenuItem item) {
+        Toast.makeText(this, "Xml item clicked! " + item.getTitle() + ", id: " + item.getId(),
+                Toast.LENGTH_SHORT).show();
+    }
+
+    private void getMenuItem(MenuItem.OnClickListener listener) {
+        if (mMenuItems.size() == 1) {
+            listener.onClick(mMenuItems.get(0));
+            return;
+        }
+
+        SimpleTextWatcher textWatcher = new SimpleTextWatcher();
+        new AlertDialogBuilder(this)
+                .setEditBox("", textWatcher, null, InputType.TYPE_CLASS_NUMBER)
+                .setTitle("Enter the index of the MenuItem")
+                .setPositiveButton("Ok", (dialog, which) -> {
+                    try {
+                        MenuItem item = mMenuItems.get(
+                                Integer.parseInt(textWatcher.getText()));
+                        listener.onClick(item);
+                    } catch (NumberFormatException | IndexOutOfBoundsException e) {
+                        Toast.makeText(this, "Invalid index \"" + textWatcher.getText()
+                                        + "\", valid range is 0 to " + (mMenuItems.size() - 1),
+                                Toast.LENGTH_LONG).show();
+                    }
+                }).show();
+    }
+
+    private static class ViewHolder extends RecyclerView.ViewHolder {
+
+        private final Button mButton;
+
+        ViewHolder(View itemView) {
+            super(itemView);
+            mButton = itemView.requireViewById(R.id.button);
+        }
+
+        public void bind(CharSequence title, View.OnClickListener listener) {
+            mButton.setText(title);
+            mButton.setOnClickListener(listener);
+        }
+    }
+
+    private final RecyclerView.Adapter<ViewHolder> mAdapter =
+            new RecyclerView.Adapter<ViewHolder>() {
+                @Override
+                public int getItemCount() {
+                    return mButtons.size();
+                }
+
+                @Override
+                public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
+                    View item =
+                            LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,
+                                    parent, false);
+                    return new ViewHolder(item);
+                }
+
+                @Override
+                public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+                    Pair<CharSequence, View.OnClickListener> pair = mButtons.get(position);
+                    holder.bind(pair.first, pair.second);
+                }
+            };
+
+    /**
+     * For changing values from lambdas
+     */
+    private static final class Mutable<E> {
+
+        public E value;
+
+        Mutable() {
+            value = null;
+        }
+
+        Mutable(E value) {
+            this.value = value;
+        }
+    }
+
+    /**
+     * Used for getting text from a dialog.
+     */
+    private static final class SimpleTextWatcher implements TextWatcher {
+
+        private String mValue;
+
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+            mValue = s.toString();
+        }
+
+        public String getText() {
+            return mValue;
+        }
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/widgets/WidgetActivity.java b/car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/widgets/WidgetActivity.java
similarity index 100%
rename from car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/widgets/WidgetActivity.java
rename to car-ui-lib/paintbooth/src/main/java/com/android/car/ui/paintbooth/widgets/WidgetActivity.java
diff --git a/car-ui-lib/paintbooth/src/main/res-public/values/public.xml b/car-ui-lib/paintbooth/src/main/res-public/values/public.xml
new file mode 100644
index 0000000..792aa8f
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res-public/values/public.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <public type="color" name="dialog_activity_background_color" id="0x7f050040" />
+</resources>
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/ic_cut.xml b/car-ui-lib/paintbooth/src/main/res/drawable/ic_cut.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/drawable/ic_cut.xml
rename to car-ui-lib/paintbooth/src/main/res/drawable/ic_cut.xml
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/ic_launcher.png b/car-ui-lib/paintbooth/src/main/res/drawable/ic_launcher.png
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/drawable/ic_launcher.png
rename to car-ui-lib/paintbooth/src/main/res/drawable/ic_launcher.png
Binary files differ
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/ic_sample_logo.png b/car-ui-lib/paintbooth/src/main/res/drawable/ic_sample_logo.png
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/drawable/ic_sample_logo.png
rename to car-ui-lib/paintbooth/src/main/res/drawable/ic_sample_logo.png
Binary files differ
diff --git a/car-ui-lib/paintbooth/src/main/res/drawable/ic_settings_gear.xml b/car-ui-lib/paintbooth/src/main/res/drawable/ic_settings_gear.xml
new file mode 100644
index 0000000..d1557f4
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/drawable/ic_settings_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2017 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.
+-->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0">
+    <path
+        android:fillColor="#fff"
+        android:pathData="M38.86,25.95c0.08,-0.64 0.14,-1.29 0.14,-1.95s-0.06,-1.31 -0.14,-1.95l4.23,-3.31c0.38,-0.3 0.49,-0.84 0.24,-1.28l-4,-6.93c-0.25,-0.43 -0.77,-0.61 -1.22,-0.43l-4.98,2.01c-1.03,-0.79 -2.16,-1.46 -3.38,-1.97L29,4.84c-0.09,-0.47 -0.5,-0.84 -1,-0.84h-8c-0.5,0 -0.91,0.37 -0.99,0.84l-0.75,5.3c-1.22,0.51 -2.35,1.17 -3.38,1.97L9.9,10.1c-0.45,-0.17 -0.97,0 -1.22,0.43l-4,6.93c-0.25,0.43 -0.14,0.97 0.24,1.28l4.22,3.31C9.06,22.69 9,23.34 9,24s0.06,1.31 0.14,1.95l-4.22,3.31c-0.38,0.3 -0.49,0.84 -0.24,1.28l4,6.93c0.25,0.43 0.77,0.61 1.22,0.43l4.98,-2.01c1.03,0.79 2.16,1.46 3.38,1.97l0.75,5.3c0.08,0.47 0.49,0.84 0.99,0.84h8c0.5,0 0.91,-0.37 0.99,-0.84l0.75,-5.3c1.22,-0.51 2.35,-1.17 3.38,-1.97l4.98,2.01c0.45,0.17 0.97,0 1.22,-0.43l4,-6.93c0.25,-0.43 0.14,-0.97 -0.24,-1.28l-4.22,-3.31zM24,31c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
+</vector>
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/ic_settings_wifi.xml b/car-ui-lib/paintbooth/src/main/res/drawable/ic_settings_wifi.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/drawable/ic_settings_wifi.xml
rename to car-ui-lib/paintbooth/src/main/res/drawable/ic_settings_wifi.xml
diff --git a/car-ui-lib/tests/paintbooth/res/drawable/ic_tracklist.xml b/car-ui-lib/paintbooth/src/main/res/drawable/ic_tracklist.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/drawable/ic_tracklist.xml
rename to car-ui-lib/paintbooth/src/main/res/drawable/ic_tracklist.xml
diff --git a/car-ui-lib/paintbooth/src/main/res/drawable/simulated_screen_shape.xml b/car-ui-lib/paintbooth/src/main/res/drawable/simulated_screen_shape.xml
new file mode 100644
index 0000000..569f098
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/drawable/simulated_screen_shape.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="100dp"
+        android:width="100dp"
+        android:viewportHeight="100"
+        android:viewportWidth="100">
+
+    <path
+        android:strokeWidth="1"
+        android:strokeColor="#0f0"
+        android:pathData="M 0,0 L 100,0 100,100 0,100 z" />
+
+</vector>
diff --git a/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_activity.xml b/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_activity.xml
new file mode 100644
index 0000000..89a73d8
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_activity.xml
@@ -0,0 +1,28 @@
+<?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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
+
+
diff --git a/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml b/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml
new file mode 100644
index 0000000..cce0cde
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2020 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.
+  -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:clipToPadding="false"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <com.android.car.ui.toolbar.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_list_item.xml b/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_list_item.xml
new file mode 100644
index 0000000..597ebcc
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/car_ui_recycler_view_list_item.xml
@@ -0,0 +1,31 @@
+<?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/paintbooth/src/main/res/layout/details_preference_widget.xml b/car-ui-lib/paintbooth/src/main/res/layout/details_preference_widget.xml
new file mode 100644
index 0000000..4f9fc41
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/details_preference_widget.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2018 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.
+-->
+
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:src="@drawable/ic_settings_gear"/>
diff --git a/car-ui-lib/paintbooth/src/main/res/layout/grid_car_ui_recycler_view_activity.xml b/car-ui-lib/paintbooth/src/main/res/layout/grid_car_ui_recycler_view_activity.xml
new file mode 100644
index 0000000..233c148
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/grid_car_ui_recycler_view_activity.xml
@@ -0,0 +1,29 @@
+<?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.
+  -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/car_ui_activity_background">
+    <com.android.car.ui.recyclerview.CarUiRecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:numOfColumns="4"
+        app:layoutStyle="grid"/>
+</FrameLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/list_item.xml b/car-ui-lib/paintbooth/src/main/res/layout/list_item.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/layout/list_item.xml
rename to car-ui-lib/paintbooth/src/main/res/layout/list_item.xml
diff --git a/car-ui-lib/paintbooth/src/main/res/layout/list_item_switch.xml b/car-ui-lib/paintbooth/src/main/res/layout/list_item_switch.xml
new file mode 100644
index 0000000..499f3e4
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/list_item_switch.xml
@@ -0,0 +1,28 @@
+<?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.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+  <Switch
+      android:id="@+id/button"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_centerHorizontal="true"
+      android:textSize="25sp"
+      android:layout_marginTop="20dp"/>
+</RelativeLayout>
diff --git a/car-ui-lib/paintbooth/src/main/res/layout/no_car_ui_toolbar_activity.xml b/car-ui-lib/paintbooth/src/main/res/layout/no_car_ui_toolbar_activity.xml
new file mode 100644
index 0000000..ce2acb4
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/no_car_ui_toolbar_activity.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+~ Copyright (C) 2020 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="match_parent"
+    android:background="@drawable/car_ui_activity_background"
+    android:orientation="vertical">
+    <androidx.appcompat.widget.Toolbar
+        android:id="@+id/my_toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:background="?attr/colorPrimary"
+        android:elevation="4dp"
+        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"/>
+</LinearLayout>
diff --git a/car-ui-lib/paintbooth/src/main/res/layout/simulated_screen_shape_container.xml b/car-ui-lib/paintbooth/src/main/res/layout/simulated_screen_shape_container.xml
new file mode 100644
index 0000000..96387b1
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/layout/simulated_screen_shape_container.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:focusableInTouchMode="false"
+                android:focusable="false"
+                android:background="@drawable/simulated_screen_shape">
+
+</RelativeLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/widgets_activity.xml b/car-ui-lib/paintbooth/src/main/res/layout/widgets_activity.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/layout/widgets_activity.xml
rename to car-ui-lib/paintbooth/src/main/res/layout/widgets_activity.xml
diff --git a/car-ui-lib/tests/paintbooth/res/values/arrays.xml b/car-ui-lib/paintbooth/src/main/res/values/arrays.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/values/arrays.xml
rename to car-ui-lib/paintbooth/src/main/res/values/arrays.xml
diff --git a/car-ui-lib/tests/paintbooth/res/values/colors.xml b/car-ui-lib/paintbooth/src/main/res/values/colors.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/values/colors.xml
rename to car-ui-lib/paintbooth/src/main/res/values/colors.xml
diff --git a/car-ui-lib/paintbooth/src/main/res/values/dimens.xml b/car-ui-lib/paintbooth/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..35dfeec
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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>
+    <!-- Width of the overlay container. Setting to 0 will use full width of the screen  -->
+    <dimen name="screen_shape_container_width">0dp</dimen>
+    <!-- Height of the overlay container. Setting to 0 will use full height of the screen  -->
+    <dimen name="screen_shape_container_height">0dp</dimen>
+</resources>
diff --git a/car-ui-lib/paintbooth/src/main/res/values/strings.xml b/car-ui-lib/paintbooth/src/main/res/values/strings.xml
new file mode 100644
index 0000000..04f1413
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/values/strings.xml
@@ -0,0 +1,295 @@
+<?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.
+  -->
+<resources>
+  <!-- Application name [CHAR LIMIT=30] -->
+  <string name="app_name" translatable="false">Paint Booth (Gerrit)</string>
+
+  <!-- Description of the CurrentActivityService. [CHAR_LIMIT=200] -->
+  <string name="current_activity_service_description">Shows the current activity</string>
+
+  <!-- Strings for Preference Samples -->
+  <eat-comment/>
+
+  <!-- Preferences page title [CHAR_LIMIT=13] -->
+  <string name="preferences_screen_title">Settings</string>
+
+  <!--This section is for basic attributes -->
+  <eat-comment/>
+  <!-- Category title for basic preferences [CHAR_LIMIT=26]-->
+  <string name="basic_preferences">Basic attributes</string>
+  <!-- Title of a basic preference [CHAR_LIMIT=10]-->
+  <string name="title_basic_preference">Preference</string>
+  <!-- Summary of a basic preference [CHAR_LIMIT=71]-->
+  <string name="summary_basic_preference">Simple preference with no special attributes</string>
+
+  <!-- Title of a preference with stylized text [CHAR_LIMIT=71]-->
+  <string name="title_stylish_preference"><b>Very</b> <i>stylish</i> <u>preference</u></string>
+  <!-- Summary of a preference with stylized text [CHAR_LIMIT=150]-->
+  <string name="summary_stylish_preference">Define style tags such as &lt;b&gt; in a string resource to customize a preference\'s text</string>
+
+  <!-- Title of an icon preference [CHAR_LIMIT=25]-->
+  <string name="title_icon_preference">Icon preference</string>
+  <!-- Summary of an icon preference [CHAR_LIMIT=103]-->
+  <string name="summary_icon_preference">Define a drawable to display it at the start of the preference</string>
+
+  <!-- Title of a single line title preference [CHAR_LIMIT=165]-->
+  <string name="title_single_line_title_preference">Single line title preference - no matter how long the title is it will never wrap to multiple lines</string>
+  <!-- Summary of a single line title preference [CHAR_LIMIT=108]-->
+  <string name="summary_single_line_title_preference">This title will be ellipsized instead of wrapping to another line</string>
+
+  <!-- Title of a single line title preference without summary [CHAR_LIMIT=28]-->
+  <string name="title_single_line_no_summary">Single line preference - no summary</string>
+
+  <!--This section is for preferences that contain a widget in their layout -->
+  <eat-comment/>
+  <!-- Category title for preferences with widgets [CHAR_LIMIT=12]-->
+  <string name="widgets">Widgets</string>
+
+  <!-- Title of a two action preference [CHAR_LIMIT=31]-->
+  <string name="title_twoaction_preference">TwoAction preference</string>
+  <!-- Summary of a two action preference [CHAR_LIMIT=70]-->
+  <string name="summary_twoaction_preference">A widget should be visible on the right</string>
+
+  <!-- Title of a checkbox preference [CHAR_LIMIT=31]-->
+  <string name="title_checkbox_preference">Checkbox preference</string>
+  <!-- Summary of a checkbox preference [CHAR_LIMIT=78]-->
+  <string name="summary_checkbox_preference">Tap anywhere in this preference to toggle state</string>
+
+  <!-- Title of a switch preference [CHAR_LIMIT=28]-->
+  <string name="title_switch_preference">Switch preference</string>
+  <!-- Summary of a switch preference [CHAR_LIMIT=78]-->
+  <string name="summary_switch_preference">Tap anywhere in this preference to toggle state</string>
+
+  <!-- Title of a dropdown preference [CHAR_LIMIT=31]-->
+  <string name="title_dropdown_preference">Dropdown preference</string>
+
+  <!-- Title of a seekbar preference [CHAR_LIMIT=30]-->
+  <string name="title_seekbar_preference">Seekbar preference</string>
+  <!-- Summary of an seekbar preference [CHAR_LIMIT=32]-->
+  <string name="summary_seekbar_preference">Seekbar summary</string>
+
+  <!--This section is for preferences that launch a dialog to edit the preference -->
+  <eat-comment/>
+  <!-- Category title for preferences which launch dialogs [CHAR_LIMIT=12]-->
+  <string name="dialogs">Dialogs</string>
+
+  <!-- Title of an edittext preference [CHAR_LIMIT=32]-->
+  <string name="title_edittext_preference">EditText preference</string>
+  <!-- Title of the dialog for an edittext preference [CHAR_LIMIT=43]-->
+  <string name="dialog_title_edittext_preference">This title can be changed!</string>
+
+  <!-- Title of a list preference [CHAR_LIMIT=25]-->
+  <string name="title_list_preference">List preference</string>
+  <!-- Title of the dialog for a list preference [CHAR_LIMIT=30]-->
+  <string name="dialog_title_list_preference">Choose one option!</string>
+
+  <!-- Title of a multi-select list preference [CHAR_LIMIT=46]-->
+  <string name="title_multi_list_preference">Multi-select list preference</string>
+  <!-- Summary of a multi-select list preference [CHAR_LIMIT=71]-->
+  <string name="summary_multi_list_preference">Shows a dialog with multiple choice options</string>
+  <!-- Title of the dialog for a multi-select list preference [CHAR_LIMIT=33]-->
+  <string name="dialog_title_multi_list_preference">Choose some options!</string>
+
+  <!--This section is for advanced attributes-->
+  <eat-comment/>
+  <!-- Category title for preferences with advanced attributes [CHAR_LIMIT=32]-->
+  <string name="advanced_attributes">Advanced attributes</string>
+
+  <!-- Title of an expandable preference [CHAR_LIMIT=45]-->
+  <string name="title_expandable_preference">Expandable preference group</string>
+  <!-- Summary of an expandable preference [CHAR_LIMIT=131]-->
+  <string name="summary_expandable_preference">This group shows one item and collapses the rest into the advanced button below</string>
+
+  <!-- Title of a preference which launches an intent [CHAR_LIMIT=28]-->
+  <string name="title_intent_preference">Intent preference</string>
+  <!-- Summary of a preference which launches an intent [CHAR_LIMIT=51]-->
+  <string name="summary_intent_preference">Launches an intent when pressed</string>
+
+  <!-- Title of a parent preference [CHAR_LIMIT=28]-->
+  <string name="title_parent_preference">Parent preference</string>
+  <!-- Summary of a parent preference [CHAR_LIMIT=130]-->
+  <string name="summary_parent_preference">Toggling this preference will change the enabled state of the preference below</string>
+
+  <!-- Title of a child preference [CHAR_LIMIT=26]-->
+  <string name="title_child_preference">Child preference</string>
+  <!-- Summary of a child preference [CHAR_LIMIT=123]-->
+  <string name="summary_child_preference">The enabled state of this preference is controlled by the preference above</string>
+
+  <!-- Title of a switch preference with variable summaries [CHAR_LIMIT=45]-->
+  <string name="title_toggle_summary_preference">Variable summary preference</string>
+  <!-- Summary of a variable summary preference when the preference is on [CHAR_LIMIT=118]-->
+  <string name="summary_on_toggle_summary_preference">On! :) - the summary of this preference changes depending on its state</string>
+  <!-- Summary of a variable summary preference when the preference is off [CHAR_LIMIT=118]-->
+  <string name="summary_off_toggle_summary_preference">Off! :( - the summary of this preference changes depending on its state</string>
+
+  <!-- Title of a copyable preference [CHAR_LIMIT=31]-->
+  <string name="title_copyable_preference">Copyable preference</string>
+  <!-- Summary of a copyable preference [CHAR_LIMIT=81]-->
+  <string name="summary_copyable_preference">Long press on this preference to copy its summary</string>
+
+  <!-- Title of a Advanced preference [CHAR_LIMIT=13]-->
+  <string name="advanced_preference">Advanced</string>
+
+  <!-- Title of a Intent preference [CHAR_LIMIT=28]-->
+  <string name="intent_preference">Intent preference</string>
+
+  <!--This section is for toolbar attributes -->
+  <eat-comment/>
+
+  <!-- Text for change title button [CHAR_LIMIT=20]-->
+  <string name="toolbar_change_title">Change title</string>
+
+  <!-- Text for set xml button [CHAR_LIMIT=45]-->
+  <string name="toolbar_set_xml_resource">MenuItem: Set to XML source</string>
+
+  <!-- Text for add icon button [CHAR_LIMIT=30]-->
+  <string name="toolbar_add_icon">MenuItem: Add Icon</string>
+
+  <!-- Text for add untined icon button [CHAR_LIMIT=45]-->
+  <string name="toolbar_add_untined_icon">MenuItem: Add untinted icon</string>
+
+  <!-- Text for add overflow button [CHAR_LIMIT=36]-->
+  <string name="toolbar_add_overflow">Overflow MenuItem: Add Simple</string>
+
+  <!-- Text for add overflow button [CHAR_LIMIT=36]-->
+  <string name="toolbar_add_overflow_switch">Overflow MenuItem: Add switchable</string>
+
+  <!-- Text for add icon text overflow button [CHAR_LIMIT=45]-->
+  <string name="toolbar_add_icon_text_overflow">Overflow MenuItem: Add icon and text</string>
+
+  <!-- Text for add switch button [CHAR_LIMIT=33]-->
+  <string name="toolbar_add_switch">MenuItem: Add Switch</string>
+
+  <!-- Text for add text button [CHAR_LIMIT=30]-->
+  <string name="toolbar_add_text">MenuItem: Add text</string>
+
+  <!-- Text for add icon text button [CHAR_LIMIT=45]-->
+  <string name="toolbar_add_icon_text">MenuItem: Add icon and text</string>
+
+  <!-- Text for add untined icon and text button [CHAR_LIMIT=60]-->
+  <string name="toolbar_add_untinted_icon_and_text">MenuItem: Add untinted icon and text</string>
+
+  <!-- Text for add activatable button [CHAR_LIMIT=41]-->
+  <string name="toolbar_add_activatable">MenuItem: Add activatable</string>
+
+  <!-- Text for add activatable button [CHAR_LIMIT=36]-->
+  <string name="toolbar_add_morphing">MenuItem: Add morphing</string>
+
+  <!-- Text for toggle visibility button [CHAR_LIMIT=45]-->
+  <string name="toolbar_toggle_visibility">MenuItem: Toggle Visibility</string>
+
+  <!-- Text for toggle enable button [CHAR_LIMIT=40]-->
+  <string name="toolbar_toggle_enable">MenuItem: Toggle Enabled</string>
+
+  <!-- Text for toggle enable button [CHAR_LIMIT=49]-->
+  <string name="toolbar_toggle_perform_click">MenuItem: Call PerformClick()</string>
+
+  <!-- Text for toggle icon button [CHAR_LIMIT=35]-->
+  <string name="toolbar_toggle_icon">MenuItem: Toggle Icon</string>
+
+  <!-- Text for toggle show while search button [CHAR_LIMIT=61]-->
+  <string name="toolbar_toggle_show_while_search">MenuItem: Toggle show while searching</string>
+
+  <!-- Text for cycle nav button mode button [CHAR_LIMIT=35]-->
+  <string name="toolbar_cycle_nav_button">Cycle nav button mode</string>
+
+  <!-- Text for toggle logo button [CHAR_LIMIT=19]-->
+  <string name="toolbar_toggle_logo">Toggle logo</string>
+
+  <!-- Text for cycle state button [CHAR_LIMIT=20]-->
+  <string name="toolbar_cycle_state">Cycle state</string>
+
+  <!-- Text for toggle search hint button [CHAR_LIMIT=30]-->
+  <string name="toolbar_toggle_search_hint">Toggle search hint</string>
+
+  <!-- Text for toggle background button [CHAR_LIMIT=30]-->
+  <string name="toolbar_toggle_background">Toggle background</string>
+
+  <!-- Text for add tab button [CHAR_LIMIT=12]-->
+  <string name="toolbar_add_tab">Add tab</string>
+
+  <!-- Text for add tab with custom text button [CHAR_LIMIT=40]-->
+  <string name="toolbar_add_tab_with_custom_text">Add tab with custom text</string>
+
+  <!-- Text for showing tabs in subpages [CHAR_LIMIT=50]-->
+  <string name="toolbar_show_tabs_in_subpage">Toggle showing tabs in subpages</string>
+
+  <!-- Text for toggle search icon button [CHAR_LIMIT=30]-->
+  <string name="toolbar_toggle_search_icon">Toggle search icon</string>
+
+  <!--This section is for dialog attributes -->
+  <eat-comment/>
+
+  <!-- Text for show dialog button [CHAR_LIMIT=18]-->
+  <string name="dialog_show_dialog">Show Dialog</string>
+
+  <!-- Text for show dialog button [CHAR_LIMIT=30]-->
+  <string name="dialog_show_dialog_icon">Show Dialog with icon</string>
+
+  <!-- Text for Dialog with edit text box button [CHAR_LIMIT=50]-->
+  <string name="dialog_show_dialog_edit">Show Dialog with edit text box</string>
+
+  <!-- Text for show Dialog with only positive button button [CHAR_LIMIT=61]-->
+  <string name="dialog_show_dialog_only_positive">Show Dialog with only positive button</string>
+
+  <!-- Text for show Dialog With no button provided button [CHAR_LIMIT=60]-->
+  <string name="dialog_show_dialog_no_button">Show Dialog With no button provided</string>
+
+  <!-- Text for show Dialog With Checkbox button [CHAR_LIMIT=41]-->
+  <string name="dialog_show_dialog_checkbox">Show Dialog With Checkbox</string>
+
+  <!-- Text for show Dialog without title button [CHAR_LIMIT=41]-->
+  <string name="dialog_show_dialog_no_title">Show Dialog without title</string>
+
+  <!-- Text for show Toast button [CHAR_LIMIT=16]-->
+  <string name="dialog_show_toast">Show Toast</string>
+
+  <!-- Button that shows a dialog with a subtitle [CHAR_LIMIT=50]-->
+  <string name="dialog_show_subtitle">Show Dialog with title and subtitle</string>
+
+  <!-- Button that shows a dialog with a subtitle and icon [CHAR_LIMIT=50]-->
+  <string name="dialog_show_subtitle_and_icon">Show Dialog with title, subtitle, and icon</string>
+
+  <!-- Button that shows a dialog with a long title, subtitle and icon [CHAR_LIMIT=500]-->
+  <string name="dialog_show_long_subtitle_and_icon">Show Dialog with a long title, subtitle, and icon</string>
+
+  <!-- Text to show Dialog with single choice items-->
+  <string name="dialog_show_single_choice">Show with single choice items</string>
+
+  <!-- Text to show a dialog with single choice items and no default button [CHAR_LIMIT=200] -->
+  <string name="dialog_show_list_items_without_default_button">Show with single choice items and no default button</string>
+
+  <!-- Text to show a permission Dialog [CHAR_LIMIT=50] -->
+  <string name="dialog_show_permission_dialog">Show permission dialog</string>
+
+  <!-- Text to show a permission Dialog for multiple permissions [CHAR_LIMIT=50] -->
+  <string name="dialog_show_multi_permission_dialog">Show multiple permissions dialog</string>
+
+  <!-- Text on button to show a permission dialog asking for the users location. [CHAR_LIMIT=100] -->
+  <string name="dialog_show_foreground_permission_dialog">Show foreground permission dialog</string>
+
+  <!-- Text on button to show a permission dialog asking for the users location in the background [CHAR_LIMIT=100] -->
+  <string name="dialog_show_background_permission_dialog">Show background permission dialog</string>
+
+  <!--This section is for widget attributes -->
+  <eat-comment/>
+  <!-- Text for checkbox [CHAR_LIMIT=16]-->
+  <string name="widget_checkbox_text">I\'m a check box</string>
+  <!-- Text for switch [CHAR_LIMIT=25]-->
+  <string name="widget_switch_text">I\'m a switch</string>
+
+</resources>
diff --git a/car-ui-lib/paintbooth/src/main/res/xml/current_activity_service.xml b/car-ui-lib/paintbooth/src/main/res/xml/current_activity_service.xml
new file mode 100644
index 0000000..f6143cd
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/xml/current_activity_service.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<accessibility-service
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accessibilityEventTypes="typeWindowStateChanged"
+    android:accessibilityFeedbackType="feedbackGeneric"
+    android:accessibilityFlags="flagIncludeNotImportantViews"
+    android:description="@string/current_activity_service_description"/>
diff --git a/car-ui-lib/tests/paintbooth/res/xml/menuitems.xml b/car-ui-lib/paintbooth/src/main/res/xml/menuitems.xml
similarity index 100%
rename from car-ui-lib/tests/paintbooth/res/xml/menuitems.xml
rename to car-ui-lib/paintbooth/src/main/res/xml/menuitems.xml
diff --git a/car-ui-lib/paintbooth/src/main/res/xml/preference_overlays.xml b/car-ui-lib/paintbooth/src/main/res/xml/preference_overlays.xml
new file mode 100644
index 0000000..f96b2a4
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/xml/preference_overlays.xml
@@ -0,0 +1,20 @@
+<?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.
+  -->
+<PreferenceScreen
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    app:title="Overlays">
+</PreferenceScreen>
diff --git a/car-ui-lib/paintbooth/src/main/res/xml/preference_samples.xml b/car-ui-lib/paintbooth/src/main/res/xml/preference_samples.xml
new file mode 100644
index 0000000..d9a891c
--- /dev/null
+++ b/car-ui-lib/paintbooth/src/main/res/xml/preference_samples.xml
@@ -0,0 +1,173 @@
+<?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.
+  -->
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    app:title="@string/preferences_screen_title">
+
+    <PreferenceCategory
+        android:title="@string/basic_preferences">
+
+        <Preference
+            android:key="preference"
+            android:summary="@string/summary_basic_preference"
+            android:title="@string/title_basic_preference"/>
+
+        <Preference
+            android:key="preference_disabled_without_ripple"
+            android:summary="Without ripple"
+            android:title="@string/title_basic_preference"/>
+
+        <Preference
+            android:key="preference_disabled_with_ripple"
+            android:summary="With ripple"
+            android:title="@string/title_basic_preference"/>
+
+        <Preference
+            android:key="stylized"
+            android:dependency="preference"
+            android:summary="@string/summary_stylish_preference"
+            android:title="@string/title_stylish_preference"/>
+
+        <Preference
+            android:icon="@drawable/ic_settings_wifi"
+            android:key="icon"
+            android:summary="@string/summary_icon_preference"
+            android:title="@string/title_icon_preference"/>
+
+        <Preference
+            android:key="single_line_title"
+            android:summary="@string/summary_single_line_title_preference"
+            android:title="@string/title_single_line_title_preference"
+            app:singleLineTitle="true"/>
+
+        <Preference
+            android:key="single_line_no_summary"
+            android:title="@string/title_single_line_no_summary"
+            app:singleLineTitle="true"/>
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/widgets">
+
+        <CheckBoxPreference
+            android:key="checkbox"
+            android:summary="@string/summary_checkbox_preference"
+            android:title="@string/title_checkbox_preference"/>
+
+        <DropDownPreference
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="dropdown"
+            android:title="@string/title_dropdown_preference"
+            app:useSimpleSummaryProvider="true"/>
+
+        <SeekBarPreference
+            android:defaultValue="5"
+            android:key="seekbar"
+            android:max="10"
+            android:title="@string/title_seekbar_preference"/>
+
+        <SwitchPreference
+            android:key="switch"
+            android:summary="@string/summary_switch_preference"
+            android:title="@string/title_switch_preference"/>
+
+        <com.android.car.ui.preference.CarUiTwoActionPreference
+            android:key="twoaction"
+            android:summary="@string/summary_twoaction_preference"
+            android:title="@string/title_twoaction_preference"
+            android:widgetLayout="@layout/details_preference_widget"/>
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/dialogs">
+
+        <EditTextPreference
+            android:dialogTitle="@string/dialog_title_edittext_preference"
+            android:key="edittext"
+            android:title="@string/title_edittext_preference"
+            app:useSimpleSummaryProvider="true"/>
+
+        <ListPreference
+            android:dialogTitle="@string/dialog_title_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="list"
+            android:title="@string/title_list_preference"
+            app:useSimpleSummaryProvider="true"/>
+
+        <MultiSelectListPreference
+            android:dialogTitle="@string/dialog_title_multi_list_preference"
+            android:entries="@array/entries"
+            android:entryValues="@array/entry_values"
+            android:key="multi_select_list"
+            android:summary="@string/summary_multi_list_preference"
+            android:title="@string/title_multi_list_preference"/>
+
+        <com.android.car.ui.preference.CarUiSeekBarDialogPreference
+            android:dialogTitle="Seekbar Dialog"
+            android:key="seekbarDialog"
+            android:summary="@string/summary_seekbar_preference"
+            android:title="@string/title_seekbar_preference"/>
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="@string/advanced_preference"
+        android:title="@string/advanced_attributes"
+        app:initialExpandedChildrenCount="1">
+
+        <Preference
+            android:key="expandable"
+            android:summary="@string/summary_expandable_preference"
+            android:title="@string/title_expandable_preference"/>
+
+        <Preference
+            android:summary="@string/summary_intent_preference"
+            android:title="@string/title_intent_preference">
+
+            <intent android:action="android.intent.action.VIEW"
+                    android:data="http://www.android.com"/>
+
+        </Preference>
+
+        <Preference
+            android:key="copyable"
+            android:selectable="false"
+            android:summary="@string/summary_copyable_preference"
+            android:title="@string/title_copyable_preference"
+            app:enableCopying="true"/>
+
+        <SwitchPreference
+            android:dependency="parent"
+            android:key="child"
+            android:summary="@string/summary_child_preference"
+            android:title="@string/title_child_preference"/>
+
+        <SwitchPreference
+            android:key="toggle_summary"
+            android:summaryOff="@string/summary_off_toggle_summary_preference"
+            android:summaryOn="@string/summary_on_toggle_summary_preference"
+            android:title="@string/title_toggle_summary_preference"/>
+
+        <SwitchPreference
+            android:key="parent"
+            android:summary="@string/summary_parent_preference"
+            android:title="@string/title_parent_preference"/>
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/car-ui-lib/referencedesign/Android.mk b/car-ui-lib/referencedesign/Android.mk
index 7da04dc..890719e 100644
--- a/car-ui-lib/referencedesign/Android.mk
+++ b/car-ui-lib/referencedesign/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 CAR_UI_RRO_SET_NAME := googlecarui
+CAR_UI_RRO_MANIFEST_FILE := $(LOCAL_PATH)/AndroidManifest.xml
 CAR_UI_RESOURCE_DIR := $(LOCAL_PATH)/res
 CAR_UI_RRO_TARGETS := \
     com.android.car.ui.paintbooth \
@@ -19,10 +20,10 @@
     com.android.car.settings \
     com.android.car.voicecontrol \
     com.android.car.faceenroll \
-    com.android.permissioncontroller \
     com.android.settings.intelligence \
     com.google.android.apps.automotive.inputmethod \
     com.google.android.apps.automotive.inputmethod.dev \
+    com.google.android.apps.automotive.templates.host \
     com.google.android.embedded.projection \
     com.google.android.gms \
     com.google.android.packageinstaller \
@@ -31,3 +32,20 @@
     com.android.vending \
 
 include packages/apps/Car/libs/car-ui-lib/generate_rros.mk
+
+CAR_UI_RRO_SET_NAME := googlecarui.overlayable
+CAR_UI_RRO_MANIFEST_FILE := $(LOCAL_PATH)/AndroidManifest-overlayable.xml
+CAR_UI_RESOURCE_DIR := $(LOCAL_PATH)/res
+CAR_UI_RRO_TARGETS := \
+    com.google.android.apps.automotive.inputmethod \
+    com.google.android.apps.automotive.inputmethod.dev \
+    com.google.android.apps.automotive.templates.host \
+    com.google.android.embedded.projection \
+    com.google.android.gms \
+    com.google.android.packageinstaller \
+    com.google.android.permissioncontroller \
+    com.google.android.carassistant \
+    com.google.android.tts \
+    com.android.vending \
+
+include packages/apps/Car/libs/car-ui-lib/generate_rros.mk
diff --git a/car-ui-lib/referencedesign/AndroidManifest-overlayable.xml b/car-ui-lib/referencedesign/AndroidManifest-overlayable.xml
new file mode 100644
index 0000000..1b0585a
--- /dev/null
+++ b/car-ui-lib/referencedesign/AndroidManifest-overlayable.xml
@@ -0,0 +1,11 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="{{RRO_PACKAGE_NAME}}">
+    <application android:hasCode="false"/>
+    <overlay android:priority="10"
+        android:targetPackage="{{TARGET_PACKAGE_NAME}}"
+        android:targetName="car-ui-lib"
+        android:resourcesMap="@xml/overlays"
+        android:isStatic="true"
+        android:requiredSystemPropertyName="ro.build.car_ui_rros_enabled"
+        android:requiredSystemPropertyValue="true"/>
+</manifest>
diff --git a/car-ui-lib/referencedesign/AndroidManifest.xml b/car-ui-lib/referencedesign/AndroidManifest.xml
index 7585b3c..0994382 100644
--- a/car-ui-lib/referencedesign/AndroidManifest.xml
+++ b/car-ui-lib/referencedesign/AndroidManifest.xml
@@ -1,16 +1,10 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="{{RRO_PACKAGE_NAME}}">
     <application android:hasCode="false"/>
-    <!-- IMPORTANT: Setting the category to "BypassIdMapV1" will cause these static RROs not to
-     have an IDMAP V1 generated within the PackageManager which improves boot performance.
-     IDMAP v1 allowed for overlays of values within an AndroidManifest file but that
-     functionality and IDMAP v1 has been removed in the next version of Android and is not used
-      here. -->
     <overlay android:priority="10"
         android:targetPackage="{{TARGET_PACKAGE_NAME}}"
-        android:targetName="car-ui-lib"
+        android:resourcesMap="@xml/overlays"
         android:isStatic="true"
-        android:category="BypassIdMapV1"
         android:requiredSystemPropertyName="ro.build.car_ui_rros_enabled"
         android:requiredSystemPropertyValue="true"/>
 </manifest>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_icon_arrow_back.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_icon_arrow_back.xml
deleted file mode 100644
index 4ad49b2..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_icon_arrow_back.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2018, 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
-</vector>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
deleted file mode 100644
index 03f8d82..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~
-  ~ Copyright (C) 2019 Google Inc.
-  ~
-  ~ 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.
-  ~
- -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="#27ffffff"
-        android:radius="48dp"/>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml
deleted file mode 100644
index fb97b92..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml
+++ /dev/null
@@ -1,141 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    ~ Copyright (C) 2020 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.
-    -->
-<!-- This is for the two-row version of the toolbar -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-     clearFocus() will actually send the focus to the first focusable thing in the layout.
-     If that focusable thing is still the search bar it will just reselect it, and the user won't
-     be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true" />
-
-    <FrameLayout
-        android:id="@+id/car_ui_base_layout_content_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_background"
-        android:layout_alignParentTop="true">
-
-        <!-- The horizontal bias here is so that when you set this view as GONE, it will be
-             treated as if it's all the way to the left instead of centered in the margin -->
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_nav_icon_container"
-            android:layout_width="112dp"
-            android:layout_height="96dp"
-            android:layout_alignParentLeft="true">
-            <!-- missing: icon src -->
-            <ImageView
-                android:id="@+id/car_ui_toolbar_nav_icon"
-                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY"
-                android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
-                android:tint="@color/car_ui_text_color_primary"/>
-            <ImageView
-                android:id="@+id/car_ui_toolbar_logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY"/>
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_title_logo_container"
-            android:layout_width="112dp"
-            android:layout_height="96dp"
-            android:layout_alignParentRight="true">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_title_logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:scaleType="fitXY"
-                android:layout_gravity="center"/>
-        </FrameLayout>
-
-        <LinearLayout
-            android:id="@+id/car_ui_toolbar_title_container"
-            android:layout_height="96dp"
-            android:layout_width="wrap_content"
-            android:orientation="vertical"
-            android:layout_marginRight="112dp"
-            android:layout_alignParentRight="true"
-            android:gravity="center_vertical">
-            <TextView android:id="@+id/car_ui_toolbar_title"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content"
-                      android:singleLine="true"
-                      android:textAlignment="viewStart"
-                      android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
-            <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content"
-                      android:visibility="gone"
-                      android:textAlignment="viewStart"
-                      android:textAppearance="?android:attr/textAppearanceSmall"/>
-        </LinearLayout>
-
-        <com.android.car.ui.toolbar.TabLayout
-            android:id="@+id/car_ui_toolbar_tabs"
-            android:layout_width="match_parent"
-            android:layout_height="96dp"
-            android:gravity="left"
-            android:layout_alignParentTop="true"
-            android:layout_marginTop="96dp"/>
-
-        <LinearLayout
-            android:id="@+id/car_ui_toolbar_menu_items_container"
-            android:layout_width="wrap_content"
-            android:layout_height="96dp"
-            android:orientation="horizontal"
-            android:divider="@drawable/car_ui_toolbar_menu_item_divider"
-            android:showDividers="beginning|middle|end"
-            android:layout_toRightOf="@+id/car_ui_toolbar_nav_icon_container"
-            android:layout_alignWithParentIfMissing="true"/>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_search_view_container"
-            android:layout_width="match_parent"
-            android:layout_height="96dp"
-            android:layout_toRightOf="@+id/car_ui_toolbar_menu_items_container"
-            android:layout_alignParentRight="true"/>
-
-        <ProgressBar
-            android:id="@+id/car_ui_toolbar_progress_bar"
-            style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true"
-            android:layout_alignParentBottom="true"
-            android:indeterminate="true"
-            android:visibility="gone"/>
-
-    </RelativeLayout>
-</RelativeLayout>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_base_layout_toolbar.xml
deleted file mode 100644
index 35d7742..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_base_layout_toolbar.xml
+++ /dev/null
@@ -1,135 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    ~ Copyright (C) 2020 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.
-    -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-     clearFocus() will actually send the focus to the first focusable thing in the layout.
-     If that focusable thing is still the search bar it will just reselect it, and the user won't
-     be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true" />
-
-    <FrameLayout
-        android:id="@+id/car_ui_base_layout_content_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
-
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="96dp"
-        android:layout_alignParentTop="true"
-        android:id="@+id/car_ui_toolbar_background">
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_nav_icon_container"
-            android:layout_width="112dp"
-            android:layout_height="match_parent"
-            android:layout_alignParentLeft="true">
-            <ImageView
-                android:id="@+id/car_ui_toolbar_nav_icon"
-                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY"
-                android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
-                android:tint="@color/car_ui_text_color_primary"/>
-            <ImageView
-                android:id="@+id/car_ui_toolbar_logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY"/>
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_title_logo_container"
-            android:layout_width="112dp"
-            android:layout_height="match_parent"
-            android:layout_alignParentRight="true">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_title_logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:scaleType="fitXY"
-                android:layout_gravity="center"/>
-        </FrameLayout>
-
-        <LinearLayout android:layout_height="wrap_content"
-                      android:layout_width="match_parent"
-                      android:id="@+id/car_ui_toolbar_title_container"
-                      android:orientation="vertical"
-                      android:layout_marginRight="112dp"
-                      android:layout_alignParentRight="true"
-                      android:layout_centerVertical="true">
-            <TextView android:id="@+id/car_ui_toolbar_title"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content"
-                      android:singleLine="true"
-                      android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
-            <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content"
-                      android:visibility="gone"
-                      android:textAlignment="viewStart"
-                      android:textAppearance="?android:attr/textAppearanceSmall"/>
-        </LinearLayout>
-
-        <com.android.car.ui.toolbar.TabLayout
-            android:id="@+id/car_ui_toolbar_tabs"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="left"
-            android:layout_toRightOf="@+id/car_ui_toolbar_menu_items_container"
-            android:layout_toLeftOf="@+id/car_ui_toolbar_title_container"/>
-
-        <LinearLayout
-            android:id="@+id/car_ui_toolbar_menu_items_container"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:orientation="horizontal"
-            android:divider="@drawable/car_ui_toolbar_menu_item_divider"
-            android:showDividers="beginning|middle|end"
-            android:layout_toRightOf="@+id/car_ui_toolbar_nav_icon_container"
-            android:layout_alignWithParentIfMissing="true"/>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_search_view_container"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_toRightOf="@+id/car_ui_toolbar_menu_items_container"
-            android:layout_alignParentRight="true"/>
-
-        <ProgressBar
-            android:id="@+id/car_ui_toolbar_progress_bar"
-            style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true"
-            android:layout_alignParentBottom="true"
-            android:indeterminate="true"
-            android:visibility="gone"/>
-
-    </RelativeLayout>
-</RelativeLayout>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_recycler_view.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_recycler_view.xml
deleted file mode 100644
index c1d16b5..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_recycler_view.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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
-  -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <com.android.car.ui.recyclerview.CarUiRecyclerViewContainer
-        android:id="@+id/car_ui_recycler_view"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_marginStart="@dimen/car_ui_scrollbar_margin"
-        android:tag="carUiRecyclerView"
-        android:layout_weight="1"/>
-
-    <include layout="@layout/car_ui_recyclerview_scrollbar"/>
-</merge>
\ No newline at end of file
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_recyclerview_scrollbar.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_recyclerview_scrollbar.xml
deleted file mode 100644
index 85d624c..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_recyclerview_scrollbar.xml
+++ /dev/null
@@ -1,73 +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.
-  -->
-
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="@dimen/car_ui_scrollbar_container_width"
-    android:layout_height="match_parent"
-    android:id="@+id/car_ui_scroll_bar"
-    android:gravity="center">
-
-    <ImageView
-        android:id="@+id/car_ui_scrollbar_page_up"
-        android:layout_width="@dimen/car_ui_scrollbar_button_size"
-        android:layout_height="@dimen/car_ui_scrollbar_button_size"
-        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
-        android:contentDescription="@string/car_ui_scrollbar_page_up_button"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/car_ui_recyclerview_ic_up"
-        android:scaleType="centerInside"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"/>
-
-    <!-- View height is dynamically calculated during layout. -->
-    <View
-        android:id="@+id/car_ui_scrollbar_thumb"
-        android:layout_width="@dimen/car_ui_scrollbar_thumb_width"
-        android:layout_height="0dp"
-        android:layout_centerHorizontal="true"
-        android:background="@drawable/car_ui_recyclerview_scrollbar_thumb"
-        android:layout_below="@+id/car_ui_scrollbar_page_up" />
-
-    <View
-        android:id="@+id/car_ui_scrollbar_track"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_marginTop="@dimen/car_ui_scrollbar_separator_margin"
-        android:layout_marginBottom="@dimen/car_ui_scrollbar_separator_margin"
-        android:layout_below="@+id/car_ui_scrollbar_page_up"
-        android:layout_above="@+id/car_ui_scrollbar_page_down"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentEnd="true"/>
-
-    <ImageView
-        android:id="@+id/car_ui_scrollbar_page_down"
-        android:layout_width="@dimen/car_ui_scrollbar_button_size"
-        android:layout_height="@dimen/car_ui_scrollbar_button_size"
-        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
-        android:contentDescription="@string/car_ui_scrollbar_page_down_button"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/car_ui_recyclerview_ic_down"
-        android:scaleType="centerInside"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"/>
-</RelativeLayout>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_toolbar.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_toolbar.xml
deleted file mode 100644
index 85e34cb..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_toolbar.xml
+++ /dev/null
@@ -1,114 +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.
--->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="96dp"
-    android:id="@+id/car_ui_toolbar_background">
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_width="112dp"
-        android:layout_height="match_parent"
-        android:layout_alignParentLeft="true">
-        <ImageView
-            android:id="@+id/car_ui_toolbar_nav_icon"
-            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"
-            android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
-            android:tint="@color/car_ui_text_color_primary"/>
-        <ImageView
-            android:id="@+id/car_ui_toolbar_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"/>
-    </FrameLayout>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_title_logo_container"
-        android:layout_width="112dp"
-        android:layout_height="match_parent"
-        android:layout_alignParentRight="true">
-
-        <ImageView
-            android:id="@+id/car_ui_toolbar_title_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:scaleType="fitXY"
-            android:layout_gravity="center"/>
-    </FrameLayout>
-
-    <LinearLayout android:layout_height="wrap_content"
-                  android:layout_width="match_parent"
-                  android:id="@+id/car_ui_toolbar_title_container"
-                  android:orientation="vertical"
-                  android:layout_marginRight="112dp"
-                  android:layout_alignParentRight="true"
-                  android:layout_centerVertical="true">
-        <TextView android:id="@+id/car_ui_toolbar_title"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:singleLine="true"
-                  android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
-        <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:visibility="gone"
-                  android:textAlignment="viewStart"
-                  android:textAppearance="?android:attr/textAppearanceSmall"/>
-    </LinearLayout>
-
-    <com.android.car.ui.toolbar.TabLayout
-        android:id="@+id/car_ui_toolbar_tabs"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:gravity="left"
-        android:layout_toRightOf="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_toLeftOf="@+id/car_ui_toolbar_title_container"/>
-
-    <LinearLayout
-        android:id="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:orientation="horizontal"
-        android:divider="@drawable/car_ui_toolbar_menu_item_divider"
-        android:showDividers="beginning|middle|end"
-        android:layout_toRightOf="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_alignWithParentIfMissing="true"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_search_view_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_toRightOf="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_alignParentRight="true"/>
-
-    <ProgressBar
-        android:id="@+id/car_ui_toolbar_progress_bar"
-        style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentBottom="true"
-        android:indeterminate="true"
-        android:visibility="gone"/>
-
-</RelativeLayout>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_toolbar_two_row.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_toolbar_two_row.xml
deleted file mode 100644
index e5eff70..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-ldrtl/car_ui_toolbar_two_row.xml
+++ /dev/null
@@ -1,119 +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.
--->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:id="@+id/car_ui_toolbar_background">
-
-    <!-- The horizontal bias here is so that when you set this view as GONE, it will be
-         treated as if it's all the way to the left instead of centered in the margin -->
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_width="112dp"
-        android:layout_height="96dp"
-        android:layout_alignParentLeft="true">
-        <!-- missing: icon src -->
-        <ImageView
-            android:id="@+id/car_ui_toolbar_nav_icon"
-            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"
-            android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
-            android:tint="@color/car_ui_text_color_primary"/>
-        <ImageView
-            android:id="@+id/car_ui_toolbar_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"/>
-    </FrameLayout>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_title_logo_container"
-        android:layout_width="112dp"
-        android:layout_height="96dp"
-        android:layout_alignParentRight="true">
-
-        <ImageView
-            android:id="@+id/car_ui_toolbar_title_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:scaleType="fitXY"
-            android:layout_gravity="center"/>
-    </FrameLayout>
-
-    <LinearLayout
-        android:id="@+id/car_ui_toolbar_title_container"
-        android:layout_height="96dp"
-        android:layout_width="wrap_content"
-        android:orientation="vertical"
-        android:layout_marginRight="112dp"
-        android:layout_alignParentRight="true"
-        android:gravity="center_vertical">
-        <TextView android:id="@+id/car_ui_toolbar_title"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:singleLine="true"
-                  android:textAlignment="viewStart"
-                  android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
-        <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:visibility="gone"
-                  android:textAlignment="viewStart"
-                  android:textAppearance="?android:attr/textAppearanceSmall"/>
-    </LinearLayout>
-
-    <com.android.car.ui.toolbar.TabLayout
-        android:id="@+id/car_ui_toolbar_tabs"
-        android:layout_width="match_parent"
-        android:layout_height="96dp"
-        android:gravity="left"
-        android:layout_alignParentTop="true"
-        android:layout_marginTop="96dp"/>
-
-    <LinearLayout
-        android:id="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_width="wrap_content"
-        android:layout_height="96dp"
-        android:orientation="horizontal"
-        android:divider="@drawable/car_ui_toolbar_menu_item_divider"
-        android:showDividers="beginning|middle|end"
-        android:layout_toRightOf="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_alignWithParentIfMissing="true"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_search_view_container"
-        android:layout_width="match_parent"
-        android:layout_height="96dp"
-        android:layout_toRightOf="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_alignParentRight="true"/>
-
-    <ProgressBar
-        android:id="@+id/car_ui_toolbar_progress_bar"
-        style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentBottom="true"
-        android:indeterminate="true"
-        android:visibility="gone"/>
-
-</RelativeLayout>
\ No newline at end of file
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-port/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-port/car_ui_base_layout_toolbar.xml
deleted file mode 100644
index d13f2fd..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/layout-port/car_ui_base_layout_toolbar.xml
+++ /dev/null
@@ -1,185 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<!-- This is for the two-row version of the toolbar -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-     clearFocus() will actually send the focus to the first focusable thing in the layout.
-     If that focusable thing is still the search bar it will just reselect it, and the user won't
-     be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true" />
-
-    <FrameLayout
-        android:id="@+id/car_ui_base_layout_content_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentTop="true" />
-
-    <com.android.car.ui.baselayout.ClickBlockingView
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_alignBottom="@+id/car_ui_toolbar_background"
-        android:layout_alignEnd="@+id/car_ui_toolbar_background"
-        android:layout_alignTop="@+id/car_ui_toolbar_background"
-        android:layout_alignStart="@+id/car_ui_toolbar_background"/>
-
-    <RelativeLayout
-        android:id="@+id/car_ui_toolbar_background"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:tag="car_ui_top_inset"
-        android:layout_alignParentTop="true">
-
-        <View
-            android:id="@+id/car_ui_toolbar_row_separator_guideline2"
-            android:layout_width="match_parent"
-            android:layout_height="96dp" />
-
-        <View
-            android:id="@+id/car_ui_toolbar_row_separator_guideline"
-            android:layout_width="match_parent"
-            android:layout_below="@+id/car_ui_toolbar_row_separator_guideline2"
-            android:layout_height="0dp" />
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_nav_icon_container"
-            android:layout_width="112dp"
-            android:layout_height="0dp"
-            android:layout_above="@+id/car_ui_toolbar_row_separator_guideline"
-            android:layout_alignParentStart="true"
-            android:layout_alignParentTop="true">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_nav_icon"
-                android:tint="@color/car_ui_toolbar_nav_icon_color"
-                android:src="@drawable/car_ui_icon_arrow_back"
-                android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple"
-                android:layout_width="44dp"
-                android:layout_height="44dp"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_logo"
-                android:layout_width="44dp"
-                android:layout_height="44dp"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_title_logo_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_above="@+id/car_ui_toolbar_row_separator_guideline"
-            android:layout_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-            android:layout_alignParentTop="true">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_title_logo"
-                android:layout_width="44dp"
-                android:layout_height="44dp"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <FrameLayout
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_marginStart="16dp"
-            android:layout_above="@+id/car_ui_toolbar_row_separator_guideline"
-            android:layout_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            android:layout_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-            android:layout_alignParentTop="true" >
-            <LinearLayout
-                android:layout_gravity="center_vertical"
-                android:layout_height="wrap_content"
-                android:layout_width="wrap_content"
-                android:id="@+id/car_ui_toolbar_title_container"
-                android:orientation="vertical" >
-                <TextView android:id="@+id/car_ui_toolbar_title"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:singleLine="true"
-                    android:textSize="32sp"
-                    android:letterSpacing="0.0"
-                    android:textAlignment="viewStart" />
-                <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:visibility="gone"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:textAlignment="viewStart" />
-            </LinearLayout>
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_search_view_container"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_above="@+id/car_ui_toolbar_row_separator_guideline"
-            android:layout_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            android:layout_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-            android:layout_alignWithParentIfMissing="true"
-            android:layout_alignParentTop="true" />
-
-        <LinearLayout
-            android:id="@+id/car_ui_toolbar_menu_items_container"
-            android:divider="@drawable/car_ui_toolbar_menu_item_divider"
-            android:showDividers="beginning|middle|end"
-            android:layout_width="wrap_content"
-            android:layout_height="0dp"
-            android:visibility="gone"
-            android:orientation="horizontal"
-            android:layout_above="@+id/car_ui_toolbar_row_separator_guideline"
-            android:layout_alignParentEnd="true"
-            android:layout_alignParentTop="true" />
-
-        <RelativeLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_below="@+id/car_ui_toolbar_row_separator_guideline">
-
-            <com.android.car.ui.toolbar.TabLayout
-                android:id="@+id/car_ui_toolbar_tabs"
-                android:layout_width="match_parent"
-                android:layout_height="96dp" />
-
-            <ProgressBar
-                android:id="@+id/car_ui_toolbar_progress_bar"
-                style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:indeterminate="true"
-                android:visibility="gone"
-                android:layout_alignBottom="@id/car_ui_toolbar_tabs"
-                android:layout_alignParentEnd="true"
-                android:layout_alignParentStart="true" />
-
-        </RelativeLayout>
-
-    </RelativeLayout>
-
-</RelativeLayout>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/values/styles.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/values/styles.xml
deleted file mode 100644
index 6847242..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/values/styles.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<resources>
-
-    <style name="TextAppearance.CarUi.Widget" parent="android:TextAppearance.DeviceDefault.Widget">
-        <item name="android:textAlignment">viewStart</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Widget.Toolbar"/>
-
-    <style name="TextAppearance.CarUi.Widget.Toolbar.Title">
-        <item name="android:singleLine">true</item>
-        <item name="android:textSize">32sp</item>
-    </style>
-</resources>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/values/values.xml b/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/values/values.xml
deleted file mode 100644
index 2b51240..0000000
--- a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/values/values.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<resources>
-    <dimen name="car_ui_toolbar_logo_size">44dp</dimen>
-    <dimen name="car_ui_toolbar_nav_icon_size">44dp</dimen>
-
-    <dimen name="car_ui_scrollbar_margin">112dp</dimen>
-    <dimen name="car_ui_scrollbar_container_width">112dp</dimen>
-    <dimen name="car_ui_scrollbar_button_size">76dp</dimen>
-    <dimen name="car_ui_scrollbar_thumb_width">7dp</dimen>
-    <dimen name="car_ui_scrollbar_separator_margin">16dp</dimen>
-
-    <string name="car_ui_scrollbar_page_up_button">Scroll up</string>
-    <string name="car_ui_scrollbar_page_down_button">Scroll down</string>
-
-    <color name="car_ui_ripple_color">#27ffffff</color>
-    <color name="car_ui_scrollbar_thumb">#99ffffff</color>
-    <dimen name="car_ui_scrollbar_thumb_radius">100dp</dimen>
-
-    <color name="car_ui_toolbar_nav_icon_color">@color/car_ui_text_color_primary</color>
-</resources>
diff --git a/car-ui-lib/referencedesign/product.mk b/car-ui-lib/referencedesign/product.mk
index f77e94d..2a74f1c 100644
--- a/car-ui-lib/referencedesign/product.mk
+++ b/car-ui-lib/referencedesign/product.mk
@@ -1,11 +1,5 @@
 # Inherit from this product to include the "Reference Design" RROs for CarUi
 
-# Include built-time overlays
-PRODUCT_PACKAGE_OVERLAYS += \
-    packages/apps/Car/libs/car-ui-lib/referencedesign/overlay/
-PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS += \
-    packages/apps/Car/libs/car-ui-lib/referencedesign/overlay/
-
 # Include generated RROs
 PRODUCT_PACKAGES += \
     googlecarui-com-android-car-ui-paintbooth \
@@ -23,10 +17,10 @@
     googlecarui-com-android-car-settings \
     googlecarui-com-android-car-voicecontrol \
     googlecarui-com-android-car-faceenroll \
-    googlecarui-com-android-permissioncontroller \
     googlecarui-com-android-settings-intelligence \
     googlecarui-com-google-android-apps-automotive-inputmethod \
     googlecarui-com-google-android-apps-automotive-inputmethod-dev \
+    googlecarui-com-google-android-apps-automotive-templates-host \
     googlecarui-com-google-android-embedded-projection \
     googlecarui-com-google-android-gms \
     googlecarui-com-google-android-packageinstaller \
@@ -34,6 +28,20 @@
     googlecarui-com-google-android-tts \
     googlecarui-com-android-vending \
 
+
+# Include generated RROs that that use targetName
+PRODUCT_PACKAGES += \
+    googlecarui-overlayable-com-google-android-apps-automotive-inputmethod \
+    googlecarui-overlayable-com-google-android-apps-automotive-inputmethod-dev \
+    googlecarui-overlayable-com-google-android-apps-automotive-templates-host \
+    googlecarui-overlayable-com-google-android-embedded-projection \
+    googlecarui-overlayable-com-google-android-gms \
+    googlecarui-overlayable-com-google-android-packageinstaller \
+    googlecarui-overlayable-com-google-android-permissioncontroller \
+    googlecarui-overlayable-com-google-android-carassistant \
+    googlecarui-overlayable-com-google-android-tts \
+    googlecarui-overlayable-com-android-vending \
+
 # This system property is used to enable the RROs on startup via
 # the requiredSystemPropertyName/Value attributes in the manifest
 PRODUCT_PRODUCT_PROPERTIES += ro.build.car_ui_rros_enabled=true
diff --git a/car-ui-lib/referencedesign/res/color/car_ui_seekbar_thumb_inner_ring_color.xml b/car-ui-lib/referencedesign/res/color/car_ui_seekbar_thumb_inner_ring_color.xml
new file mode 100644
index 0000000..1f197c0
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/color/car_ui_seekbar_thumb_inner_ring_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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:state_selected="true" android:color="#3D94CBFF"/>
+    <item android:color="@android:color/transparent"/>
+</selector>
diff --git a/car-ui-lib/referencedesign/res/color/car_ui_seekbar_thumb_outer_ring_color.xml b/car-ui-lib/referencedesign/res/color/car_ui_seekbar_thumb_outer_ring_color.xml
new file mode 100644
index 0000000..d03fe13
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/color/car_ui_seekbar_thumb_outer_ring_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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:state_selected="true" android:color="#94CBFF"/>
+    <item android:color="@android:color/transparent"/>
+</selector>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/color/car_ui_text_color_primary.xml b/car-ui-lib/referencedesign/res/color/car_ui_text_color_primary.xml
similarity index 100%
rename from car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/color/car_ui_text_color_primary.xml
rename to car-ui-lib/referencedesign/res/color/car_ui_text_color_primary.xml
diff --git a/car-ui-lib/res/color/car_ui_text_color_secondary.xml b/car-ui-lib/referencedesign/res/color/car_ui_text_color_secondary.xml
similarity index 100%
rename from car-ui-lib/res/color/car_ui_text_color_secondary.xml
rename to car-ui-lib/referencedesign/res/color/car_ui_text_color_secondary.xml
diff --git a/car-ui-lib/referencedesign/res/color/car_ui_toolbar_menu_item_icon_background_color.xml b/car-ui-lib/referencedesign/res/color/car_ui_toolbar_menu_item_icon_background_color.xml
new file mode 100644
index 0000000..01b70aa
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/color/car_ui_toolbar_menu_item_icon_background_color.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2020 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.
+  -->
+<!-- The same as @color/car_ui_text_color_primary but with an activated state.
+     ColorStateLists don't support switching to complex colors, so we have to repeat
+     car_ui_text_color_primary here. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_activated="false"
+          android:color="@android:color/transparent"/>
+    <item android:state_enabled="false"
+          android:alpha="?android:attr/disabledAlpha"
+          android:color="?android:attr/colorForeground"/>
+    <item app:state_ux_restricted="true"
+          android:alpha="?android:attr/disabledAlpha"
+          android:color="?android:attr/colorForeground"/>
+    <item android:color="?android:attr/colorForeground" />
+</selector>
diff --git a/car-ui-lib/referencedesign/res/color/car_ui_toolbar_menu_item_icon_color.xml b/car-ui-lib/referencedesign/res/color/car_ui_toolbar_menu_item_icon_color.xml
new file mode 100644
index 0000000..a15bcba
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/color/car_ui_toolbar_menu_item_icon_color.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2020 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.
+  -->
+<!-- The same as @color/car_ui_text_color_primary but with an activated state.
+     ColorStateLists don't support switching to complex colors, so we have to repeat
+     car_ui_text_color_primary here. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_activated="true"
+          android:color="?android:attr/colorBackground"/>
+    <item android:state_enabled="false"
+          android:alpha="?android:attr/disabledAlpha"
+          android:color="?android:attr/colorForeground"/>
+    <item app:state_ux_restricted="true"
+          android:alpha="?android:attr/disabledAlpha"
+          android:color="?android:attr/colorForeground"/>
+    <item android:color="?android:attr/colorForeground" />
+</selector>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_button_ripple_background.xml b/car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_button_ripple_background.xml
similarity index 100%
rename from car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_button_ripple_background.xml
rename to car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_button_ripple_background.xml
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_ic_down.xml b/car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_ic_down.xml
similarity index 100%
rename from car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_ic_down.xml
rename to car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_ic_down.xml
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_ic_up.xml b/car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_ic_up.xml
similarity index 100%
rename from car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_ic_up.xml
rename to car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_ic_up.xml
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_scrollbar_thumb.xml b/car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_scrollbar_thumb.xml
similarity index 100%
rename from car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_recyclerview_scrollbar_thumb.xml
rename to car-ui-lib/referencedesign/res/drawable-ldrtl/car_ui_recyclerview_scrollbar_thumb.xml
diff --git a/car-ui-lib/res/drawable/car_ui_icon_arrow_back.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_icon_arrow_back.xml
similarity index 100%
rename from car-ui-lib/res/drawable/car_ui_icon_arrow_back.xml
rename to car-ui-lib/referencedesign/res/drawable/car_ui_icon_arrow_back.xml
diff --git a/car-ui-lib/referencedesign/res/drawable/car_ui_seekbar_preference_background.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_seekbar_preference_background.xml
new file mode 100644
index 0000000..405403b
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/drawable/car_ui_seekbar_preference_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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">
+    <!-- Highlight the preference when it's focused but not selected. The preference is selected in
+    direct manipulation mode. -->
+    <item android:state_focused="true" android:state_selected="false">
+        <shape android:shape="rectangle">
+            <solid android:color="#3D94CBFF"/>
+            <stroke android:width="8dp"
+                    android:color="#94CBFF"/>
+        </shape>
+    </item>
+</selector>
diff --git a/car-ui-lib/referencedesign/res/drawable/car_ui_seekbar_thumb.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_seekbar_thumb.xml
new file mode 100644
index 0000000..2d6723e
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/drawable/car_ui_seekbar_thumb.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Padding ensures the intrinsic size of this drawable includes the rings. -->
+    <item>
+        <shape android:shape="oval">
+            <solid android:color="?android:attr/colorAccent"/>
+            <size android:width="24dp" android:height="24dp"/>
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="ring"
+               android:innerRadius="12dp"
+               android:thickness="4dp"
+               android:useLevel="false">
+            <solid android:color="@color/car_ui_seekbar_thumb_inner_ring_color"/>
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="ring"
+               android:innerRadius="16dp"
+               android:thickness="8dp"
+               android:useLevel="false">
+            <solid android:color="@color/car_ui_seekbar_thumb_outer_ring_color"/>
+        </shape>
+    </item>
+</layer-list>
diff --git a/car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_toolbar_menu_item_divider.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_divider.xml
similarity index 100%
rename from car-ui-lib/referencedesign/overlay/frameworks/base/core/res/res/drawable/car_ui_toolbar_menu_item_divider.xml
rename to car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_divider.xml
diff --git a/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_background.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_background.xml
new file mode 100644
index 0000000..3f96409
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~
+  ~ Copyright (C) 2020 Google Inc.
+  ~
+  ~ 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.
+  ~
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <size
+        android:width="54dp"
+        android:height="54dp"/>
+    <solid android:color="@color/car_ui_toolbar_menu_item_icon_background_color"/>
+</shape>
diff --git a/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
new file mode 100644
index 0000000..14f6cd0
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/drawable/car_ui_toolbar_menu_item_icon_ripple.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~
+  ~ Copyright (C) 2019 Google Inc.
+  ~
+  ~ 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:state_focused="true" android:state_pressed="true">
+        <shape android:shape="oval">
+            <solid android:color="#8A94CBFF"/>
+            <stroke android:width="4dp"
+                    android:color="#94CBFF"/>
+            <size android:width="48dp"
+                  android:height="48dp"/>
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape android:shape="oval">
+            <solid android:color="#3D94CBFF"/>
+            <stroke android:width="8dp"
+                    android:color="#94CBFF"/>
+            <size android:width="48dp"
+                  android:height="48dp"/>
+        </shape>
+    </item>
+    <item>
+        <ripple android:color="#27ffffff">
+            <item android:id="@android:id/mask">
+                <shape android:shape="oval">
+                    <solid android:color="#FFFFFF"/>
+                </shape>
+            </item>
+        </ripple>
+    </item>
+</selector>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml
new file mode 100644
index 0000000..d988179
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl-port/car_ui_base_layout_toolbar.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<!-- This is for the two-row version of the toolbar -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:tag="carUiToolbar">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_base_layout_content_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.FocusArea
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
+
+            <androidx.constraintlayout.widget.Guideline
+                android:id="@+id/car_ui_toolbar_row_separator_guideline"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintGuide_begin="96dp"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+                android:layout_width="@dimen/car_ui_toolbar_margin"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    style="@style/Widget.CarUi.Toolbar.NavIcon"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"
+                    android:tint="@color/car_ui_text_color_primary"/>
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                android:layout_width="112dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginRight="112dp"
+                          app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                          app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintRight_toRightOf="parent"
+                          app:layout_constraintTop_toTopOf="parent" >
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="?android:attr/textAppearanceSmall"/>
+            </LinearLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+                android:showDividers="beginning|middle|end"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="match_parent"
+                android:layout_height="96dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline" />
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintLeft_toLeftOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_base_layout_toolbar.xml
new file mode 100644
index 0000000..52c9f3f
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_base_layout_toolbar.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:tag="CarUiBaseLayoutToolbar">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_base_layout_content_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.FocusArea
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            android:layout_width="match_parent"
+            android:layout_height="96dp"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+                android:layout_width="@dimen/car_ui_toolbar_margin"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    style="@style/Widget.CarUi.Toolbar.NavIcon"
+                    android:tint="@color/car_ui_text_color_primary"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                android:layout_width="112dp"
+                android:layout_height="wrap_content"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginRight="112dp"
+                          app:layout_constraintBottom_toBottomOf="parent"
+                          app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintTop_toTopOf="parent"
+                          app:layout_constraintRight_toRightOf="parent">
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="?android:attr/textAppearanceSmall"/>
+            </LinearLayout>
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintRight_toLeftOf="@+id/car_ui_toolbar_title_logo_container"
+                app:layout_constraintHorizontal_bias="0.0"/>
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+                android:showDividers="beginning|middle|end"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"/>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toRightOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_recycler_view.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_recycler_view.xml
new file mode 100644
index 0000000..4847388
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_recycler_view.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <com.android.car.ui.recyclerview.CarUiRecyclerViewContainer
+        android:id="@+id/car_ui_recycler_view"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_marginStart="@dimen/car_ui_scrollbar_margin"
+        android:tag="carUiRecyclerView"
+        android:layout_weight="1"/>
+
+    <include layout="@layout/car_ui_recyclerview_scrollbar"/>
+</merge>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_recyclerview_scrollbar.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_recyclerview_scrollbar.xml
new file mode 100644
index 0000000..5896819
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_recyclerview_scrollbar.xml
@@ -0,0 +1,77 @@
+<?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.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="@dimen/car_ui_scrollbar_container_width"
+    android:layout_height="match_parent"
+    android:id="@+id/car_ui_scroll_bar"
+    android:gravity="center">
+
+    <ImageView
+        android:id="@+id/car_ui_scrollbar_page_up"
+        android:layout_width="@dimen/car_ui_scrollbar_button_size"
+        android:layout_height="@dimen/car_ui_scrollbar_button_size"
+        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
+        android:contentDescription="@string/car_ui_scrollbar_page_up_button"
+        android:focusable="false"
+        android:hapticFeedbackEnabled="false"
+        android:src="@drawable/car_ui_recyclerview_ic_up"
+        android:scaleType="centerInside"
+        android:layout_marginTop="15dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+
+    <!-- View height is dynamically calculated during layout. -->
+    <View
+        android:id="@+id/car_ui_scrollbar_thumb"
+        android:layout_width="@dimen/car_ui_scrollbar_thumb_width"
+        android:layout_height="0dp"
+        android:layout_gravity="center_horizontal"
+        android:background="@drawable/car_ui_recyclerview_scrollbar_thumb"
+        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+
+    <View
+        android:id="@+id/car_ui_scrollbar_track"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_marginTop="@dimen/car_ui_scrollbar_separator_margin"
+        android:layout_marginBottom="@dimen/car_ui_scrollbar_separator_margin"
+        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
+        app:layout_constraintBottom_toTopOf="@+id/car_ui_scrollbar_page_down"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <ImageView
+        android:id="@+id/car_ui_scrollbar_page_down"
+        android:layout_width="@dimen/car_ui_scrollbar_button_size"
+        android:layout_height="@dimen/car_ui_scrollbar_button_size"
+        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
+        android:contentDescription="@string/car_ui_scrollbar_page_down_button"
+        android:focusable="false"
+        android:hapticFeedbackEnabled="false"
+        android:src="@drawable/car_ui_recyclerview_ic_down"
+        android:scaleType="centerInside"
+        android:layout_marginBottom="15dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"/>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar.xml
new file mode 100644
index 0000000..2714f44
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020, 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.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/car_ui_toolbar_background"
+    android:layout_width="match_parent"
+    android:layout_height="96dp">
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_nav_icon_container"
+        style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+        android:layout_width="@dimen/car_ui_toolbar_margin"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_nav_icon"
+            style="@style/Widget.CarUi.Toolbar.NavIcon"
+            android:tint="@color/car_ui_text_color_primary"
+            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_title_logo_container"
+        android:layout_width="112dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_title_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <LinearLayout android:layout_height="wrap_content"
+                  android:layout_width="0dp"
+                  android:id="@+id/car_ui_toolbar_title_container"
+                  android:orientation="vertical"
+                  android:layout_marginRight="112dp"
+                  app:layout_constraintBottom_toBottomOf="parent"
+                  app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                  app:layout_constraintTop_toTopOf="parent"
+                  app:layout_constraintRight_toRightOf="parent">
+        <TextView android:id="@+id/car_ui_toolbar_title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+        <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:visibility="gone"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="?android:attr/textAppearanceSmall"/>
+    </LinearLayout>
+
+    <com.android.car.ui.toolbar.TabLayout
+        android:id="@+id/car_ui_toolbar_tabs"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+        app:layout_constraintRight_toLeftOf="@+id/car_ui_toolbar_title_logo_container"
+        app:layout_constraintHorizontal_bias="0.0"/>
+
+    <LinearLayout
+        android:id="@+id/car_ui_toolbar_menu_items_container"
+        android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+        android:showDividers="beginning|middle|end"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        android:orientation="horizontal"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_search_view_container"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ProgressBar
+        android:id="@+id/car_ui_toolbar_progress_bar"
+        style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:indeterminate="true"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar_two_row.xml b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar_two_row.xml
new file mode 100644
index 0000000..6935121
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-ldrtl/car_ui_toolbar_two_row.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2020, 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.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/car_ui_toolbar_background"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/car_ui_toolbar_row_separator_guideline"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:orientation="horizontal"
+        app:layout_constraintGuide_begin="96dp"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_nav_icon_container"
+        style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+        android:layout_width="@dimen/car_ui_toolbar_margin"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_nav_icon"
+            style="@style/Widget.CarUi.Toolbar.NavIcon"
+            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY"
+            android:tint="@color/car_ui_text_color_primary"/>
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_title_logo_container"
+        android:layout_width="112dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <ImageView
+            android:id="@+id/car_ui_toolbar_title_logo"
+            android:layout_width="@dimen/car_ui_toolbar_logo_size"
+            android:layout_height="@dimen/car_ui_toolbar_logo_size"
+            android:layout_gravity="center"
+            android:scaleType="fitXY" />
+    </FrameLayout>
+
+    <LinearLayout android:layout_height="wrap_content"
+                  android:layout_width="0dp"
+                  android:id="@+id/car_ui_toolbar_title_container"
+                  android:orientation="vertical"
+                  android:layout_marginRight="112dp"
+                  app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                  app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_menu_items_container"
+                  app:layout_constraintRight_toRightOf="parent"
+                  app:layout_constraintTop_toTopOf="parent" >
+        <TextView android:id="@+id/car_ui_toolbar_title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+        <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:visibility="gone"
+                  android:textAlignment="viewStart"
+                  android:textAppearance="?android:attr/textAppearanceSmall"/>
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_search_view_container"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintLeft_toRightOf="@+id/car_ui_toolbar_menu_items_container"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <LinearLayout
+        android:id="@+id/car_ui_toolbar_menu_items_container"
+        android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+        android:showDividers="beginning|middle|end"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        android:orientation="horizontal"
+        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+        app:layout_constraintLeft_toRightOf="@id/car_ui_toolbar_nav_icon_container"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.toolbar.TabLayout
+        android:id="@+id/car_ui_toolbar_tabs"
+        android:layout_width="match_parent"
+        android:layout_height="96dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline" />
+
+    <ProgressBar
+        android:id="@+id/car_ui_toolbar_progress_bar"
+        style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:indeterminate="true"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout-port/car_ui_base_layout_toolbar.xml b/car-ui-lib/referencedesign/res/layout-port/car_ui_base_layout_toolbar.xml
new file mode 100644
index 0000000..283baf8
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout-port/car_ui_base_layout_toolbar.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+<!-- This is for the two-row version of the toolbar -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:tag="CarUiBaseLayoutToolbar">
+
+    <!-- When not in touch mode, if we clear focus in current window, Android will re-focus the
+         first focusable view in the window automatically. Adding a FocusParkingView to the window
+         can fix this issue, because it can take focus, and it is transparent and its default focus
+         highlight is disabled, so it's invisible to the user no matter whether it's focused or not.
+         -->
+    <com.android.car.ui.FocusParkingView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <FrameLayout
+        android:id="@+id/car_ui_base_layout_content_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <com.android.car.ui.FocusArea
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:id="@+id/car_ui_toolbar_background"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="car_ui_top_inset"
+            app:layout_constraintTop_toTopOf="parent">
+            <com.android.car.ui.baselayout.ClickBlockingView
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintBottom_toBottomOf="parent"/>
+
+            <androidx.constraintlayout.widget.Guideline
+                android:id="@+id/car_ui_toolbar_row_separator_guideline"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintGuide_begin="96dp" />
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_nav_icon_container"
+                style="@style/Widget.CarUi.Toolbar.NavIconContainer"
+                android:layout_width="@dimen/car_ui_toolbar_margin"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_nav_icon"
+                    style="@style/Widget.CarUi.Toolbar.NavIcon"
+                    android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY"
+                    android:tint="@color/car_ui_text_color_primary"/>
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_title_logo_container"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent">
+
+                <ImageView
+                    android:id="@+id/car_ui_toolbar_title_logo"
+                    android:layout_width="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_height="@dimen/car_ui_toolbar_logo_size"
+                    android:layout_gravity="center"
+                    android:scaleType="fitXY" />
+            </FrameLayout>
+
+            <LinearLayout android:layout_height="wrap_content"
+                          android:layout_width="0dp"
+                          android:id="@+id/car_ui_toolbar_title_container"
+                          android:orientation="vertical"
+                          android:layout_marginStart="16dp"
+                          app:layout_goneMarginStart="0dp"
+                          app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                          app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_menu_items_container"
+                          app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_title_logo_container"
+                          app:layout_constraintTop_toTopOf="parent" >
+                <TextView android:id="@+id/car_ui_toolbar_title"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:singleLine="true"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="@style/TextAppearance.CarUi.Widget.Toolbar.Title"/>
+                <TextView android:id="@+id/car_ui_toolbar_subtitle"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:visibility="gone"
+                          android:textAlignment="viewStart"
+                          android:textAppearance="?android:attr/textAppearanceSmall"/>
+            </LinearLayout>
+
+            <FrameLayout
+                android:id="@+id/car_ui_toolbar_search_view_container"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
+                app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <LinearLayout
+                android:id="@+id/car_ui_toolbar_menu_items_container"
+                android:divider="@drawable/car_ui_toolbar_menu_item_divider"
+                android:showDividers="beginning|middle|end"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:orientation="horizontal"
+                app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator_guideline"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <com.android.car.ui.toolbar.TabLayout
+                android:id="@+id/car_ui_toolbar_tabs"
+                android:layout_width="match_parent"
+                android:layout_height="96dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline" />
+
+            <ProgressBar
+                android:id="@+id/car_ui_toolbar_progress_bar"
+                style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </com.android.car.ui.FocusArea>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/referencedesign/res/layout/car_ui_preference_widget_seekbar.xml b/car-ui-lib/referencedesign/res/layout/car_ui_preference_widget_seekbar.xml
new file mode 100644
index 0000000..16d4ea0
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout/car_ui_preference_widget_seekbar.xml
@@ -0,0 +1,92 @@
+<?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:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:orientation="horizontal"
+    android:background="@drawable/car_ui_seekbar_preference_background"
+    android:clipChildren="false"
+    android:clipToPadding="false">
+
+    <ImageView
+        android:id="@android:id/icon"
+        android:layout_width="44dp"
+        android:layout_height="44dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginBottom="16dp"
+        android:layout_marginEnd="16dp"
+        android:scaleType="fitCenter"
+        android:tint="@color/car_ui_text_color_primary"/>
+
+    <RelativeLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_marginTop="16dp"
+        android:layout_marginBottom="16dp"
+        android:clipChildren="false"
+        android:clipToPadding="false">
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="@style/TextAppearance.CarUi.PreferenceTitle"/>
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignStart="@android:id/title"
+            android:layout_below="@android:id/title"
+            android:textAppearance="@style/TextAppearance.CarUi.PreferenceSummary"/>
+
+        <!-- Using UnPressableLinearLayout as a workaround to disable the pressed state propagation
+        to the children of this container layout. Otherwise, the animated pressed state will also
+        play for the thumb in the AbsSeekBar in addition to the preference's ripple background.
+        The background of the SeekBar is also set to null to disable the ripple background -->
+        <androidx.preference.UnPressableLinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignStart="@android:id/title"
+            android:layout_below="@android:id/summary"
+            android:clipChildren="false"
+            android:clipToPadding="false">
+            <SeekBar
+                android:id="@+id/seekbar"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                style="@style/Widget.CarUi.SeekbarPreference.Seekbar"/>
+
+            <TextView
+                android:id="@+id/seekbar_value"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:visibility="gone"/>
+        </androidx.preference.UnPressableLinearLayout>
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/car-ui-lib/referencedesign/res/layout/car_ui_toolbar_menu_item.xml b/car-ui-lib/referencedesign/res/layout/car_ui_toolbar_menu_item.xml
new file mode 100644
index 0000000..18f2e16
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/layout/car_ui_toolbar_menu_item.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2020, 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:focusable="false">
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_menu_item_icon_container"
+        style="@style/Widget.CarUi.Toolbar.MenuItem.IndividualContainer"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@drawable/car_ui_toolbar_menu_item_icon_ripple">
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:src="@drawable/car_ui_toolbar_menu_item_icon_background"
+            android:scaleType="center"/>
+        <ImageView
+            android:id="@+id/car_ui_toolbar_menu_item_icon"
+            android:layout_width="44dp"
+            android:layout_height="44dp"
+            android:layout_gravity="center"
+            android:tint="@color/car_ui_toolbar_menu_item_icon_color"
+            android:tintMode="src_in"/>
+        <com.android.car.ui.uxr.DrawableStateSwitch
+            android:id="@+id/car_ui_toolbar_menu_item_switch"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:background="@null"
+            android:focusable="false"
+            android:clickable="false"/>
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/car_ui_toolbar_menu_item_text_container"
+        style="@style/Widget.CarUi.Toolbar.MenuItem.IndividualContainer"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="?android:attr/selectableItemBackground">
+        <!-- These buttons must have clickable="false" or they will steal the click events from the container -->
+        <com.android.car.ui.uxr.DrawableStateButton
+            android:id="@+id/car_ui_toolbar_menu_item_text"
+            style="@style/Widget.CarUi.Toolbar.TextButton"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:background="@null"
+            android:focusable="false"
+            android:clickable="false"/>
+        <com.android.car.ui.uxr.DrawableStateButton
+            android:id="@+id/car_ui_toolbar_menu_item_text_with_icon"
+            style="@style/Widget.CarUi.Toolbar.TextButton.WithIcon"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:background="@null"
+            android:focusable="false"
+            android:clickable="false"/>
+    </FrameLayout>
+</FrameLayout>
diff --git a/car-ui-lib/referencedesign/res/values-ldrtl/values.xml b/car-ui-lib/referencedesign/res/values-ldrtl/values.xml
index c83009d..24552a5 100644
--- a/car-ui-lib/referencedesign/res/values-ldrtl/values.xml
+++ b/car-ui-lib/referencedesign/res/values-ldrtl/values.xml
@@ -1,30 +1,17 @@
 <resources>
-    <item type="layout" name="car_ui_base_layout_toolbar">@*android:layout/car_ui_base_layout_toolbar</item>
-    <item type="layout" name="car_ui_toolbar">@*android:layout/car_ui_toolbar</item>
-    <item type="layout" name="car_ui_toolbar_two_row">@*android:layout/car_ui_toolbar_two_row</item>
-    <item type="bool" name="car_ui_toolbar_nav_icon_reserve_space">false</item>
-    <item type="bool" name="car_ui_toolbar_logo_fills_nav_icon_space">false</item>
+    <bool name="car_ui_toolbar_nav_icon_reserve_space">false</bool>
+    <bool name="car_ui_toolbar_logo_fills_nav_icon_space">false</bool>
 
-    <item type="id" name="car_ui_toolbar_background">@*android:id/car_ui_toolbar_background</item>
-    <item type="id" name="car_ui_toolbar_nav_icon_container">@*android:id/car_ui_toolbar_nav_icon_container</item>
-    <item type="id" name="car_ui_toolbar_nav_icon">@*android:id/car_ui_toolbar_nav_icon</item>
-    <item type="id" name="car_ui_toolbar_logo">@*android:id/car_ui_toolbar_logo</item>
-    <item type="id" name="car_ui_toolbar_title_logo">@*android:id/car_ui_toolbar_title_logo</item>
-    <item type="id" name="car_ui_toolbar_title_container">@*android:id/car_ui_toolbar_title_container</item>
-    <item type="id" name="car_ui_toolbar_menu_items_container">@*android:id/car_ui_toolbar_menu_items_container</item>
-    <item type="id" name="car_ui_toolbar_title">@*android:id/car_ui_toolbar_title</item>
-    <item type="id" name="car_ui_toolbar_subtitle">@*android:id/car_ui_toolbar_subtitle</item>
-    <item type="id" name="car_ui_toolbar_tabs">@*android:id/car_ui_toolbar_tabs</item>
-    <item type="id" name="car_ui_toolbar_search_view_container">@*android:id/car_ui_toolbar_search_view_container</item>
-    <item type="id" name="car_ui_toolbar_progress_bar">@*android:id/car_ui_toolbar_progress_bar</item>
-    <item type="id" name="car_ui_toolbar_title_logo_container">@*android:id/car_ui_toolbar_title_logo_container</item>
-    <item type="id" name="car_ui_base_layout_content_container">@*android:id/car_ui_base_layout_content_container</item>
+    <dimen name="car_ui_scrollbar_margin">112dp</dimen>
+    <dimen name="car_ui_scrollbar_container_width">112dp</dimen>
+    <dimen name="car_ui_scrollbar_button_size">76dp</dimen>
+    <dimen name="car_ui_scrollbar_thumb_width">7dp</dimen>
+    <dimen name="car_ui_scrollbar_separator_margin">16dp</dimen>
 
-     <item type="layout" name="car_ui_recycler_view">@*android:layout/car_ui_recycler_view</item>
-     <item type="id" name="car_ui_recycler_view">@*android:id/car_ui_recycler_view</item>
-     <item type="id" name="car_ui_scroll_bar">@*android:id/car_ui_scroll_bar</item>
-     <item type="id" name="car_ui_scrollbar_page_up">@*android:id/car_ui_scrollbar_page_up</item>
-     <item type="id" name="car_ui_scrollbar_thumb">@*android:id/car_ui_scrollbar_thumb</item>
-     <item type="id" name="car_ui_scrollbar_track">@*android:id/car_ui_scrollbar_track</item>
-     <item type="id" name="car_ui_scrollbar_page_down">@*android:id/car_ui_scrollbar_page_down</item>
+    <string name="car_ui_scrollbar_page_up_button">Scroll up</string>
+    <string name="car_ui_scrollbar_page_down_button">Scroll down</string>
+
+    <color name="car_ui_ripple_color">#27ffffff</color>
+    <color name="car_ui_scrollbar_thumb">#99ffffff</color>
+    <dimen name="car_ui_scrollbar_thumb_radius">100dp</dimen>
 </resources>
diff --git a/car-ui-lib/referencedesign/res/values-night/colors.xml b/car-ui-lib/referencedesign/res/values-night/colors.xml
new file mode 100644
index 0000000..42d706d
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values-night/colors.xml
@@ -0,0 +1,21 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2020 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>
+    <!-- Rotary focus -->
+
+    <color name="car_ui_rotary_focus_stroke_color">#94CBFF</color>
+    <color name="car_ui_rotary_focus_fill_color">#3D94CBFF</color>
+</resources>
diff --git a/car-ui-lib/referencedesign/res/values-port/bools.xml b/car-ui-lib/referencedesign/res/values-port/bools.xml
index ac4c389..16f3724 100644
--- a/car-ui-lib/referencedesign/res/values-port/bools.xml
+++ b/car-ui-lib/referencedesign/res/values-port/bools.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright (C) 2020 The Android Open Source Project
+  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.
diff --git a/car-ui-lib/referencedesign/res/values-port/values.xml b/car-ui-lib/referencedesign/res/values-port/values.xml
deleted file mode 100644
index c069d81..0000000
--- a/car-ui-lib/referencedesign/res/values-port/values.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<resources>
-     <item type="layout" name="car_ui_base_layout_toolbar">@*android:layout/car_ui_base_layout_toolbar</item>
-     <item type="id" name="car_ui_base_layout_content_container">@*android:id/car_ui_base_layout_content_container</item>
-     <item type="id" name="car_ui_toolbar_background">@*android:id/car_ui_toolbar_background</item>
-     <item type="id" name="car_ui_toolbar_row_separator_guideline">@*android:id/car_ui_toolbar_row_separator_guideline</item>
-     <item type="id" name="car_ui_toolbar_nav_icon_container">@*android:id/car_ui_toolbar_nav_icon_container</item>
-     <item type="id" name="car_ui_toolbar_nav_icon">@*android:id/car_ui_toolbar_nav_icon</item>
-     <item type="id" name="car_ui_toolbar_logo">@*android:id/car_ui_toolbar_logo</item>
-     <item type="id" name="car_ui_toolbar_title_logo_container">@*android:id/car_ui_toolbar_title_logo_container</item>
-     <item type="id" name="car_ui_toolbar_title_logo">@*android:id/car_ui_toolbar_title_logo</item>
-     <item type="id" name="car_ui_toolbar_title_container">@*android:id/car_ui_toolbar_title_container</item>
-     <item type="id" name="car_ui_toolbar_title">@*android:id/car_ui_toolbar_title</item>
-     <item type="id" name="car_ui_toolbar_subtitle">@*android:id/car_ui_toolbar_subtitle</item>
-     <item type="id" name="car_ui_toolbar_search_view_container">@*android:id/car_ui_toolbar_search_view_container</item>
-     <item type="id" name="car_ui_toolbar_menu_items_container">@*android:id/car_ui_toolbar_menu_items_container</item>
-     <item type="id" name="car_ui_toolbar_tabs">@*android:id/car_ui_toolbar_tabs</item>
-     <item type="id" name="car_ui_toolbar_progress_bar">@*android:id/car_ui_toolbar_progress_bar</item>
-</resources>
diff --git a/car-ui-lib/referencedesign/res/values/attrs.xml b/car-ui-lib/referencedesign/res/values/attrs.xml
new file mode 100644
index 0000000..0708c10
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values/attrs.xml
@@ -0,0 +1,61 @@
+<resources>
+    <!-- ConstraintLayout attributes. For a more complete list, see: -->
+    <!-- https://android.googlesource.com/platform/frameworks/opt/sherpa/+/studio-3.0/constraintlayout/src/main/res/values/attrs.xml -->
+
+    <attr name="layout_constraintGuide_begin" format="dimension"/>
+    <attr name="layout_constraintGuide_end" format="dimension"/>
+    <attr name="layout_constraintGuide_percent" format="float"/>
+
+    <attr name="layout_constraintLeft_toLeftOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintLeft_toRightOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintRight_toLeftOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintRight_toRightOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintTop_toTopOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintTop_toBottomOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintBottom_toTopOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintBottom_toBottomOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintBaseline_toBaselineOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintStart_toEndOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintStart_toStartOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintEnd_toStartOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+    <attr name="layout_constraintEnd_toEndOf" format="reference|enum">
+        <enum name="parent" value="0"/>
+    </attr>
+
+    <attr name="layout_constraintHorizontal_bias" format="float"/>
+    <attr name="layout_constraintVertical_bias" format="float"/>
+
+    <attr name="layout_goneMarginLeft" format="dimension"/>
+    <attr name="layout_goneMarginTop" format="dimension"/>
+    <attr name="layout_goneMarginRight" format="dimension"/>
+    <attr name="layout_goneMarginBottom" format="dimension"/>
+    <attr name="layout_goneMarginStart" format="dimension"/>
+    <attr name="layout_goneMarginEnd" format="dimension"/>
+
+    <attr name="state_ux_restricted" format="boolean"/>
+
+</resources>
diff --git a/car-ui-lib/referencedesign/res/values/dimens.xml b/car-ui-lib/referencedesign/res/values/dimens.xml
new file mode 100644
index 0000000..80fc15b
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values/dimens.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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>
+    <dimen name="car_ui_toolbar_margin">76dp</dimen>
+</resources>
diff --git a/car-ui-lib/referencedesign/res/values/styles.xml b/car-ui-lib/referencedesign/res/values/styles.xml
new file mode 100644
index 0000000..433911c
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values/styles.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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 xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="Widget.CarUi" parent="android:Widget.DeviceDefault"/>
+
+    <style name="Widget.CarUi.Toolbar"/>
+
+    <style name="Widget.CarUi.Toolbar.NavIconContainer">
+        <item name="android:layout_marginVertical">10dp</item>
+        <item name="android:layout_marginHorizontal">18dp</item>
+        <item name="android:background">@drawable/car_ui_toolbar_menu_item_icon_ripple</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.NavIcon">
+        <item name="android:tint">@color/car_ui_text_color_primary</item>
+        <item name="android:src">@drawable/car_ui_icon_arrow_back</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.MenuItem"/>
+
+    <style name="Widget.CarUi.Toolbar.MenuItem.IndividualContainer">
+        <item name="android:minHeight">76dp</item>
+        <item name="android:minWidth">76dp</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:focusable">true</item>
+    </style>
+
+    <style name="Widget.CarUi.Button.Borderless.Colored"
+           parent="android:Widget.DeviceDefault.Button.Borderless.Colored"/>
+
+    <style name="Widget.CarUi.Toolbar.TextButton" parent="Widget.CarUi.Button.Borderless.Colored">
+        <item name="android:drawableTint">@color/car_ui_toolbar_menu_item_icon_color</item>
+        <item name="android:drawablePadding">10dp</item>
+        <item name="android:maxWidth">350dp</item>
+    </style>
+
+    <style name="Widget.CarUi.Toolbar.TextButton.WithIcon">
+        <item name="android:textColor">@color/car_ui_toolbar_menu_item_icon_color</item>
+    </style>
+
+    <style name="Widget.CarUi.SeekbarPreference"/>
+
+    <!-- Style applied to the seekbar widget within the seekbar preference -->
+    <style name="Widget.CarUi.SeekbarPreference.Seekbar">
+        <item name="android:background">@null</item>
+        <item name="android:clickable">false</item>
+        <item name="android:focusable">false</item>
+        <item name="android:thumb">@drawable/car_ui_seekbar_thumb</item>
+        <item name="android:splitTrack">false</item>
+    </style>
+
+    <style name="TextAppearance.CarUi" parent="android:TextAppearance.DeviceDefault">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Body1">
+        <item name="android:textSize">32sp</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.PreferenceTitle" parent="TextAppearance.CarUi.Body1"/>
+
+    <style name="TextAppearance.CarUi.Body3">
+        <item name="android:textSize">24sp</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.PreferenceSummary" parent="TextAppearance.CarUi.Body3">
+        <item name="android:textColor">@color/car_ui_text_color_secondary</item>
+    </style>
+
+</resources>
diff --git a/car-ui-lib/referencedesign/res/values/values.xml b/car-ui-lib/referencedesign/res/values/values.xml
new file mode 100644
index 0000000..0cbb8ee
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/values/values.xml
@@ -0,0 +1,15 @@
+<resources>
+    <style name="TextAppearance.CarUi.Widget" parent="android:TextAppearance.DeviceDefault.Widget">
+        <item name="android:textAlignment">viewStart</item>
+    </style>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar"/>
+
+    <style name="TextAppearance.CarUi.Widget.Toolbar.Title">
+        <item name="android:singleLine">true</item>
+        <item name="android:textSize">32sp</item>
+    </style>
+
+    <dimen name="car_ui_toolbar_logo_size">44dp</dimen>
+    <dimen name="car_ui_toolbar_nav_icon_size">44dp</dimen>
+</resources>
diff --git a/car-ui-lib/referencedesign/res/xml/overlays.xml b/car-ui-lib/referencedesign/res/xml/overlays.xml
new file mode 100644
index 0000000..cc9b092
--- /dev/null
+++ b/car-ui-lib/referencedesign/res/xml/overlays.xml
@@ -0,0 +1,104 @@
+<overlay>
+    <item target="layout/car_ui_base_layout_toolbar" value="@layout/car_ui_base_layout_toolbar"/>
+    <item target="layout/car_ui_toolbar" value="@layout/car_ui_toolbar"/>
+    <item target="layout/car_ui_toolbar_two_row" value="@layout/car_ui_toolbar_two_row"/>
+    <item target="layout/car_ui_toolbar_menu_item" value="@layout/car_ui_toolbar_menu_item"/>
+    <item target="layout/car_ui_preference_widget_seekbar" value="@layout/car_ui_preference_widget_seekbar"/>
+
+    <item target="drawable/car_ui_icon_arrow_back" value="@drawable/car_ui_icon_arrow_back"/>
+    <item target="drawable/car_ui_toolbar_menu_item_icon_ripple" value="@drawable/car_ui_toolbar_menu_item_icon_ripple"/>
+    <item target="drawable/car_ui_toolbar_menu_item_icon_background" value="@drawable/car_ui_toolbar_menu_item_icon_background"/>
+    <item target="drawable/car_ui_toolbar_menu_item_icon_background" value="@drawable/car_ui_toolbar_menu_item_icon_background"/>
+
+    <item target="style/Widget.CarUi" value="@style/Widget.CarUi"/>
+    <item target="style/Widget.CarUi.Toolbar" value="@style/Widget.CarUi.Toolbar"/>
+    <item target="style/Widget.CarUi.Toolbar.NavIconContainer" value="@style/Widget.CarUi.Toolbar.NavIconContainer"/>
+    <item target="style/Widget.CarUi.Toolbar.NavIcon" value="@style/Widget.CarUi.Toolbar.NavIcon"/>
+    <item target="style/Widget.CarUi.Toolbar.MenuItem" value="@style/Widget.CarUi.Toolbar.MenuItem"/>
+    <item target="style/Widget.CarUi.Toolbar.MenuItem.IndividualContainer" value="@style/Widget.CarUi.Toolbar.MenuItem.IndividualContainer"/>
+    <item target="style/Widget.CarUi.Button.Borderless.Colored" value="@style/Widget.CarUi.Button.Borderless.Colored"/>
+    <item target="style/Widget.CarUi.Toolbar.TextButton" value="@style/Widget.CarUi.Toolbar.TextButton"/>
+    <item target="style/Widget.CarUi.Toolbar.TextButton.WithIcon" value="@style/Widget.CarUi.Toolbar.TextButton.WithIcon"/>
+    <item target="style/Widget.CarUi.SeekbarPreference" value="@style/Widget.CarUi.SeekbarPreference"/>
+    <item target="style/Widget.CarUi.SeekbarPreference.Seekbar" value="@style/Widget.CarUi.SeekbarPreference.Seekbar"/>
+
+    <item target="dimen/car_ui_toolbar_margin" value="@dimen/car_ui_toolbar_margin"/>
+
+    <item target="color/car_ui_text_color_secondary" value="@color/car_ui_text_color_secondary"/>
+    <item target="color/car_ui_toolbar_menu_item_icon_background_color" value="@color/car_ui_toolbar_menu_item_icon_background_color"/>
+    <item target="color/car_ui_toolbar_menu_item_icon_color" value="@color/car_ui_toolbar_menu_item_icon_color"/>
+
+    <item target="drawable/car_ui_icon_arrow_back" value="@drawable/car_ui_icon_arrow_back"/>
+    <item target="drawable/car_ui_toolbar_menu_item_icon_ripple" value="@drawable/car_ui_toolbar_menu_item_icon_ripple"/>
+
+    <item target="style/TextAppearance.CarUi" value="@style/TextAppearance.CarUi"/>
+    <item target="style/TextAppearance.CarUi.Body1" value="@style/TextAppearance.CarUi.Body1"/>
+    <item target="style/TextAppearance.CarUi.PreferenceTitle" value="@style/TextAppearance.CarUi.PreferenceTitle"/>
+    <item target="style/TextAppearance.CarUi.Body3" value="@style/TextAppearance.CarUi.Body3"/>
+    <item target="style/TextAppearance.CarUi.PreferenceSummary" value="@style/TextAppearance.CarUi.PreferenceSummary"/>
+
+    <item target="style/Widget.CarUi" value="@style/Widget.CarUi"/>
+    <item target="style/Widget.CarUi.Toolbar" value="@style/Widget.CarUi.Toolbar"/>
+    <item target="style/Widget.CarUi.Toolbar.NavIconContainer" value="@style/Widget.CarUi.Toolbar.NavIconContainer"/>
+    <item target="style/Widget.CarUi.Toolbar.NavIcon" value="@style/Widget.CarUi.Toolbar.NavIcon"/>
+
+    <item target="dimen/car_ui_toolbar_margin" value="@dimen/car_ui_toolbar_margin"/>
+    <item target="layout/car_ui_recycler_view" value="@layout/car_ui_recycler_view"/>
+
+    <item target="bool/car_ui_toolbar_nav_icon_reserve_space" value="@bool/car_ui_toolbar_nav_icon_reserve_space" />
+    <item target="bool/car_ui_toolbar_logo_fills_nav_icon_space" value="@bool/car_ui_toolbar_logo_fills_nav_icon_space" />
+    <item target="bool/car_ui_toolbar_tab_flexible_layout" value="@bool/car_ui_toolbar_tab_flexible_layout" />
+    <item target="bool/car_ui_toolbar_tabs_on_second_row" value="@bool/car_ui_toolbar_tabs_on_second_row" />
+
+    <item target="id/car_ui_toolbar_background" value="@id/car_ui_toolbar_background" />
+    <item target="id/car_ui_toolbar_nav_icon_container" value="@id/car_ui_toolbar_nav_icon_container" />
+    <item target="id/car_ui_toolbar_nav_icon" value="@id/car_ui_toolbar_nav_icon" />
+    <item target="id/car_ui_toolbar_logo" value="@id/car_ui_toolbar_logo" />
+    <item target="id/car_ui_toolbar_title_logo_container" value="@id/car_ui_toolbar_title_logo_container" />
+    <item target="id/car_ui_toolbar_title_logo" value="@id/car_ui_toolbar_title_logo" />
+    <item target="id/car_ui_toolbar_title" value="@id/car_ui_toolbar_title" />
+    <item target="id/car_ui_toolbar_title_container" value="@id/car_ui_toolbar_title_container" />
+    <item target="id/car_ui_toolbar_subtitle" value="@id/car_ui_toolbar_subtitle" />
+    <item target="id/car_ui_toolbar_tabs" value="@id/car_ui_toolbar_tabs" />
+    <item target="id/car_ui_toolbar_menu_items_container" value="@id/car_ui_toolbar_menu_items_container" />
+    <item target="id/car_ui_toolbar_search_view_container" value="@id/car_ui_toolbar_search_view_container" />
+    <item target="id/car_ui_toolbar_progress_bar" value="@id/car_ui_toolbar_progress_bar" />
+    <item target="id/car_ui_base_layout_content_container" value="@id/car_ui_base_layout_content_container" />
+    <item target="id/car_ui_toolbar_menu_item_icon_container" value="@id/car_ui_toolbar_menu_item_icon_container"/>
+    <item target="id/car_ui_toolbar_menu_item_icon" value="@id/car_ui_toolbar_menu_item_icon"/>
+    <item target="id/car_ui_toolbar_menu_item_switch" value="@id/car_ui_toolbar_menu_item_switch"/>
+    <item target="id/car_ui_toolbar_menu_item_text_container" value="@id/car_ui_toolbar_menu_item_text_container"/>
+    <item target="id/car_ui_toolbar_menu_item_text" value="@id/car_ui_toolbar_menu_item_text"/>
+    <item target="id/car_ui_toolbar_menu_item_text_with_icon" value="@id/car_ui_toolbar_menu_item_text_with_icon"/>
+    <item target="id/seekbar" value="@id/seekbar"/>
+    <item target="id/seekbar_value" value="@id/seekbar_value"/>
+    <item target="id/car_ui_recycler_view" value="@id/car_ui_recycler_view" />
+    <item target="id/car_ui_scroll_bar" value="@id/car_ui_scroll_bar"/>
+    <item target="id/car_ui_scrollbar_page_down" value="@id/car_ui_scrollbar_page_down"/>
+    <item target="id/car_ui_scrollbar_page_up" value="@id/car_ui_scrollbar_page_up"/>
+    <item target="id/car_ui_scrollbar_thumb" value="@id/car_ui_scrollbar_thumb"/>
+    <item target="id/car_ui_scrollbar_track" value="@id/car_ui_scrollbar_track"/>
+
+    <item target="attr/layout_constraintGuide_begin" value="@attr/layout_constraintGuide_begin"/>
+    <item target="attr/layout_constraintGuide_end" value="@attr/layout_constraintGuide_end"/>
+    <item target="attr/layout_constraintStart_toStartOf" value="@attr/layout_constraintStart_toStartOf"/>
+    <item target="attr/layout_constraintStart_toEndOf" value="@attr/layout_constraintStart_toEndOf"/>
+    <item target="attr/layout_constraintEnd_toStartOf" value="@attr/layout_constraintEnd_toStartOf"/>
+    <item target="attr/layout_constraintEnd_toEndOf" value="@attr/layout_constraintEnd_toEndOf"/>
+    <item target="attr/layout_constraintLeft_toLeftOf" value="@attr/layout_constraintLeft_toLeftOf"/>
+    <item target="attr/layout_constraintLeft_toRightOf" value="@attr/layout_constraintLeft_toRightOf"/>
+    <item target="attr/layout_constraintRight_toLeftOf" value="@attr/layout_constraintRight_toLeftOf"/>
+    <item target="attr/layout_constraintRight_toRightOf" value="@attr/layout_constraintRight_toRightOf"/>
+    <item target="attr/layout_constraintTop_toTopOf" value="@attr/layout_constraintTop_toTopOf"/>
+    <item target="attr/layout_constraintTop_toBottomOf" value="@attr/layout_constraintTop_toBottomOf"/>
+    <item target="attr/layout_constraintBottom_toTopOf" value="@attr/layout_constraintBottom_toTopOf"/>
+    <item target="attr/layout_constraintBottom_toBottomOf" value="@attr/layout_constraintBottom_toBottomOf"/>
+    <item target="attr/layout_constraintHorizontal_bias" value="@attr/layout_constraintHorizontal_bias"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginLeft"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginRight"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginTop"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginBottom"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginStart"/>
+    <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginEnd"/>
+    <item target="attr/state_ux_restricted" value="@attr/state_ux_restricted"/>
+</overlay>
diff --git a/car-ui-lib/res-overlayable/values/overlayable.xml b/car-ui-lib/res-overlayable/values/overlayable.xml
deleted file mode 100644
index 821cc50..0000000
--- a/car-ui-lib/res-overlayable/values/overlayable.xml
+++ /dev/null
@@ -1,465 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--Copyright (C) 2020 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.-->
-<!--THIS FILE IS AUTO GENERATED, DO NOT EDIT MANUALLY.-->
-<resources>
-  <overlayable name="car-ui-lib">
-    <policy type="public">
-      <item type="attr" name="CarUiToolbarStyle"/>
-      <item type="attr" name="barrierDirection"/>
-      <item type="attr" name="carUiPreferenceStyle"/>
-      <item type="attr" name="carUiRecyclerViewStyle"/>
-      <item type="attr" name="chainUseRtl"/>
-      <item type="attr" name="constraintSet"/>
-      <item type="attr" name="constraint_referenced_ids"/>
-      <item type="attr" name="layout_constraintBaseline_creator"/>
-      <item type="attr" name="layout_constraintBaseline_toBaselineOf"/>
-      <item type="attr" name="layout_constraintBottom_creator"/>
-      <item type="attr" name="layout_constraintBottom_toBottomOf"/>
-      <item type="attr" name="layout_constraintBottom_toTopOf"/>
-      <item type="attr" name="layout_constraintDimensionRatio"/>
-      <item type="attr" name="layout_constraintEnd_toEndOf"/>
-      <item type="attr" name="layout_constraintEnd_toStartOf"/>
-      <item type="attr" name="layout_constraintGuide_begin"/>
-      <item type="attr" name="layout_constraintGuide_end"/>
-      <item type="attr" name="layout_constraintGuide_percent"/>
-      <item type="attr" name="layout_constraintHeight_default"/>
-      <item type="attr" name="layout_constraintHeight_max"/>
-      <item type="attr" name="layout_constraintHeight_min"/>
-      <item type="attr" name="layout_constraintHeight_percent"/>
-      <item type="attr" name="layout_constraintHorizontal_bias"/>
-      <item type="attr" name="layout_constraintHorizontal_chainStyle"/>
-      <item type="attr" name="layout_constraintHorizontal_weight"/>
-      <item type="attr" name="layout_constraintLeft_creator"/>
-      <item type="attr" name="layout_constraintLeft_toLeftOf"/>
-      <item type="attr" name="layout_constraintLeft_toRightOf"/>
-      <item type="attr" name="layout_constraintRight_creator"/>
-      <item type="attr" name="layout_constraintRight_toLeftOf"/>
-      <item type="attr" name="layout_constraintRight_toRightOf"/>
-      <item type="attr" name="layout_constraintStart_toEndOf"/>
-      <item type="attr" name="layout_constraintStart_toStartOf"/>
-      <item type="attr" name="layout_constraintTop_creator"/>
-      <item type="attr" name="layout_constraintTop_toBottomOf"/>
-      <item type="attr" name="layout_constraintTop_toTopOf"/>
-      <item type="attr" name="layout_constraintVertical_bias"/>
-      <item type="attr" name="layout_constraintVertical_chainStyle"/>
-      <item type="attr" name="layout_constraintVertical_weight"/>
-      <item type="attr" name="layout_constraintWidth_default"/>
-      <item type="attr" name="layout_constraintWidth_max"/>
-      <item type="attr" name="layout_constraintWidth_min"/>
-      <item type="attr" name="layout_constraintWidth_percent"/>
-      <item type="attr" name="layout_editor_absoluteX"/>
-      <item type="attr" name="layout_editor_absoluteY"/>
-      <item type="attr" name="layout_goneMarginBottom"/>
-      <item type="attr" name="layout_goneMarginEnd"/>
-      <item type="attr" name="layout_goneMarginLeft"/>
-      <item type="attr" name="layout_goneMarginRight"/>
-      <item type="attr" name="layout_goneMarginStart"/>
-      <item type="attr" name="layout_goneMarginTop"/>
-      <item type="attr" name="layout_optimizationLevel"/>
-      <item type="attr" name="state_ux_restricted"/>
-      <item type="attr" name="title"/>
-      <item type="bool" name="car_ui_list_item_single_line_title"/>
-      <item type="bool" name="car_ui_preference_list_show_full_screen"/>
-      <item type="bool" name="car_ui_preference_show_chevron"/>
-      <item type="bool" name="car_ui_scrollbar_enable"/>
-      <item type="bool" name="car_ui_toolbar_logo_fills_nav_icon_space"/>
-      <item type="bool" name="car_ui_toolbar_nav_icon_reserve_space"/>
-      <item type="bool" name="car_ui_toolbar_show_logo"/>
-      <item type="bool" name="car_ui_toolbar_tab_flexible_layout"/>
-      <item type="bool" name="car_ui_toolbar_tabs_on_second_row"/>
-      <item type="color" name="car_ui_activity_background_color"/>
-      <item type="color" name="car_ui_color_accent"/>
-      <item type="color" name="car_ui_list_item_body_text_color"/>
-      <item type="color" name="car_ui_list_item_divider"/>
-      <item type="color" name="car_ui_list_item_header_text_color"/>
-      <item type="color" name="car_ui_list_item_title_text_color"/>
-      <item type="color" name="car_ui_preference_category_title_text_color"/>
-      <item type="color" name="car_ui_preference_edit_text_dialog_message_text_color"/>
-      <item type="color" name="car_ui_preference_icon_color"/>
-      <item type="color" name="car_ui_preference_summary_text_color"/>
-      <item type="color" name="car_ui_preference_switch_track_text_color"/>
-      <item type="color" name="car_ui_preference_title_text_color"/>
-      <item type="color" name="car_ui_recyclerview_divider_color"/>
-      <item type="color" name="car_ui_ripple_color"/>
-      <item type="color" name="car_ui_scrollbar_thumb"/>
-      <item type="color" name="car_ui_text_color_hint"/>
-      <item type="color" name="car_ui_text_color_primary"/>
-      <item type="color" name="car_ui_text_color_secondary"/>
-      <item type="color" name="car_ui_toolbar_menu_item_icon_background_color"/>
-      <item type="color" name="car_ui_toolbar_menu_item_icon_color"/>
-      <item type="color" name="car_ui_toolbar_nav_icon_color"/>
-      <item type="color" name="car_ui_toolbar_search_hint_text_color"/>
-      <item type="color" name="car_ui_toolbar_tab_item_selector"/>
-      <item type="color" name="car_ui_toolbar_tab_selected_color"/>
-      <item type="color" name="car_ui_toolbar_tab_unselected_color"/>
-      <item type="dimen" name="car_ui_body1_size"/>
-      <item type="dimen" name="car_ui_body2_size"/>
-      <item type="dimen" name="car_ui_body3_size"/>
-      <item type="dimen" name="car_ui_button_disabled_alpha"/>
-      <item type="dimen" name="car_ui_dialog_edittext_height"/>
-      <item type="dimen" name="car_ui_dialog_edittext_margin_bottom"/>
-      <item type="dimen" name="car_ui_dialog_edittext_margin_end"/>
-      <item type="dimen" name="car_ui_dialog_edittext_margin_start"/>
-      <item type="dimen" name="car_ui_dialog_edittext_margin_top"/>
-      <item type="dimen" name="car_ui_dialog_icon_size"/>
-      <item type="dimen" name="car_ui_dialog_title_margin"/>
-      <item type="dimen" name="car_ui_header_list_item_text_start_margin"/>
-      <item type="dimen" name="car_ui_letter_spacing_body1"/>
-      <item type="dimen" name="car_ui_letter_spacing_body3"/>
-      <item type="dimen" name="car_ui_list_item_action_divider_height"/>
-      <item type="dimen" name="car_ui_list_item_action_divider_width"/>
-      <item type="dimen" name="car_ui_list_item_avatar_icon_height"/>
-      <item type="dimen" name="car_ui_list_item_avatar_icon_width"/>
-      <item type="dimen" name="car_ui_list_item_body_text_size"/>
-      <item type="dimen" name="car_ui_list_item_check_box_end_inset"/>
-      <item type="dimen" name="car_ui_list_item_check_box_height"/>
-      <item type="dimen" name="car_ui_list_item_check_box_icon_container_width"/>
-      <item type="dimen" name="car_ui_list_item_check_box_start_inset"/>
-      <item type="dimen" name="car_ui_list_item_content_icon_height"/>
-      <item type="dimen" name="car_ui_list_item_content_icon_width"/>
-      <item type="dimen" name="car_ui_list_item_end_inset"/>
-      <item type="dimen" name="car_ui_list_item_header_height"/>
-      <item type="dimen" name="car_ui_list_item_header_start_inset"/>
-      <item type="dimen" name="car_ui_list_item_header_text_size"/>
-      <item type="dimen" name="car_ui_list_item_height"/>
-      <item type="dimen" name="car_ui_list_item_icon_container_width"/>
-      <item type="dimen" name="car_ui_list_item_icon_size"/>
-      <item type="dimen" name="car_ui_list_item_radio_button_end_inset"/>
-      <item type="dimen" name="car_ui_list_item_radio_button_height"/>
-      <item type="dimen" name="car_ui_list_item_radio_button_icon_container_width"/>
-      <item type="dimen" name="car_ui_list_item_radio_button_start_inset"/>
-      <item type="dimen" name="car_ui_list_item_start_inset"/>
-      <item type="dimen" name="car_ui_list_item_supplemental_icon_size"/>
-      <item type="dimen" name="car_ui_list_item_text_no_icon_start_margin"/>
-      <item type="dimen" name="car_ui_list_item_text_start_margin"/>
-      <item type="dimen" name="car_ui_list_item_title_text_size"/>
-      <item type="dimen" name="car_ui_margin"/>
-      <item type="dimen" name="car_ui_padding_0"/>
-      <item type="dimen" name="car_ui_padding_1"/>
-      <item type="dimen" name="car_ui_padding_2"/>
-      <item type="dimen" name="car_ui_padding_3"/>
-      <item type="dimen" name="car_ui_padding_4"/>
-      <item type="dimen" name="car_ui_padding_5"/>
-      <item type="dimen" name="car_ui_padding_6"/>
-      <item type="dimen" name="car_ui_preference_category_icon_margin_end"/>
-      <item type="dimen" name="car_ui_preference_category_icon_size"/>
-      <item type="dimen" name="car_ui_preference_category_min_height"/>
-      <item type="dimen" name="car_ui_preference_category_text_size"/>
-      <item type="dimen" name="car_ui_preference_content_margin_bottom"/>
-      <item type="dimen" name="car_ui_preference_content_margin_top"/>
-      <item type="dimen" name="car_ui_preference_dropdown_padding_start"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_margin_bottom"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_margin_top"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_bottom"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_end"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_start"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_message_text_size"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_end"/>
-      <item type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_start"/>
-      <item type="dimen" name="car_ui_preference_icon_margin_end"/>
-      <item type="dimen" name="car_ui_preference_icon_size"/>
-      <item type="dimen" name="car_ui_preference_summary_text_size"/>
-      <item type="dimen" name="car_ui_preference_switch_height"/>
-      <item type="dimen" name="car_ui_preference_switch_text_size"/>
-      <item type="dimen" name="car_ui_preference_switch_width"/>
-      <item type="dimen" name="car_ui_preference_switch_width_half"/>
-      <item type="dimen" name="car_ui_preference_title_text_size"/>
-      <item type="dimen" name="car_ui_primary_icon_size"/>
-      <item type="dimen" name="car_ui_recyclerview_divider_bottom_margin"/>
-      <item type="dimen" name="car_ui_recyclerview_divider_end_margin"/>
-      <item type="dimen" name="car_ui_recyclerview_divider_height"/>
-      <item type="dimen" name="car_ui_recyclerview_divider_start_margin"/>
-      <item type="dimen" name="car_ui_recyclerview_divider_top_margin"/>
-      <item type="dimen" name="car_ui_scrollbar_button_size"/>
-      <item type="dimen" name="car_ui_scrollbar_container_width"/>
-      <item type="dimen" name="car_ui_scrollbar_decelerate_interpolator_factor"/>
-      <item type="dimen" name="car_ui_scrollbar_deceleration_times_divisor"/>
-      <item type="dimen" name="car_ui_scrollbar_margin"/>
-      <item type="dimen" name="car_ui_scrollbar_milliseconds_per_inch"/>
-      <item type="dimen" name="car_ui_scrollbar_min_thumb_height"/>
-      <item type="dimen" name="car_ui_scrollbar_padding_bottom"/>
-      <item type="dimen" name="car_ui_scrollbar_padding_top"/>
-      <item type="dimen" name="car_ui_scrollbar_separator_margin"/>
-      <item type="dimen" name="car_ui_scrollbar_thumb_radius"/>
-      <item type="dimen" name="car_ui_scrollbar_thumb_width"/>
-      <item type="dimen" name="car_ui_sub1_size"/>
-      <item type="dimen" name="car_ui_sub2_size"/>
-      <item type="dimen" name="car_ui_sub3_size"/>
-      <item type="dimen" name="car_ui_toolbar_bottom_inset"/>
-      <item type="dimen" name="car_ui_toolbar_bottom_view_height"/>
-      <item type="dimen" name="car_ui_toolbar_end_inset"/>
-      <item type="dimen" name="car_ui_toolbar_first_row_height"/>
-      <item type="dimen" name="car_ui_toolbar_logo_size"/>
-      <item type="dimen" name="car_ui_toolbar_margin"/>
-      <item type="dimen" name="car_ui_toolbar_menu_item_icon_background_size"/>
-      <item type="dimen" name="car_ui_toolbar_menu_item_icon_ripple_radius"/>
-      <item type="dimen" name="car_ui_toolbar_menu_item_icon_size"/>
-      <item type="dimen" name="car_ui_toolbar_menu_item_margin"/>
-      <item type="dimen" name="car_ui_toolbar_nav_icon_size"/>
-      <item type="dimen" name="car_ui_toolbar_row_height"/>
-      <item type="dimen" name="car_ui_toolbar_search_close_icon_container_width"/>
-      <item type="dimen" name="car_ui_toolbar_search_close_icon_size"/>
-      <item type="dimen" name="car_ui_toolbar_search_height"/>
-      <item type="dimen" name="car_ui_toolbar_search_search_icon_container_width"/>
-      <item type="dimen" name="car_ui_toolbar_search_search_icon_size"/>
-      <item type="dimen" name="car_ui_toolbar_second_row_height"/>
-      <item type="dimen" name="car_ui_toolbar_separator_height"/>
-      <item type="dimen" name="car_ui_toolbar_start_inset"/>
-      <item type="dimen" name="car_ui_toolbar_tab_icon_height"/>
-      <item type="dimen" name="car_ui_toolbar_tab_icon_width"/>
-      <item type="dimen" name="car_ui_toolbar_tab_padding_x"/>
-      <item type="dimen" name="car_ui_toolbar_tab_text_width"/>
-      <item type="dimen" name="car_ui_toolbar_title_logo_padding"/>
-      <item type="dimen" name="car_ui_toolbar_title_margin_start"/>
-      <item type="dimen" name="car_ui_toolbar_title_no_logo_margin_start"/>
-      <item type="dimen" name="car_ui_toolbar_top_inset"/>
-      <item type="dimen" name="car_ui_touch_target_height"/>
-      <item type="dimen" name="car_ui_touch_target_width"/>
-      <item type="dimen" name="wrap_content"/>
-      <item type="drawable" name="car_ui_activity_background"/>
-      <item type="drawable" name="car_ui_divider"/>
-      <item type="drawable" name="car_ui_icon_arrow_back"/>
-      <item type="drawable" name="car_ui_icon_close"/>
-      <item type="drawable" name="car_ui_icon_down"/>
-      <item type="drawable" name="car_ui_icon_lock"/>
-      <item type="drawable" name="car_ui_icon_overflow_menu"/>
-      <item type="drawable" name="car_ui_icon_search"/>
-      <item type="drawable" name="car_ui_icon_search_nav_icon"/>
-      <item type="drawable" name="car_ui_icon_settings"/>
-      <item type="drawable" name="car_ui_list_header_background"/>
-      <item type="drawable" name="car_ui_list_item_avatar_icon_outline"/>
-      <item type="drawable" name="car_ui_list_item_background"/>
-      <item type="drawable" name="car_ui_list_item_divider"/>
-      <item type="drawable" name="car_ui_list_limiting_message_background"/>
-      <item type="drawable" name="car_ui_preference_icon_chevron"/>
-      <item type="drawable" name="car_ui_preference_icon_chevron_disabled"/>
-      <item type="drawable" name="car_ui_preference_icon_chevron_enabled"/>
-      <item type="drawable" name="car_ui_recyclerview_button_ripple_background"/>
-      <item type="drawable" name="car_ui_recyclerview_divider"/>
-      <item type="drawable" name="car_ui_recyclerview_ic_down"/>
-      <item type="drawable" name="car_ui_recyclerview_ic_up"/>
-      <item type="drawable" name="car_ui_recyclerview_scrollbar_thumb"/>
-      <item type="drawable" name="car_ui_toolbar_background"/>
-      <item type="drawable" name="car_ui_toolbar_menu_item_divider"/>
-      <item type="drawable" name="car_ui_toolbar_menu_item_icon_background"/>
-      <item type="drawable" name="car_ui_toolbar_menu_item_icon_ripple"/>
-      <item type="drawable" name="car_ui_toolbar_search_close_icon"/>
-      <item type="drawable" name="car_ui_toolbar_search_search_icon"/>
-      <item type="id" name="action_container"/>
-      <item type="id" name="action_container_touch_interceptor"/>
-      <item type="id" name="action_divider"/>
-      <item type="id" name="avatar_icon"/>
-      <item type="id" name="body"/>
-      <item type="id" name="car_ui_alert_icon"/>
-      <item type="id" name="car_ui_alert_subtitle"/>
-      <item type="id" name="car_ui_alert_title"/>
-      <item type="id" name="car_ui_base_layout_content_container"/>
-      <item type="id" name="car_ui_check_box_end_guideline"/>
-      <item type="id" name="car_ui_check_box_start_guideline"/>
-      <item type="id" name="car_ui_list_item_end_guideline"/>
-      <item type="id" name="car_ui_list_item_start_guideline"/>
-      <item type="id" name="car_ui_list_limiting_message"/>
-      <item type="id" name="car_ui_preference_fragment_container"/>
-      <item type="id" name="car_ui_recycler_view"/>
-      <item type="id" name="car_ui_scroll_bar"/>
-      <item type="id" name="car_ui_scrollbar_page_down"/>
-      <item type="id" name="car_ui_scrollbar_page_up"/>
-      <item type="id" name="car_ui_scrollbar_thumb"/>
-      <item type="id" name="car_ui_scrollbar_track"/>
-      <item type="id" name="car_ui_toolbar"/>
-      <item type="id" name="car_ui_toolbar_background"/>
-      <item type="id" name="car_ui_toolbar_bottom_guideline"/>
-      <item type="id" name="car_ui_toolbar_bottom_styleable"/>
-      <item type="id" name="car_ui_toolbar_end_guideline"/>
-      <item type="id" name="car_ui_toolbar_logo"/>
-      <item type="id" name="car_ui_toolbar_menu_item_icon"/>
-      <item type="id" name="car_ui_toolbar_menu_item_icon_container"/>
-      <item type="id" name="car_ui_toolbar_menu_item_switch"/>
-      <item type="id" name="car_ui_toolbar_menu_item_text"/>
-      <item type="id" name="car_ui_toolbar_menu_item_text_with_icon"/>
-      <item type="id" name="car_ui_toolbar_menu_items_container"/>
-      <item type="id" name="car_ui_toolbar_nav_icon"/>
-      <item type="id" name="car_ui_toolbar_nav_icon_container"/>
-      <item type="id" name="car_ui_toolbar_progress_bar"/>
-      <item type="id" name="car_ui_toolbar_row_separator"/>
-      <item type="id" name="car_ui_toolbar_row_separator_guideline"/>
-      <item type="id" name="car_ui_toolbar_search_bar"/>
-      <item type="id" name="car_ui_toolbar_search_close"/>
-      <item type="id" name="car_ui_toolbar_search_icon"/>
-      <item type="id" name="car_ui_toolbar_search_view_container"/>
-      <item type="id" name="car_ui_toolbar_start_guideline"/>
-      <item type="id" name="car_ui_toolbar_subtitle"/>
-      <item type="id" name="car_ui_toolbar_tab_item_icon"/>
-      <item type="id" name="car_ui_toolbar_tab_item_text"/>
-      <item type="id" name="car_ui_toolbar_tabs"/>
-      <item type="id" name="car_ui_toolbar_title"/>
-      <item type="id" name="car_ui_toolbar_title_container"/>
-      <item type="id" name="car_ui_toolbar_title_logo"/>
-      <item type="id" name="car_ui_toolbar_title_logo_container"/>
-      <item type="id" name="car_ui_toolbar_top_guideline"/>
-      <item type="id" name="check_box_container"/>
-      <item type="id" name="checkbox"/>
-      <item type="id" name="checkbox_widget"/>
-      <item type="id" name="container"/>
-      <item type="id" name="content_icon"/>
-      <item type="id" name="icon"/>
-      <item type="id" name="icon_container"/>
-      <item type="id" name="list"/>
-      <item type="id" name="nested_recycler_view_layout"/>
-      <item type="id" name="radio_button_widget"/>
-      <item type="id" name="recycler_view"/>
-      <item type="id" name="reduced_touch_interceptor"/>
-      <item type="id" name="search"/>
-      <item type="id" name="seekbar"/>
-      <item type="id" name="seekbar_value"/>
-      <item type="id" name="spinner"/>
-      <item type="id" name="supplemental_icon"/>
-      <item type="id" name="switch_widget"/>
-      <item type="id" name="text"/>
-      <item type="id" name="textbox"/>
-      <item type="id" name="title"/>
-      <item type="id" name="title_template"/>
-      <item type="id" name="toolbar"/>
-      <item type="id" name="touch_interceptor"/>
-      <item type="integer" name="car_ui_default_max_string_length"/>
-      <item type="integer" name="car_ui_scrollbar_longpress_initial_delay"/>
-      <item type="integer" name="car_ui_scrollbar_longpress_repeat_interval"/>
-      <item type="layout" name="car_ui_alert_dialog_edit_text"/>
-      <item type="layout" name="car_ui_alert_dialog_list"/>
-      <item type="layout" name="car_ui_alert_dialog_title_with_subtitle"/>
-      <item type="layout" name="car_ui_base_layout"/>
-      <item type="layout" name="car_ui_base_layout_toolbar"/>
-      <item type="layout" name="car_ui_base_layout_toolbar_legacy"/>
-      <item type="layout" name="car_ui_check_box_list_item"/>
-      <item type="layout" name="car_ui_header_list_item"/>
-      <item type="layout" name="car_ui_list_item"/>
-      <item type="layout" name="car_ui_list_limiting_message"/>
-      <item type="layout" name="car_ui_list_preference"/>
-      <item type="layout" name="car_ui_preference"/>
-      <item type="layout" name="car_ui_preference_category"/>
-      <item type="layout" name="car_ui_preference_chevron"/>
-      <item type="layout" name="car_ui_preference_dialog_edittext"/>
-      <item type="layout" name="car_ui_preference_dropdown"/>
-      <item type="layout" name="car_ui_preference_fragment"/>
-      <item type="layout" name="car_ui_preference_fragment_with_toolbar"/>
-      <item type="layout" name="car_ui_preference_widget_checkbox"/>
-      <item type="layout" name="car_ui_preference_widget_seekbar"/>
-      <item type="layout" name="car_ui_preference_widget_switch"/>
-      <item type="layout" name="car_ui_recycler_view"/>
-      <item type="layout" name="car_ui_recycler_view_item"/>
-      <item type="layout" name="car_ui_recyclerview_scrollbar"/>
-      <item type="layout" name="car_ui_toolbar"/>
-      <item type="layout" name="car_ui_toolbar_menu_item"/>
-      <item type="layout" name="car_ui_toolbar_search_view"/>
-      <item type="layout" name="car_ui_toolbar_tab_item"/>
-      <item type="layout" name="car_ui_toolbar_tab_item_flexible"/>
-      <item type="layout" name="car_ui_toolbar_tab_item_layout"/>
-      <item type="layout" name="car_ui_toolbar_tab_item_layout_flexible"/>
-      <item type="layout" name="car_ui_toolbar_two_row"/>
-      <item type="string" name="car_ui_alert_dialog_default_button"/>
-      <item type="string" name="car_ui_dialog_preference_negative"/>
-      <item type="string" name="car_ui_dialog_preference_positive"/>
-      <item type="string" name="car_ui_ellipsis"/>
-      <item type="string" name="car_ui_list_item_header_font_family"/>
-      <item type="string" name="car_ui_preference_category_title_font_family"/>
-      <item type="string" name="car_ui_preference_switch_off"/>
-      <item type="string" name="car_ui_preference_switch_on"/>
-      <item type="string" name="car_ui_restricted_while_driving"/>
-      <item type="string" name="car_ui_scrollbar_component"/>
-      <item type="string" name="car_ui_scrollbar_page_down_button"/>
-      <item type="string" name="car_ui_scrollbar_page_up_button"/>
-      <item type="string" name="car_ui_scrolling_limited_message"/>
-      <item type="string" name="car_ui_toolbar_default_search_hint"/>
-      <item type="string" name="car_ui_toolbar_menu_item_overflow_title"/>
-      <item type="string" name="car_ui_toolbar_menu_item_search_title"/>
-      <item type="string" name="car_ui_toolbar_menu_item_settings_title"/>
-      <item type="string" name="car_ui_toolbar_nav_icon_content_description"/>
-      <item type="style" name="CarUiPreferenceTheme"/>
-      <item type="style" name="CarUiPreferenceTheme.WithToolbar"/>
-      <item type="style" name="Preference.CarUi"/>
-      <item type="style" name="Preference.CarUi.Category"/>
-      <item type="style" name="Preference.CarUi.CheckBoxPreference"/>
-      <item type="style" name="Preference.CarUi.DialogPreference"/>
-      <item type="style" name="Preference.CarUi.DialogPreference.EditTextPreference"/>
-      <item type="style" name="Preference.CarUi.DropDown"/>
-      <item type="style" name="Preference.CarUi.Icon"/>
-      <item type="style" name="Preference.CarUi.Information"/>
-      <item type="style" name="Preference.CarUi.Preference"/>
-      <item type="style" name="Preference.CarUi.PreferenceScreen"/>
-      <item type="style" name="Preference.CarUi.SeekBarPreference"/>
-      <item type="style" name="Preference.CarUi.SwitchPreference"/>
-      <item type="style" name="PreferenceFragment.CarUi"/>
-      <item type="style" name="PreferenceFragment.CarUi.WithToolbar"/>
-      <item type="style" name="PreferenceFragmentList.CarUi"/>
-      <item type="style" name="TextAppearance.CarUi"/>
-      <item type="style" name="TextAppearance.CarUi.AlertDialog.Subtitle"/>
-      <item type="style" name="TextAppearance.CarUi.AlertDialog.Title"/>
-      <item type="style" name="TextAppearance.CarUi.Body1"/>
-      <item type="style" name="TextAppearance.CarUi.Body2"/>
-      <item type="style" name="TextAppearance.CarUi.Body3"/>
-      <item type="style" name="TextAppearance.CarUi.ListItem"/>
-      <item type="style" name="TextAppearance.CarUi.ListItem.Body"/>
-      <item type="style" name="TextAppearance.CarUi.ListItem.Header"/>
-      <item type="style" name="TextAppearance.CarUi.PreferenceCategoryTitle"/>
-      <item type="style" name="TextAppearance.CarUi.PreferenceEditTextDialogMessage"/>
-      <item type="style" name="TextAppearance.CarUi.PreferenceSummary"/>
-      <item type="style" name="TextAppearance.CarUi.PreferenceTitle"/>
-      <item type="style" name="TextAppearance.CarUi.Sub1"/>
-      <item type="style" name="TextAppearance.CarUi.Sub2"/>
-      <item type="style" name="TextAppearance.CarUi.Sub3"/>
-      <item type="style" name="TextAppearance.CarUi.Widget"/>
-      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar"/>
-      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar.Tab"/>
-      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar.Tab.Selected"/>
-      <item type="style" name="TextAppearance.CarUi.Widget.Toolbar.Title"/>
-      <item type="style" name="Theme.CarUi"/>
-      <item type="style" name="Theme.CarUi.NoToolbar"/>
-      <item type="style" name="Theme.CarUi.WithToolbar"/>
-      <item type="style" name="Widget.CarUi"/>
-      <item type="style" name="Widget.CarUi.AlertDialog"/>
-      <item type="style" name="Widget.CarUi.AlertDialog.HeaderContainer"/>
-      <item type="style" name="Widget.CarUi.AlertDialog.Icon"/>
-      <item type="style" name="Widget.CarUi.AlertDialog.TitleContainer"/>
-      <item type="style" name="Widget.CarUi.Button"/>
-      <item type="style" name="Widget.CarUi.Button.Borderless.Colored"/>
-      <item type="style" name="Widget.CarUi.CarUiRecyclerView"/>
-      <item type="style" name="Widget.CarUi.SeekbarPreference"/>
-      <item type="style" name="Widget.CarUi.SeekbarPreference.Seekbar"/>
-      <item type="style" name="Widget.CarUi.Toolbar"/>
-      <item type="style" name="Widget.CarUi.Toolbar.BottomView"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Container"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Logo"/>
-      <item type="style" name="Widget.CarUi.Toolbar.LogoContainer"/>
-      <item type="style" name="Widget.CarUi.Toolbar.MenuItem"/>
-      <item type="style" name="Widget.CarUi.Toolbar.MenuItem.Container"/>
-      <item type="style" name="Widget.CarUi.Toolbar.MenuItem.IndividualContainer"/>
-      <item type="style" name="Widget.CarUi.Toolbar.NavIcon"/>
-      <item type="style" name="Widget.CarUi.Toolbar.NavIconContainer"/>
-      <item type="style" name="Widget.CarUi.Toolbar.ProgressBar"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Search.CloseIcon"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Search.EditText"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Search.SearchIcon"/>
-      <item type="style" name="Widget.CarUi.Toolbar.SeparatorView"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Subtitle"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Tab"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Tab.Container"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Tab.Icon"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Tab.Text"/>
-      <item type="style" name="Widget.CarUi.Toolbar.TextButton"/>
-      <item type="style" name="Widget.CarUi.Toolbar.TextButton.WithIcon"/>
-      <item type="style" name="Widget.CarUi.Toolbar.Title"/>
-    </policy>
-  </overlayable>
-</resources>
diff --git a/car-ui-lib/res/drawable/car_ui_icon_close.xml b/car-ui-lib/res/drawable/car_ui_icon_close.xml
deleted file mode 100644
index 482df0f..0000000
--- a/car-ui-lib/res/drawable/car_ui_icon_close.xml
+++ /dev/null
@@ -1,27 +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.
--->
-
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0">
-    <path
-        android:fillColor="#FFF"
-        android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
-</vector>
\ No newline at end of file
diff --git a/car-ui-lib/res/drawable/car_ui_list_item_background.xml b/car-ui-lib/res/drawable/car_ui_list_item_background.xml
deleted file mode 100644
index df8df2f..0000000
--- a/car-ui-lib/res/drawable/car_ui_list_item_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="?android:colorControlHighlight">
-    <item android:id="@android:id/mask">
-        <shape android:shape="rectangle">
-            <solid android:color="?android:colorAccent" />
-        </shape>
-    </item>
-</ripple>
\ No newline at end of file
diff --git a/car-ui-lib/res/drawable/car_ui_list_item_divider.xml b/car-ui-lib/res/drawable/car_ui_list_item_divider.xml
deleted file mode 100644
index 1e229c8..0000000
--- a/car-ui-lib/res/drawable/car_ui_list_item_divider.xml
+++ /dev/null
@@ -1,22 +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.
-  -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <size android:height="@dimen/car_ui_list_item_action_divider_height" />
-    <solid android:color="@color/car_ui_list_item_divider" />
-</shape>
\ No newline at end of file
diff --git a/car-ui-lib/res/drawable/car_ui_preference_icon_chevron.xml b/car-ui-lib/res/drawable/car_ui_preference_icon_chevron.xml
deleted file mode 100644
index 61d594c..0000000
--- a/car-ui-lib/res/drawable/car_ui_preference_icon_chevron.xml
+++ /dev/null
@@ -1,21 +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.
-  -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-  <item android:state_enabled="false" android:drawable="@drawable/car_ui_preference_icon_chevron_disabled"/>
-  <item android:state_enabled="true" android:drawable="@drawable/car_ui_preference_icon_chevron_enabled"/>
-</selector>
\ No newline at end of file
diff --git a/car-ui-lib/res/drawable/car_ui_toolbar_menu_item_icon_background.xml b/car-ui-lib/res/drawable/car_ui_toolbar_menu_item_icon_background.xml
deleted file mode 100644
index 33594c2..0000000
--- a/car-ui-lib/res/drawable/car_ui_toolbar_menu_item_icon_background.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~
-  ~ Copyright (C) 2019 Google Inc.
-  ~
-  ~ 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.
-  ~
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="oval">
-    <size
-        android:width="@dimen/car_ui_toolbar_menu_item_icon_background_size"
-        android:height="@dimen/car_ui_toolbar_menu_item_icon_background_size"/>
-    <solid android:color="@color/car_ui_toolbar_menu_item_icon_background_color"/>
-</shape>
-
-
diff --git a/car-ui-lib/res/layout/car_ui_alert_dialog_edit_text.xml b/car-ui-lib/res/layout/car_ui_alert_dialog_edit_text.xml
deleted file mode 100644
index 3cc87c1..0000000
--- a/car-ui-lib/res/layout/car_ui_alert_dialog_edit_text.xml
+++ /dev/null
@@ -1,27 +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.
-  -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android">
-    <EditText
-              android:id="@+id/textbox"
-              android:layout_width="match_parent"
-              android:layout_height="@dimen/car_ui_dialog_edittext_height"
-              android:layout_marginTop="@dimen/car_ui_dialog_edittext_margin_top"
-              android:layout_marginBottom="@dimen/car_ui_dialog_edittext_margin_bottom"
-              android:layout_marginStart="@dimen/car_ui_dialog_edittext_margin_start"
-              android:layout_marginEnd="@dimen/car_ui_dialog_edittext_margin_end"/>
-</FrameLayout>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_base_layout.xml b/car-ui-lib/res/layout/car_ui_base_layout.xml
deleted file mode 100644
index fdc8b53..0000000
--- a/car-ui-lib/res/layout/car_ui_base_layout.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/car_ui_base_layout_content_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_base_layout_toolbar.xml b/car-ui-lib/res/layout/car_ui_base_layout_toolbar.xml
deleted file mode 100644
index 374dc4b..0000000
--- a/car-ui-lib/res/layout/car_ui_base_layout_toolbar.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-     clearFocus() will actually send the focus to the first focusable thing in the layout.
-     If that focusable thing is still the search bar it will just reselect it, and the user won't
-     be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true" />
-
-    <FrameLayout
-        android:id="@+id/car_ui_base_layout_content_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/car_ui_toolbar_background"
-        style="@style/Widget.CarUi.Toolbar.Container"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_first_row_height"
-        android:tag="car_ui_top_inset"
-        app:layout_constraintTop_toTopOf="parent">
-        <com.android.car.ui.baselayout.ClickBlockingView
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toTopOf="parent"
-            app:layout_constraintBottom_toBottomOf="parent"/>
-
-        <!-- The horizontal bias set to 0.0 here is so that when you set this view as GONE, it will
-             be treated as if it's all the way to the left instead of centered in the margin -->
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_nav_icon_container"
-            style="@style/Widget.CarUi.Toolbar.NavIconContainer"
-            android:layout_width="@dimen/car_ui_toolbar_margin"
-            android:layout_height="0dp"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintHorizontal_bias="0.0"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_nav_icon"
-                style="@style/Widget.CarUi.Toolbar.NavIcon"
-                android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_title_logo_container"
-            style="@style/Widget.CarUi.Toolbar.LogoContainer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container"
-            app:layout_constraintTop_toTopOf="parent">
-
-            <ImageView
-                android:id="@+id/car_ui_toolbar_title_logo"
-                style="@style/Widget.CarUi.Toolbar.Logo"
-                android:layout_width="@dimen/car_ui_toolbar_logo_size"
-                android:layout_height="@dimen/car_ui_toolbar_logo_size"
-                android:layout_gravity="center"
-                android:scaleType="fitXY" />
-        </FrameLayout>
-
-        <LinearLayout android:layout_height="wrap_content"
-                      android:layout_width="0dp"
-                      android:id="@+id/car_ui_toolbar_title_container"
-                      android:orientation="vertical"
-                      android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
-                      app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
-                      app:layout_constraintBottom_toBottomOf="parent"
-                      app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-                      app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-                      app:layout_constraintTop_toTopOf="parent">
-            <TextView android:id="@+id/car_ui_toolbar_title"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content"
-                      android:singleLine="true"
-                      style="@style/Widget.CarUi.Toolbar.Title"/>
-            <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                      android:layout_width="wrap_content"
-                      android:layout_height="wrap_content"
-                      android:visibility="gone"
-                      style="@style/Widget.CarUi.Toolbar.Subtitle"/>
-        </LinearLayout>
-
-        <com.android.car.ui.toolbar.TabLayout
-            android:id="@+id/car_ui_toolbar_tabs"
-            android:layout_width="wrap_content"
-            android:layout_height="0dp"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            app:layout_constraintHorizontal_bias="0.0"
-            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-            app:layout_constraintTop_toTopOf="parent" />
-
-        <LinearLayout
-            android:id="@+id/car_ui_toolbar_menu_items_container"
-            style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
-            android:layout_width="wrap_content"
-            android:layout_height="0dp"
-            android:orientation="horizontal"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toTopOf="parent" />
-
-        <FrameLayout
-            android:id="@+id/car_ui_toolbar_search_view_container"
-            android:layout_width="0dp"
-            android:layout_height="@dimen/car_ui_toolbar_search_height"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-            app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-            app:layout_constraintTop_toTopOf="parent" />
-
-        <ProgressBar
-            android:id="@+id/car_ui_toolbar_progress_bar"
-            style="@style/Widget.CarUi.Toolbar.ProgressBar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:indeterminate="true"
-            android:visibility="gone"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent" />
-
-    </androidx.constraintlayout.widget.ConstraintLayout>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
-
diff --git a/car-ui-lib/res/layout/car_ui_base_layout_toolbar_legacy.xml b/car-ui-lib/res/layout/car_ui_base_layout_toolbar_legacy.xml
deleted file mode 100644
index 263cc8a..0000000
--- a/car-ui-lib/res/layout/car_ui_base_layout_toolbar_legacy.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<!-- This layout is used on Q or earlier, to support OEMs that shipped
-     on Q and only customized the non-baselayout version of the toolbar -->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-         clearFocus() will actually send the focus to the first focusable thing in the layout.
-         If that focusable thing is still the search bar it will just reselect it, and the user won't
-         be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_base_layout_content_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <com.android.car.ui.toolbar.Toolbar
-        android:id="@+id/car_ui_toolbar"
-        android:tag="car_ui_top_inset"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:layout_constraintTop_toTopOf="parent" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/layout/car_ui_check_box_list_item.xml b/car-ui-lib/res/layout/car_ui_check_box_list_item.xml
deleted file mode 100644
index 59f0726..0000000
--- a/car-ui-lib/res/layout/car_ui_check_box_list_item.xml
+++ /dev/null
@@ -1,65 +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.
-  -->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:background="?android:attr/selectableItemBackground"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/car_ui_list_item_check_box_height">
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/car_ui_check_box_start_guideline"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        app:layout_constraintGuide_begin="@dimen/car_ui_list_item_check_box_start_inset" />
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/car_ui_check_box_end_guideline"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        app:layout_constraintGuide_end="@dimen/car_ui_list_item_check_box_end_inset" />
-
-    <FrameLayout
-        android:id="@+id/check_box_container"
-        android:layout_width="@dimen/car_ui_list_item_check_box_icon_container_width"
-        android:layout_height="0dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="@+id/car_ui_check_box_start_guideline"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <CheckBox
-            android:id="@+id/checkbox"
-            android:clickable="false"
-            android:focusable="false"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center" />
-    </FrameLayout>
-
-    <TextView
-        android:id="@+id/text"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
-        android:textAppearance="@style/TextAppearance.CarUi.ListItem"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="@+id/car_ui_check_box_end_guideline"
-        app:layout_constraintStart_toEndOf="@+id/check_box_container"
-        app:layout_constraintTop_toTopOf="parent" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_header_list_item.xml b/car-ui-lib/res/layout/car_ui_header_list_item.xml
deleted file mode 100644
index e1196cf..0000000
--- a/car-ui-lib/res/layout/car_ui_header_list_item.xml
+++ /dev/null
@@ -1,55 +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.
-  -->
-
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:background="@drawable/car_ui_list_header_background"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/car_ui_list_item_header_height">
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/car_ui_list_item_start_guideline"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        app:layout_constraintGuide_begin="@dimen/car_ui_list_item_header_start_inset" />
-
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_ui_header_list_item_text_start_margin"
-        android:textAppearance="@style/TextAppearance.CarUi.ListItem.Header"
-        app:layout_constraintBottom_toTopOf="@+id/body"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="@id/car_ui_list_item_start_guideline"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintVertical_chainStyle="packed" />
-
-    <TextView
-        android:id="@+id/body"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_ui_list_item_text_no_icon_start_margin"
-        android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="@id/car_ui_list_item_start_guideline"
-        app:layout_constraintTop_toBottomOf="@+id/title" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_list_item.xml b/car-ui-lib/res/layout/car_ui_list_item.xml
deleted file mode 100644
index d838fcb..0000000
--- a/car-ui-lib/res/layout/car_ui_list_item.xml
+++ /dev/null
@@ -1,186 +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.
-  -->
-
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="@dimen/car_ui_list_item_height">
-
-    <!-- The following touch interceptor views are sized to encompass the specific sub-sections of
-    the list item view to easily control the bounds of a background ripple effects. -->
-    <View
-        android:id="@+id/touch_interceptor"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:background="@drawable/car_ui_list_item_background"
-        android:clickable="true"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <!-- This touch interceptor does not include the action container -->
-    <View
-        android:id="@+id/reduced_touch_interceptor"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:background="@drawable/car_ui_list_item_background"
-        android:clickable="true"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@id/action_container"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/car_ui_list_item_start_guideline"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        app:layout_constraintGuide_begin="@dimen/car_ui_list_item_start_inset" />
-
-    <FrameLayout
-        android:id="@+id/icon_container"
-        android:layout_width="@dimen/car_ui_list_item_icon_container_width"
-        android:layout_height="0dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="@+id/car_ui_list_item_start_guideline"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <ImageView
-            android:id="@+id/icon"
-            android:layout_width="@dimen/car_ui_list_item_icon_size"
-            android:layout_height="@dimen/car_ui_list_item_icon_size"
-            android:layout_gravity="center"
-            android:visibility="gone"
-            android:scaleType="fitXY" />
-
-        <ImageView
-            android:id="@+id/content_icon"
-            android:layout_width="@dimen/car_ui_list_item_content_icon_width"
-            android:layout_height="@dimen/car_ui_list_item_content_icon_height"
-            android:layout_gravity="center"
-            android:visibility="gone"
-            android:scaleType="fitXY" />
-
-        <ImageView
-            android:id="@+id/avatar_icon"
-            android:background="@drawable/car_ui_list_item_avatar_icon_outline"
-            android:layout_width="@dimen/car_ui_list_item_avatar_icon_width"
-            android:layout_height="@dimen/car_ui_list_item_avatar_icon_height"
-            android:layout_gravity="center"
-            android:visibility="gone"
-            android:scaleType="fitXY" />
-    </FrameLayout>
-
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
-        android:singleLine="@bool/car_ui_list_item_single_line_title"
-        android:textAppearance="@style/TextAppearance.CarUi.ListItem"
-        app:layout_constraintBottom_toTopOf="@+id/body"
-        app:layout_constraintEnd_toStartOf="@+id/action_container"
-        app:layout_constraintStart_toEndOf="@+id/icon_container"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintVertical_chainStyle="packed"
-        app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" />
-
-    <TextView
-        android:id="@+id/body"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
-        android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/action_container"
-        app:layout_constraintStart_toEndOf="@+id/icon_container"
-        app:layout_constraintTop_toBottomOf="@+id/title"
-        app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" />
-
-    <!-- This touch interceptor is sized and positioned to encompass the action container   -->
-    <View
-        android:id="@+id/action_container_touch_interceptor"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:background="@drawable/car_ui_list_item_background"
-        android:clickable="true"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="@id/action_container"
-        app:layout_constraintEnd_toEndOf="@id/action_container"
-        app:layout_constraintStart_toStartOf="@id/action_container"
-        app:layout_constraintTop_toTopOf="@id/action_container" />
-
-    <FrameLayout
-        android:id="@+id/action_container"
-        android:layout_width="wrap_content"
-        android:minWidth="@dimen/car_ui_list_item_icon_container_width"
-        android:layout_height="0dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="@+id/car_ui_list_item_end_guideline"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <View
-            android:id="@+id/action_divider"
-            android:layout_width="@dimen/car_ui_list_item_action_divider_width"
-            android:layout_height="@dimen/car_ui_list_item_action_divider_height"
-            android:layout_gravity="start|center_vertical"
-            android:background="@drawable/car_ui_list_item_divider" />
-
-        <Switch
-            android:id="@+id/switch_widget"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:clickable="false"
-            android:focusable="false" />
-
-        <CheckBox
-            android:id="@+id/checkbox_widget"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:clickable="false"
-            android:focusable="false" />
-
-        <RadioButton
-            android:id="@+id/radio_button_widget"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:clickable="false"
-            android:focusable="false" />
-
-        <ImageView
-            android:id="@+id/supplemental_icon"
-            android:layout_width="@dimen/car_ui_list_item_supplemental_icon_size"
-            android:layout_height="@dimen/car_ui_list_item_supplemental_icon_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY" />
-    </FrameLayout>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/car_ui_list_item_end_guideline"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        app:layout_constraintGuide_end="@dimen/car_ui_list_item_end_inset" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_list_limiting_message.xml b/car-ui-lib/res/layout/car_ui_list_limiting_message.xml
deleted file mode 100644
index 0b06575..0000000
--- a/car-ui-lib/res/layout/car_ui_list_limiting_message.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="144dp"
-    android:gravity="center"
-    android:paddingTop="16dp"
-    android:paddingBottom="32dp"
->
-    <TextView
-        android:id="@+id/car_ui_list_limiting_message"
-        android:layout_width="wrap_content"
-        android:layout_height="96dp"
-        android:layout_gravity="center_horizontal"
-        android:gravity="center"
-        android:paddingStart="48dp"
-        android:paddingEnd="48dp"
-        android:drawableStart="@drawable/car_ui_icon_lock"
-        android:drawablePadding="24dp"
-        android:textColor="?android:attr/textColorPrimary"
-        android:textAllCaps="false"
-        android:singleLine="true"
-        android:background="@drawable/car_ui_list_limiting_message_background"
-    />
-</FrameLayout>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_list_preference.xml b/car-ui-lib/res/layout/car_ui_list_preference.xml
deleted file mode 100644
index 88957b0..0000000
--- a/car-ui-lib/res/layout/car_ui_list_preference.xml
+++ /dev/null
@@ -1,37 +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.
-  -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@drawable/car_ui_activity_background">
-
-    <com.android.car.ui.recyclerview.CarUiRecyclerView
-        android:id="@+id/list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:enableDivider="true" />
-
-    <com.android.car.ui.toolbar.Toolbar
-        android:id="@+id/toolbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:state="subpage" />
-
-</FrameLayout>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_preference.xml b/car-ui-lib/res/layout/car_ui_preference.xml
deleted file mode 100644
index 03e101d..0000000
--- a/car-ui-lib/res/layout/car_ui_preference.xml
+++ /dev/null
@@ -1,73 +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.
--->
-
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:background="?android:attr/selectableItemBackground"
-    android:clipToPadding="false"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart">
-
-    <ImageView
-        android:id="@android:id/icon"
-        android:layout_width="@dimen/car_ui_preference_icon_size"
-        android:layout_height="@dimen/car_ui_preference_icon_size"
-        android:layout_alignParentStart="true"
-        android:layout_centerVertical="true"
-        android:layout_marginBottom="@dimen/car_ui_preference_content_margin_bottom"
-        android:layout_marginEnd="@dimen/car_ui_preference_icon_margin_end"
-        android:layout_marginTop="@dimen/car_ui_preference_content_margin_top"
-        android:scaleType="fitCenter"
-        style="@style/Preference.CarUi.Icon"/>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginBottom="@dimen/car_ui_preference_content_margin_bottom"
-        android:layout_marginTop="@dimen/car_ui_preference_content_margin_top"
-        android:layout_toEndOf="@android:id/icon"
-        android:layout_toStartOf="@android:id/widget_frame"
-        android:orientation="vertical">
-
-        <TextView
-            android:id="@android:id/title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            android:textAppearance="@style/TextAppearance.CarUi.PreferenceTitle"/>
-
-        <TextView
-            android:id="@android:id/summary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="@style/TextAppearance.CarUi.PreferenceSummary"/>
-
-    </LinearLayout>
-
-    <!-- Preference should place its actual preference widget here. -->
-    <FrameLayout
-        android:id="@android:id/widget_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:layout_centerVertical="true"/>
-
-</RelativeLayout>
diff --git a/car-ui-lib/res/layout/car_ui_preference_chevron.xml b/car-ui-lib/res/layout/car_ui_preference_chevron.xml
deleted file mode 100644
index efeaddb..0000000
--- a/car-ui-lib/res/layout/car_ui_preference_chevron.xml
+++ /dev/null
@@ -1,21 +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.
--->
-<ImageView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center_horizontal"
-    android:src="@drawable/car_ui_preference_icon_chevron"/>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_preference_fragment.xml b/car-ui-lib/res/layout/car_ui_preference_fragment.xml
deleted file mode 100644
index 7298055..0000000
--- a/car-ui-lib/res/layout/car_ui_preference_fragment.xml
+++ /dev/null
@@ -1,35 +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.
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@drawable/car_ui_activity_background">
-
-    <FrameLayout
-        android:id="@android:id/list_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <com.android.car.ui.recyclerview.CarUiRecyclerView
-            android:id="@+id/recycler_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            app:enableDivider="true"/>
-    </FrameLayout>
-</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_preference_fragment_with_toolbar.xml b/car-ui-lib/res/layout/car_ui_preference_fragment_with_toolbar.xml
deleted file mode 100644
index 4acb10d..0000000
--- a/car-ui-lib/res/layout/car_ui_preference_fragment_with_toolbar.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright 2020 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.
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/car_ui_preference_fragment_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@drawable/car_ui_activity_background">
-
-    <FrameLayout
-        android:id="@android:id/list_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <com.android.car.ui.recyclerview.CarUiRecyclerView
-            android:id="@+id/recycler_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            app:enableDivider="true"/>
-    </FrameLayout>
-
-    <com.android.car.ui.toolbar.Toolbar
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:id="@+id/toolbar"
-        app:state="subpage"/>
-</FrameLayout>
diff --git a/car-ui-lib/res/layout/car_ui_recycler_view.xml b/car-ui-lib/res/layout/car_ui_recycler_view.xml
deleted file mode 100644
index 50600c1..0000000
--- a/car-ui-lib/res/layout/car_ui_recycler_view.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright 2020 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.
-  -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <include layout="@layout/car_ui_recyclerview_scrollbar"/>
-
-    <com.android.car.ui.recyclerview.CarUiRecyclerViewContainer
-        android:id="@+id/car_ui_recycler_view"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_marginEnd="@dimen/car_ui_scrollbar_margin"
-        android:tag="carUiRecyclerView"
-        android:layout_weight="1"/>
-</merge>
\ No newline at end of file
diff --git a/car-ui-lib/res/layout/car_ui_recyclerview_scrollbar.xml b/car-ui-lib/res/layout/car_ui_recyclerview_scrollbar.xml
deleted file mode 100644
index 1c7097a..0000000
--- a/car-ui-lib/res/layout/car_ui_recyclerview_scrollbar.xml
+++ /dev/null
@@ -1,75 +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.
-  -->
-
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="@dimen/car_ui_scrollbar_container_width"
-    android:layout_height="match_parent"
-    android:id="@+id/car_ui_scroll_bar"
-    android:gravity="center">
-
-    <ImageView
-        android:id="@+id/car_ui_scrollbar_page_up"
-        android:layout_width="@dimen/car_ui_scrollbar_button_size"
-        android:layout_height="@dimen/car_ui_scrollbar_button_size"
-        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
-        android:contentDescription="@string/car_ui_scrollbar_page_up_button"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/car_ui_recyclerview_ic_up"
-        android:scaleType="centerInside"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
-
-    <!-- View height is dynamically calculated during layout. -->
-    <View
-        android:id="@+id/car_ui_scrollbar_thumb"
-        android:layout_width="@dimen/car_ui_scrollbar_thumb_width"
-        android:layout_height="0dp"
-        android:layout_gravity="center_horizontal"
-        android:background="@drawable/car_ui_recyclerview_scrollbar_thumb"
-        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
-
-    <View
-        android:id="@+id/car_ui_scrollbar_track"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_marginTop="@dimen/car_ui_scrollbar_separator_margin"
-        android:layout_marginBottom="@dimen/car_ui_scrollbar_separator_margin"
-        app:layout_constraintTop_toBottomOf="@+id/car_ui_scrollbar_page_up"
-        app:layout_constraintBottom_toTopOf="@+id/car_ui_scrollbar_page_down"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <ImageView
-        android:id="@+id/car_ui_scrollbar_page_down"
-        android:layout_width="@dimen/car_ui_scrollbar_button_size"
-        android:layout_height="@dimen/car_ui_scrollbar_button_size"
-        android:background="@drawable/car_ui_recyclerview_button_ripple_background"
-        android:contentDescription="@string/car_ui_scrollbar_page_down_button"
-        android:focusable="false"
-        android:hapticFeedbackEnabled="false"
-        android:src="@drawable/car_ui_recyclerview_ic_down"
-        android:scaleType="centerInside"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintRight_toRightOf="parent"/>
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/layout/car_ui_toolbar.xml b/car-ui-lib/res/layout/car_ui_toolbar.xml
deleted file mode 100644
index b0716a7..0000000
--- a/car-ui-lib/res/layout/car_ui_toolbar.xml
+++ /dev/null
@@ -1,187 +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.
--->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/car_ui_toolbar_first_row_height"
-    android:id="@+id/car_ui_toolbar_background"
-    style="@style/Widget.CarUi.Toolbar.Container">
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-         clearFocus() will actually send the focus to the first focusable thing in the layout.
-         If that focusable thing is still the search bar it will just reselect it, and the user won't
-         be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_start_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_top_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
-        android:orientation="horizontal"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_end_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
-        android:orientation="horizontal"/>
-
-    <!-- The horizontal bias here is so that when you set this view as GONE, it will be
-         treated as if it's all the way to the left instead of centered in the margin -->
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_width="@dimen/car_ui_toolbar_margin"
-        android:layout_height="0dp"
-        style="@style/Widget.CarUi.Toolbar.NavIconContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_start_guideline"
-        app:layout_constraintHorizontal_bias="0.0">
-        <ImageView
-            android:id="@+id/car_ui_toolbar_nav_icon"
-            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"
-            style="@style/Widget.CarUi.Toolbar.NavIcon"/>
-        <ImageView
-            android:id="@+id/car_ui_toolbar_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"/>
-    </FrameLayout>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_title_logo_container"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="@style/Widget.CarUi.Toolbar.LogoContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
-
-        <ImageView
-            android:id="@+id/car_ui_toolbar_title_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:scaleType="fitXY"
-            android:layout_gravity="center"
-            style="@style/Widget.CarUi.Toolbar.Logo"/>
-    </FrameLayout>
-
-    <LinearLayout android:layout_height="wrap_content"
-                  android:layout_width="0dp"
-                  android:id="@+id/car_ui_toolbar_title_container"
-                  android:orientation="vertical"
-                  android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
-                  app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
-                  app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-                  app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-                  app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-                  app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container">
-        <TextView android:id="@+id/car_ui_toolbar_title"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:singleLine="true"
-                  style="@style/Widget.CarUi.Toolbar.Title"/>
-        <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:visibility="gone"
-                  style="@style/Widget.CarUi.Toolbar.Subtitle"/>
-    </LinearLayout>
-
-    <com.android.car.ui.toolbar.TabLayout
-        android:id="@+id/car_ui_toolbar_tabs"
-        android:layout_width="wrap_content"
-        android:layout_height="0dp"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_title_logo_container"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"
-        app:layout_constraintHorizontal_bias="0.0"/>
-
-    <LinearLayout
-        android:id="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_width="wrap_content"
-        android:layout_height="0dp"
-        android:orientation="horizontal"
-        style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_end_guideline"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_search_view_container"
-        android:layout_width="0dp"
-        android:layout_height="@dimen/car_ui_toolbar_search_height"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
-
-    <View
-        android:id="@+id/car_ui_toolbar_row_separator"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_separator_height"
-        style="@style/Widget.CarUi.Toolbar.SeparatorView"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <ProgressBar
-        android:id="@+id/car_ui_toolbar_progress_bar"
-        style="@style/Widget.CarUi.Toolbar.ProgressBar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        android:indeterminate="true"
-        android:visibility="gone"/>
-
-    <View
-        android:id="@+id/car_ui_toolbar_bottom_styleable"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
-        style="@style/Widget.CarUi.Toolbar.BottomView"
-        app:layout_constraintBottom_toTopOf="@+id/car_ui_toolbar_progress_bar"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/layout/car_ui_toolbar_two_row.xml b/car-ui-lib/res/layout/car_ui_toolbar_two_row.xml
deleted file mode 100644
index ea93323..0000000
--- a/car-ui-lib/res/layout/car_ui_toolbar_two_row.xml
+++ /dev/null
@@ -1,188 +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.
--->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:id="@+id/car_ui_toolbar_background"
-    style="@style/Widget.CarUi.Toolbar.Container">
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_start_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_start_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_top_guideline"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_top_inset"
-        android:orientation="horizontal"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_end_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_end_inset"
-        android:orientation="vertical"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:id="@+id/car_ui_toolbar_bottom_guideline"
-        app:layout_constraintGuide_end="@dimen/car_ui_toolbar_bottom_inset"
-        android:orientation="horizontal"/>
-
-    <!-- When the user finishes searching, we call clearFocus() on the editText in the search bar.
-         clearFocus() will actually send the focus to the first focusable thing in the layout.
-         If that focusable thing is still the search bar it will just reselect it, and the user won't
-         be able to deselect. So make a focusable view here to guarantee that we can clear the focus -->
-    <View
-        android:layout_width="1dp"
-        android:layout_height="1dp"
-        android:focusable="true"
-        android:focusableInTouchMode="true"/>
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/car_ui_toolbar_row_separator_guideline"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:orientation="horizontal"
-        app:layout_constraintGuide_begin="@dimen/car_ui_toolbar_first_row_height"/>
-
-    <View
-        android:id="@+id/car_ui_toolbar_row_separator"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_separator_height"
-        style="@style/Widget.CarUi.Toolbar.SeparatorView"
-        app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator_guideline"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_nav_icon_container"
-        android:layout_width="@dimen/car_ui_toolbar_margin"
-        android:layout_height="0dp"
-        style="@style/Widget.CarUi.Toolbar.NavIconContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toStartOf="@id/car_ui_toolbar_start_guideline">
-        <ImageView
-            android:id="@+id/car_ui_toolbar_nav_icon"
-            android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"
-            style="@style/Widget.CarUi.Toolbar.NavIcon"/>
-        <ImageView
-            android:id="@+id/car_ui_toolbar_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:layout_gravity="center"
-            android:scaleType="fitXY"/>
-    </FrameLayout>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_title_logo_container"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="@style/Widget.CarUi.Toolbar.LogoContainer"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_nav_icon_container">
-
-        <ImageView
-            android:id="@+id/car_ui_toolbar_title_logo"
-            android:layout_width="@dimen/car_ui_toolbar_logo_size"
-            android:layout_height="@dimen/car_ui_toolbar_logo_size"
-            android:scaleType="fitXY"
-            android:layout_gravity="center"
-            style="@style/Widget.CarUi.Toolbar.Logo"/>
-    </FrameLayout>
-
-    <LinearLayout android:layout_height="wrap_content"
-                  android:layout_width="0dp"
-                  android:id="@+id/car_ui_toolbar_title_container"
-                  android:orientation="vertical"
-                  android:layout_marginStart="@dimen/car_ui_toolbar_title_margin_start"
-                  app:layout_goneMarginStart="@dimen/car_ui_toolbar_title_no_logo_margin_start"
-                  app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-                  app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-                  app:layout_constraintStart_toEndOf="@id/car_ui_toolbar_title_logo_container"
-                  app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_menu_items_container">
-        <TextView android:id="@+id/car_ui_toolbar_title"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:singleLine="true"
-                  style="@style/Widget.CarUi.Toolbar.Title"/>
-        <TextView android:id="@+id/car_ui_toolbar_subtitle"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:visibility="gone"
-                  style="@style/Widget.CarUi.Toolbar.Subtitle"/>
-    </LinearLayout>
-
-    <FrameLayout
-        android:id="@+id/car_ui_toolbar_search_view_container"
-        android:layout_width="0dp"
-        android:layout_height="@dimen/car_ui_toolbar_search_height"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintStart_toEndOf="@+id/car_ui_toolbar_nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/car_ui_toolbar_menu_items_container"/>
-
-    <LinearLayout
-        android:id="@+id/car_ui_toolbar_menu_items_container"
-        android:layout_width="wrap_content"
-        android:layout_height="0dp"
-        android:orientation="horizontal"
-        style="@style/Widget.CarUi.Toolbar.MenuItem.Container"
-        app:layout_constraintTop_toTopOf="@id/car_ui_toolbar_top_guideline"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintEnd_toStartOf="@id/car_ui_toolbar_end_guideline"/>
-
-    <com.android.car.ui.toolbar.TabLayout
-        android:id="@+id/car_ui_toolbar_tabs"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_second_row_height"
-        app:layout_constraintTop_toBottomOf="@id/car_ui_toolbar_row_separator"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_guideline"/>
-
-    <View
-        android:id="@+id/car_ui_toolbar_bottom_styleable"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_ui_toolbar_bottom_view_height"
-        style="@style/Widget.CarUi.Toolbar.BottomView"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <ProgressBar
-        android:id="@+id/car_ui_toolbar_progress_bar"
-        style="@style/Widget.CarUi.Toolbar.ProgressBar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:layout_constraintBottom_toTopOf="@id/car_ui_toolbar_bottom_styleable"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        android:indeterminate="true"
-        android:visibility="gone"/>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/res/values-af/strings.xml b/car-ui-lib/res/values-af/strings.xml
deleted file mode 100644
index 8404aca..0000000
--- a/car-ui-lib/res/values-af/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Soek …"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Rollees af"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Rollees op"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Terug"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Soek"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Instellings"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Oorloop"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Kanselleer"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Aan"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Af"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Maak toe"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Rollees word beperk terwyl jy bestuur"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Kenmerk is nie beskikbaar terwyl jy bestuur nie"</string>
-</resources>
diff --git a/car-ui-lib/res/values-am/strings.xml b/car-ui-lib/res/values-am/strings.xml
deleted file mode 100644
index 55c7fc8..0000000
--- a/car-ui-lib/res/values-am/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ይፈልጉ…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"ወደ ታች ይሸብልሉ"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ወደ ላይ ይሸብልሉ"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ተመለስ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"ፈልግ"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ቅንብሮች"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ትርፍ ፍሰት"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"እሺ"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ይቅር"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"አብራ"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ቅናሽ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"ዝጋ"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"እየነዱ ማሸብለል ተገድቧል"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"እየነዱ ሳለ ባህሪው አይገኝም"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ar/strings.xml b/car-ui-lib/res/values-ar/strings.xml
deleted file mode 100644
index 9bfe85f..0000000
--- a/car-ui-lib/res/values-ar/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"بحث…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"التمرير للأسفل"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"التمرير للأعلى"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"رجوع"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"بحث"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"إعدادات"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"القائمة الكاملة"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"حسنًا"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"إلغاء"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"مفعّل"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"غير مفعَّل"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"إغلاق"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"هناك حد أقصى للتمرير على الشاشة أثناء القيادة."</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"لا تتوفَّر هذه الميزة أثناء القيادة."</string>
-</resources>
diff --git a/car-ui-lib/res/values-as/strings.xml b/car-ui-lib/res/values-as/strings.xml
deleted file mode 100644
index 2fa5db9..0000000
--- a/car-ui-lib/res/values-as/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"সন্ধান কৰক…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"তললৈ স্ক্ৰ’ল কৰক"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ওপৰলৈ স্ক্ৰ’ল কৰক"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"উভতি যাওক"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ছেটিংসমূহ"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"অভাৰফ্ল’"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ঠিক আছে"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"বাতিল কৰক"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"অন আছে"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"অফ আছে"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"বন্ধ কৰক"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"গাড়ী চলাই থকা সময়ত স্ক্ৰ’ল কৰাটো সীমিত কৰা হৈছে"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"গাড়ী চলাই থকা সময়ত এই সুবিধাটো উপলব্ধ নহয়"</string>
-</resources>
diff --git a/car-ui-lib/res/values-az/strings.xml b/car-ui-lib/res/values-az/strings.xml
deleted file mode 100644
index 63cb2bc..0000000
--- a/car-ui-lib/res/values-az/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Axtarış…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Aşağı sürüşdürün"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Yuxarı sürüşdürün"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Geri"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Axtarış"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Ayarlar"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Kənara çıxma"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ok"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Ləğv edin"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Aktiv"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Deaktiv"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Qapadın"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Sürüşdürmə avtomobil idarə edərkən məhdudlaşdırılır"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funksiya avtomobil idarə edərkən əlçatan deyil"</string>
-</resources>
diff --git a/car-ui-lib/res/values-b+sr+Latn/strings.xml b/car-ui-lib/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index 104095f..0000000
--- a/car-ui-lib/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Pretražite…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Pomerite nadole"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Pomerite nagore"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Nazad"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Pretraži"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Podešavanja"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Preklopni meni"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Potvrdi"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Otkaži"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Uključeno"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Isključeno"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Zatvori"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Pomeranje je ograničeno tokom vožnje"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkcija nije dostupna tokom vožnje"</string>
-</resources>
diff --git a/car-ui-lib/res/values-be/strings.xml b/car-ui-lib/res/values-be/strings.xml
deleted file mode 100644
index 643faa7..0000000
--- a/car-ui-lib/res/values-be/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Пошук…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Прагартаць уніз"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Прагартаць уверх"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Назад"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Пошук"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Налады"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Дадатковае меню"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ОК"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Скасаваць"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Уключана"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Выключана"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Закрыць"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Функцыя прагортвання абмежаваная, калі аўтамабіль рухаецца"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Функцыя недаступная, калі аўтамабіль рухаецца"</string>
-</resources>
diff --git a/car-ui-lib/res/values-bg/strings.xml b/car-ui-lib/res/values-bg/strings.xml
deleted file mode 100644
index 714b410..0000000
--- a/car-ui-lib/res/values-bg/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Търсете…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Превъртане надолу"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Превъртане нагоре"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Назад"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Търсене"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Настройки"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Препълване"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Отказ"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Вкл."</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Изкл."</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Затваряне"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Превъртането е ограничено при шофиране"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Функцията не е налице по време на шофиране"</string>
-</resources>
diff --git a/car-ui-lib/res/values-bn/strings.xml b/car-ui-lib/res/values-bn/strings.xml
deleted file mode 100644
index 333887b..0000000
--- a/car-ui-lib/res/values-bn/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"সার্চ করুন…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"নিচের দিকে স্ক্রল করুন"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"উপরের দিকে স্ক্রল করুন"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ফিরুন"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"সেটিংস"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ওভারফ্লো মেনু"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"আচ্ছা"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"বাতিল করুন"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"চালু"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"বন্ধ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"বন্ধ করুন"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"গাড়ি চালানোর সময় স্ক্রলিং ফিচার সীমিতভাবে ব্যবহার করা যাবে"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"গাড়ি চালানোর সময় এই ফিচার কাজ করবে না"</string>
-</resources>
diff --git a/car-ui-lib/res/values-bs/strings.xml b/car-ui-lib/res/values-bs/strings.xml
deleted file mode 100644
index c08deb5..0000000
--- a/car-ui-lib/res/values-bs/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Pretražite…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Klizanje prema dolje"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Klizanje prema gore"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Nazad"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Pretraživanje"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Postavke"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Preklopni meni"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Uredu"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Otkaži"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Uključeno"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Isključeno"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Zatvori"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Klizanje je ograničeno tokom vožnje"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkcija nije dostupna tokom vožnje"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ca/strings.xml b/car-ui-lib/res/values-ca/strings.xml
deleted file mode 100644
index db00c39..0000000
--- a/car-ui-lib/res/values-ca/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Cerca…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Desplaça cap avall"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Desplaça cap amunt"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Enrere"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Cerca"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Configuració"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Menú addicional"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"D\'acord"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancel·la"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Activat"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Desactivat"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Tanca"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"El desplaçament està limitat mentre condueixes"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Aquesta funció no està disponible mentre condueixes"</string>
-</resources>
diff --git a/car-ui-lib/res/values-cs/strings.xml b/car-ui-lib/res/values-cs/strings.xml
deleted file mode 100644
index 50e7191..0000000
--- a/car-ui-lib/res/values-cs/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Vyhledat…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Posunout dolů"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Posunout nahoru"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Zpět"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Hledat"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Nastavení"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Rozbalovací nabídka"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Zrušit"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Zap"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Vyp"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Zavřít"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Posouvání zobrazení je při řízení omezeno"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkce při řízení není dostupná"</string>
-</resources>
diff --git a/car-ui-lib/res/values-da/strings.xml b/car-ui-lib/res/values-da/strings.xml
deleted file mode 100644
index 2b01661..0000000
--- a/car-ui-lib/res/values-da/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Søg…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Rul ned"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Rul op"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Tilbage"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Søg"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Indstillinger"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overløb"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Luk"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Til"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Fra"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Luk"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Rullefunktionen er begrænset under kørsel"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funktionen er ikke tilgængelig, mens du kører"</string>
-</resources>
diff --git a/car-ui-lib/res/values-de/strings.xml b/car-ui-lib/res/values-de/strings.xml
deleted file mode 100644
index 14502c8..0000000
--- a/car-ui-lib/res/values-de/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Suchen…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Nach unten scrollen"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Nach oben scrollen"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Zurück"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Suchen"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Einstellungen"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Dreipunkt-Menü"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Abbrechen"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"An"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Aus"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Schließen"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scrollen während der Fahrt eingeschränkt"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funktion während der Fahrt nicht verfügbar"</string>
-</resources>
diff --git a/car-ui-lib/res/values-el/strings.xml b/car-ui-lib/res/values-el/strings.xml
deleted file mode 100644
index 90f9e5c..0000000
--- a/car-ui-lib/res/values-el/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Αναζήτηση…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Κύλιση προς τα κάτω"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Κύλιση προς τα επάνω"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Πίσω"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Αναζήτηση"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Ρυθμίσεις"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Υπερχείλιση"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Άκυρο"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Ενεργό"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Ανενεργή"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Κλείσιμο"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Η κύλιση είναι περιορισμένη κατά τη διάρκεια της οδήγησης."</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Η λειτουργία δεν διατίθεται κατά τη διάρκεια της οδήγησης."</string>
-</resources>
diff --git a/car-ui-lib/res/values-en-rAU/strings.xml b/car-ui-lib/res/values-en-rAU/strings.xml
deleted file mode 100644
index 14455e4..0000000
--- a/car-ui-lib/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Search…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Scroll down"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Scroll up"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Back"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Settings"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overflow"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancel"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"On"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Off"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Close"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scrolling limited while driving"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Feature not available while driving"</string>
-</resources>
diff --git a/car-ui-lib/res/values-en-rCA/strings.xml b/car-ui-lib/res/values-en-rCA/strings.xml
deleted file mode 100644
index 14455e4..0000000
--- a/car-ui-lib/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Search…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Scroll down"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Scroll up"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Back"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Settings"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overflow"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancel"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"On"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Off"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Close"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scrolling limited while driving"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Feature not available while driving"</string>
-</resources>
diff --git a/car-ui-lib/res/values-en-rGB/strings.xml b/car-ui-lib/res/values-en-rGB/strings.xml
deleted file mode 100644
index 14455e4..0000000
--- a/car-ui-lib/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Search…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Scroll down"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Scroll up"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Back"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Settings"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overflow"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancel"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"On"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Off"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Close"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scrolling limited while driving"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Feature not available while driving"</string>
-</resources>
diff --git a/car-ui-lib/res/values-en-rIN/strings.xml b/car-ui-lib/res/values-en-rIN/strings.xml
deleted file mode 100644
index 14455e4..0000000
--- a/car-ui-lib/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Search…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Scroll down"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Scroll up"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Back"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Settings"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overflow"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancel"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"On"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Off"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Close"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scrolling limited while driving"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Feature not available while driving"</string>
-</resources>
diff --git a/car-ui-lib/res/values-en-rXC/strings.xml b/car-ui-lib/res/values-en-rXC/strings.xml
deleted file mode 100644
index cc754fd..0000000
--- a/car-ui-lib/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎Search…‎‏‎‎‏‎"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎Scroll down‎‏‎‎‏‎"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎Scroll up‎‏‎‎‏‎"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‎Back‎‏‎‎‏‎"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‎‎Search‎‏‎‎‏‎"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎Settings‎‏‎‎‏‎"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎Overflow‎‏‎‎‏‎"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎Ok‎‏‎‎‏‎"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎Cancel‎‏‎‎‏‎"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎On‎‏‎‎‏‎"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎Off‎‏‎‎‏‎"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎Close‎‏‎‎‏‎"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎Scrolling limited while driving‎‏‎‎‏‎"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‏‎Feature not available while driving‎‏‎‎‏‎"</string>
-</resources>
diff --git a/car-ui-lib/res/values-es-rUS/strings.xml b/car-ui-lib/res/values-es-rUS/strings.xml
deleted file mode 100644
index 31c5bd1..0000000
--- a/car-ui-lib/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Buscar…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Desplazamiento hacia abajo"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Desplazamiento hacia arriba"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Atrás"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Buscar"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Configuración"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Ampliado"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Aceptar"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancelar"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Sí"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"No"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Cerrar"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"La función de desplazamiento se limita al conducir"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Esta función no está disponible mientras conduces"</string>
-</resources>
diff --git a/car-ui-lib/res/values-es/strings.xml b/car-ui-lib/res/values-es/strings.xml
deleted file mode 100644
index 145d73e..0000000
--- a/car-ui-lib/res/values-es/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Realiza una búsqueda…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Desplazarse hacia abajo"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Desplazarse hacia arriba"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Atrás"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Buscar"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Ajustes"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Menú adicional"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Aceptar"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancelar"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Activado"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Desactivado"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Cerrar"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Desplazamiento limitado mientras conduces"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Función no disponible mientras conduces"</string>
-</resources>
diff --git a/car-ui-lib/res/values-et/strings.xml b/car-ui-lib/res/values-et/strings.xml
deleted file mode 100644
index 0d494d1..0000000
--- a/car-ui-lib/res/values-et/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Otsing …"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Keri alla"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Keri üles"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Tagasi"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Otsi"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Seaded"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Ületäide"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Tühista"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Sees"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Väljas"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Sule"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Kerimine on sõitmise ajal piiratud"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funktsioon pole sõidu ajal saadaval"</string>
-</resources>
diff --git a/car-ui-lib/res/values-eu/strings.xml b/car-ui-lib/res/values-eu/strings.xml
deleted file mode 100644
index 3935830..0000000
--- a/car-ui-lib/res/values-eu/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Bilatu…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Egin behera"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Egin gora"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Atzera"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Bilaketa"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Ezarpenak"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Luzapena"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ados"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Utzi"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Aktibatuta"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Desaktibatuta"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Itxi"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Gora edo behera egiteko eginbidea mugatuta dago gidatu bitartean"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Eginbide hau ezin da erabili gidatu bitartean"</string>
-</resources>
diff --git a/car-ui-lib/res/values-fa/strings.xml b/car-ui-lib/res/values-fa/strings.xml
deleted file mode 100644
index 9d8b9f6..0000000
--- a/car-ui-lib/res/values-fa/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"جستجو…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"پیمایش به پایین"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"پیمایش به بالا"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"برگشت"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"جستجو"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"تنظیمات"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"لبریزشده"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"تأیید"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"لغو"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"روشن"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"خاموش"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"بستن"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"پیمایش درحین رانندگی محدود شده است"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"این ویژگی هنگام رانندگی در دسترس نیست"</string>
-</resources>
diff --git a/car-ui-lib/res/values-fi/strings.xml b/car-ui-lib/res/values-fi/strings.xml
deleted file mode 100644
index 78aa846..0000000
--- a/car-ui-lib/res/values-fi/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Hae…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Vieritä alas"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Vieritä ylös"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Takaisin"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Haku"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Asetukset"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Ylivuoto"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Peruuta"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Päällä"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Pois"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Sulje"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Vierittämistä rajoitettu ajon aikana"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Ominaisuus ei ole käytettävissä ajon aikana"</string>
-</resources>
diff --git a/car-ui-lib/res/values-fr-rCA/strings.xml b/car-ui-lib/res/values-fr-rCA/strings.xml
deleted file mode 100644
index e5a7c6f..0000000
--- a/car-ui-lib/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Rechercher…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Faire défiler vers le bas"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Faire défiler vers le haut"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Retour"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Rechercher"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Paramètres"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Menu déroulant"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Annuler"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Activé"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Désactivé"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Fermer"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Le défilement de l\'écran est limité durant la conduite"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Cette fonctionnalité n\'est pas accessible durant la conduite"</string>
-</resources>
diff --git a/car-ui-lib/res/values-fr/strings.xml b/car-ui-lib/res/values-fr/strings.xml
deleted file mode 100644
index cd58390..0000000
--- a/car-ui-lib/res/values-fr/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Rechercher…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Défiler vers le bas"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Défiler vers le haut"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Retour"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Rechercher"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Paramètres"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Menu à développer"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Annuler"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Activé"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Désactivé"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Fermer"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Défilement limité lorsque vous conduisez"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Fonctionnalité non disponible lorsque vous conduisez"</string>
-</resources>
diff --git a/car-ui-lib/res/values-gl/strings.xml b/car-ui-lib/res/values-gl/strings.xml
deleted file mode 100644
index 7b7356c..0000000
--- a/car-ui-lib/res/values-gl/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Busca…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Desprazarse cara abaixo"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Desprazarse cara arriba"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Atrás"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Buscar"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Configuración"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Elemento do menú adicional"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Aceptar"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancelar"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Si"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Non"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Pechar"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"O desprazamento está limitado mentres conduces"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Esta función non está dispoñible mentres conduces"</string>
-</resources>
diff --git a/car-ui-lib/res/values-gu/strings.xml b/car-ui-lib/res/values-gu/strings.xml
deleted file mode 100644
index 081510c..0000000
--- a/car-ui-lib/res/values-gu/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"શોધો…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"નીચે સ્ક્રોલ કરો"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ઉપર સ્ક્રોલ કરો"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"પાછળ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"સેટિંગ"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ઓવરફ્લો"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ઓકે"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"રદ કરો"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ચાલુ"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"બંધ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"બંધ કરો"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ડ્રાઇવિંગ કરતી વખતે સ્ક્રોલ કરવું મર્યાદિત છે"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ડ્રાઇવિંગ કરતી વખતે આ સુવિધા ઉપલબ્ધ રહેશે નહીં"</string>
-</resources>
diff --git a/car-ui-lib/res/values-hi/strings.xml b/car-ui-lib/res/values-hi/strings.xml
deleted file mode 100644
index 4900774..0000000
--- a/car-ui-lib/res/values-hi/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"खोजें…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"नीचे की ओर स्क्रोल करें"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ऊपर की ओर स्क्रोल करें"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"वापस जाएं"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"खोजें"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"सेटिंग"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ओवरफ़्लो मेन्यू"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ठीक है"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"अभी नहीं"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"चालू है"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"बंद है"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"बंद करें"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"गाड़ी चलाते समय इससे ज़्यादा स्क्रोल नहीं कर सकते"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"गाड़ी चलाते समय इस सुविधा का इस्तेमाल नहीं किया जा सकता"</string>
-</resources>
diff --git a/car-ui-lib/res/values-hr/strings.xml b/car-ui-lib/res/values-hr/strings.xml
deleted file mode 100644
index 2f64956..0000000
--- a/car-ui-lib/res/values-hr/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Pretražite…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Pomak prema dolje"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Pomak prema gore"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Natrag"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Pretraži"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Postavke"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Dodatno"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"U redu"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Odustani"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Uključeno"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Isključeno"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Zatvori"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Pomicanje je ograničeno tijekom vožnje"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Značajka nije dostupna tijekom vožnje"</string>
-</resources>
diff --git a/car-ui-lib/res/values-hu/strings.xml b/car-ui-lib/res/values-hu/strings.xml
deleted file mode 100644
index 3f8233a..0000000
--- a/car-ui-lib/res/values-hu/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Keresés…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Görgetés lefelé"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Görgetés felfelé"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Vissza"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Keresés"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Beállítások"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"További elemeket tartalmazó menü"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Mégse"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Be"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Ki"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Bezárás"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Vezetés közben a görgetés korlátozott"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Vezetés közben nem áll rendelkezésre a funkció"</string>
-</resources>
diff --git a/car-ui-lib/res/values-hy/strings.xml b/car-ui-lib/res/values-hy/strings.xml
deleted file mode 100644
index ff952ea..0000000
--- a/car-ui-lib/res/values-hy/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Որոնում…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Ոլորել վար"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Ոլորել վեր"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Հետ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Որոնել"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Կարգավորումներ"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Լրացուցիչ ընտրացանկ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Եղավ"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Չեղարկել"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Միացված է"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Անջատված է"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Փակել"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Վարելու ընթացքում ոլորումը սահմանափակված է"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Վարելու ընթացքում գործառույթը հասանելի չէ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-in/strings.xml b/car-ui-lib/res/values-in/strings.xml
deleted file mode 100644
index daf9e0f..0000000
--- a/car-ui-lib/res/values-in/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Telusuri…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Scroll ke bawah"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Scroll ke atas"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Kembali"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Penelusuran"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Setelan"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Tambahan"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Oke"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Batal"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Aktif"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Nonaktif"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Tutup"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Men-scroll dibatasi saat mengemudi"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Fitur tidak tersedia saat mengemudi"</string>
-</resources>
diff --git a/car-ui-lib/res/values-is/strings.xml b/car-ui-lib/res/values-is/strings.xml
deleted file mode 100644
index 5cc3463..0000000
--- a/car-ui-lib/res/values-is/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Leita…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Fletta niður"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Fletta upp"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Til baka"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Leit"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Stillingar"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Yfirflæði"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Í lagi"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Hætta"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Kveikt"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Slökkt"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Loka"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Fletting er takmörkuð meðan á akstri stendur"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Þessi eiginleiki er ekki í boði meðan á akstri stendur"</string>
-</resources>
diff --git a/car-ui-lib/res/values-it/strings.xml b/car-ui-lib/res/values-it/strings.xml
deleted file mode 100644
index 2386303..0000000
--- a/car-ui-lib/res/values-it/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Cerca…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Scorri verso il basso"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Scorri verso l\'alto"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Indietro"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Cerca"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Impostazioni"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Extra"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Annulla"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"On"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Off"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Chiudi"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scorrimento limitato durante la guida"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funzionalità non disponibile durante la guida"</string>
-</resources>
diff --git a/car-ui-lib/res/values-iw/strings.xml b/car-ui-lib/res/values-iw/strings.xml
deleted file mode 100644
index 543da53..0000000
--- a/car-ui-lib/res/values-iw/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"חיפוש…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"גלילה למטה"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"גלילה למעלה"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"חזרה"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"חיפוש"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"הגדרות"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"אפשרויות נוספות"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"אישור"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ביטול"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"פועל"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"כבוי"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"סגירה"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"הגלילה מוגבלת בזמן הנהיגה"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"התכונה לא זמינה בזמן הנהיגה"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ja/strings.xml b/car-ui-lib/res/values-ja/strings.xml
deleted file mode 100644
index 7db4ad8..0000000
--- a/car-ui-lib/res/values-ja/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"検索…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"下にスクロール"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"上にスクロール"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"戻る"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"検索"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"設定"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"オーバーフロー"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"キャンセル"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ON"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"OFF"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"閉じる"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"運転中のスクロール操作は制限されています"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"この機能は運転中は利用できません"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ka/strings.xml b/car-ui-lib/res/values-ka/strings.xml
deleted file mode 100644
index 2e6a0da..0000000
--- a/car-ui-lib/res/values-ka/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ძიება…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"ქვემოთ გადაადგილება"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ზემოთ გადაადგილება"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"უკან"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"ძიება"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"პარამეტრები"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"გადავსება"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"კარგი"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"გაუქმება"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ჩართულია"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"გამორთულია"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"დახურვა"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"გადაადგილება შეზღუდულია მანქანის მართვისას"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ფუნქცია მიუწვდომელია მანქანის მართვისას"</string>
-</resources>
diff --git a/car-ui-lib/res/values-kk/strings.xml b/car-ui-lib/res/values-kk/strings.xml
deleted file mode 100644
index 3d32de3..0000000
--- a/car-ui-lib/res/values-kk/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Іздеу…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Төмен айналдыру"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Жоғары айналдыру"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Артқа"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Іздеу"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Параметрлер"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Қосымша мәзір"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Жарайды"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Бас тарту"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Қосулы"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Өшірулі"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Жабу"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Көлік жүргізу кезінде айналдыру мүмкіндігі шектеледі."</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Көлік жүргізу кезінде бұл функция жұмыс істемейді."</string>
-</resources>
diff --git a/car-ui-lib/res/values-km/strings.xml b/car-ui-lib/res/values-km/strings.xml
deleted file mode 100644
index 65aa214..0000000
--- a/car-ui-lib/res/values-km/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ស្វែងរក…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"រំកិលចុះក្រោម"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"រំកិល​​ឡើង​លើ"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ថយក្រោយ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"ស្វែងរក"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ការកំណត់"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ម៉ឺនុយបន្ថែម"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"យល់ព្រម"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"បោះបង់"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"បើក"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"បិទ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"បិទ"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ការរំកិលបានកំណត់ ខណៈពេលកំពុង​បើកបរ"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"មិនអាច​ប្រើមុខងារ​នេះបានទេ ខណៈពេល​កំពុង​បើកបរ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-kn/strings.xml b/car-ui-lib/res/values-kn/strings.xml
deleted file mode 100644
index a0e7a85..0000000
--- a/car-ui-lib/res/values-kn/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ಹುಡುಕಿ…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"ಕೆಳಗೆ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ಮೇಲೆ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ಹಿಂದಕ್ಕೆ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ಓವರ್‌ಫ್ಲೋ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ಸರಿ"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ರದ್ದುಮಾಡಿ"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ಆನ್ ಆಗಿದೆ"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ಆಫ್ ಆಗಿದೆ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"ಮುಚ್ಚಿ"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ಡ್ರೈವ್ ಮಾಡುವಾಗ ಸ್ಕ್ರಾಲ್ ಮಾಡುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸೀಮಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ಡ್ರೈವ್ ಮಾಡುವಾಗ ಈ ವೈಶಿಷ್ಟ್ಯ ಲಭ್ಯವಿಲ್ಲ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ko/strings.xml b/car-ui-lib/res/values-ko/strings.xml
deleted file mode 100644
index bf84fb9..0000000
--- a/car-ui-lib/res/values-ko/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"검색…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"아래로 스크롤"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"위로 스크롤"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"뒤로"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"검색"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"설정"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"더보기"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"확인"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"취소"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"사용 설정됨"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"사용 중지됨"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"닫기"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"운전 중에는 스크롤이 제한됨"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"운전 중에 사용할 수 없는 기능입니다."</string>
-</resources>
diff --git a/car-ui-lib/res/values-ky/strings.xml b/car-ui-lib/res/values-ky/strings.xml
deleted file mode 100644
index 5d55581..0000000
--- a/car-ui-lib/res/values-ky/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Издөө…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Төмөн сыдыруу"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Жогору сыдыруу"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Артка"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Издөө"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Жөндөөлөр"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Кошумча меню"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Жарайт"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Жок"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Күйүк"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Өчүк"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Жабуу"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Унаа айдаганда сыдыруу чектелет"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Унаа айдаганда бул функция жеткиликтүү эмес"</string>
-</resources>
diff --git a/car-ui-lib/res/values-lo/strings.xml b/car-ui-lib/res/values-lo/strings.xml
deleted file mode 100644
index e17fae2..0000000
--- a/car-ui-lib/res/values-lo/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ຊອກຫາ…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"ເລື່ອນລົງ"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ເລື່ອນຂຶ້ນ"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ກັບຄືນ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"ຊອກຫາ"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ການຕັ້ງຄ່າ"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ລົ້ນ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ຕົກລົງ"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ຍົກເລີກ"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ເປີດ"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ປິດ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"ປິດ"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ຈຳກັດການເລື່ອນໃນຂະນະທີ່ຂັບລົດ"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ຄຸນສົມບັດບໍ່ສາມາດໃຊ້ໄດ້ໃນເວລາຂັບລົດ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-lt/strings.xml b/car-ui-lib/res/values-lt/strings.xml
deleted file mode 100644
index 2946f72..0000000
--- a/car-ui-lib/res/values-lt/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Ieškoti…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Slinkti žemyn"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Slinkti aukštyn"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Atgal"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Paieška"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Nustatymai"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Perpildymas"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Gerai"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Atšaukti"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Įjungta"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Išjungta"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Uždaryti"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Slinkimas apribotas vairuojant"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkcija nepasiekiama vairuojant"</string>
-</resources>
diff --git a/car-ui-lib/res/values-lv/strings.xml b/car-ui-lib/res/values-lv/strings.xml
deleted file mode 100644
index 4f658c7..0000000
--- a/car-ui-lib/res/values-lv/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Meklēt…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Ritināt uz leju"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Ritināt uz augšu"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Atpakaļ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Meklēšana"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Iestatījumi"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Pārpilde"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Labi"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Atcelt"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Ieslēgta"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Izslēgta"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Aizvērt"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Ritināšana ir ierobežota braukšanas laikā."</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkcija nav pieejama braukšanas laikā."</string>
-</resources>
diff --git a/car-ui-lib/res/values-mk/strings.xml b/car-ui-lib/res/values-mk/strings.xml
deleted file mode 100644
index 1470f8d..0000000
--- a/car-ui-lib/res/values-mk/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Пребарувајте…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Оди надолу"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Оди нагоре"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Назад"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Пребарување"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Поставки"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Прелевање"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Во ред"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Откажи"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Вклучено"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Исклучено"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Затвори"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Лизгањето е ограничено при возење"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Функцијата не е достапна при возење"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ml/strings.xml b/car-ui-lib/res/values-ml/strings.xml
deleted file mode 100644
index e324e7c..0000000
--- a/car-ui-lib/res/values-ml/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"തിരയുക…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"താഴോട്ട് സ്‌ക്രോൾ ചെയ്യുക"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"മുകളിലോട്ട് സ്‌ക്രോൾ ചെയ്യുക"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"മടങ്ങുക"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ക്രമീകരണം"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ഓവർഫ്ലോ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ശരി"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"റദ്ദാക്കുക"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ഓണാണ്"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ഓഫാണ്"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"അടയ്‌ക്കുക"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ഡ്രൈവ് ചെയ്യുമ്പോൾ സ്ക്രോൾ ചെയ്യൽ പരിമിതപ്പെടുത്തിയിരിക്കുന്നു"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ഡ്രൈവ് ചെയ്യുമ്പോൾ ഫീച്ചർ ലഭ്യമല്ല"</string>
-</resources>
diff --git a/car-ui-lib/res/values-mn/strings.xml b/car-ui-lib/res/values-mn/strings.xml
deleted file mode 100644
index 7c62426..0000000
--- a/car-ui-lib/res/values-mn/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Хайх..."</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Доош гүйлгэх"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Дээш гүйлгэх"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Буцах"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Хайлт"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Тохиргоо"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Халих"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ок"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Болих"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Асаалттай"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Унтраалттай"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Хаах"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Жолоо барьж байх үед гүйлгэхийг хязгаарласан"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Жолоо барьж байх үед онцлог боломжгүй"</string>
-</resources>
diff --git a/car-ui-lib/res/values-mr/strings.xml b/car-ui-lib/res/values-mr/strings.xml
deleted file mode 100644
index 339a363..0000000
--- a/car-ui-lib/res/values-mr/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"शोधा…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"खाली स्क्रोल करा"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"वर स्क्रोल करा"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"मागे जा"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"सेटिंग्ज"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ओव्हरफ्लो"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ओके"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"रद्द करा"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"सुरू आहे"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"बंद आहे"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"बंद करा"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ड्राइव्ह करताना स्क्रोलिंग मर्यादित केली आहे"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ड्राइव्ह करताना वैशिष्ट्य उपलब्ध नाही"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ms/strings.xml b/car-ui-lib/res/values-ms/strings.xml
deleted file mode 100644
index d31613e..0000000
--- a/car-ui-lib/res/values-ms/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Cari…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Tatal ke bawah"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Tatal ke atas"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Kembali"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Cari"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Tetapan"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Limpahan"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ok"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Batal"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Hidup"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Mati"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Tutup"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Penatalan terhad semasa memandu"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Ciri tidak tersedia semasa anda memandu"</string>
-</resources>
diff --git a/car-ui-lib/res/values-my/strings.xml b/car-ui-lib/res/values-my/strings.xml
deleted file mode 100644
index adada08..0000000
--- a/car-ui-lib/res/values-my/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ရှာဖွေရန်…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"အောက်သို့ လှိမ့်ရန်"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"အပေါ်သို့ လှိမ့်ရန်"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"နောက်သို့"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"ရှာဖွေခြင်း"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ဆက်တင်များ"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"အပို"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"မလုပ်တော့"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ဖွင့်ထားသည်"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ပိတ်ထားသည်"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"ပိတ်ရန်"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ယာဉ်မောင်းနေစဉ် အပေါ်အောက်ရွှေ့ခြင်းကို ကန့်သတ်ထားသည်"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ကားမောင်းနေစဉ် ဝန်ဆောင်မှု မရနိုင်ပါ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-nb/strings.xml b/car-ui-lib/res/values-nb/strings.xml
deleted file mode 100644
index 21160c8..0000000
--- a/car-ui-lib/res/values-nb/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Søk"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Rull ned"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Rull opp"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Tilbake"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Søk"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Innstillinger"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overflyt"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Avbryt"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"På"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Av"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Lukk"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Rullefunksjonen er begrenset mens du kjører"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funksjonen er ikke tilgjengelig når du kjører"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ne/strings.xml b/car-ui-lib/res/values-ne/strings.xml
deleted file mode 100644
index f33ac72..0000000
--- a/car-ui-lib/res/values-ne/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"खोज्नुहोस्…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"तलतिर स्क्रोल गर्नुहोस्"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"माथितिर स्क्रोल गर्नु…"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"पछाडि"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"खोज्नुहोस्"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"सेटिङ"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ओभरफ्लो"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ठिक छ"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"रद्द गर्नुहोस्"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"सुचारू छ"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"बन्द छ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"बन्द गर्नुहोस्"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"सवारी साधन चलाइरहेका बेला योभन्दा बढी स्क्रोल गर्न पाइँदैन"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"सवारी साधन चलाइरहेका बेला यो सुविधा उपलब्ध हुँदैन"</string>
-</resources>
diff --git a/car-ui-lib/res/values-nl/strings.xml b/car-ui-lib/res/values-nl/strings.xml
deleted file mode 100644
index da110d5..0000000
--- a/car-ui-lib/res/values-nl/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Zoeken…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Omlaag scrollen"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Omhoog scrollen"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Terug"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Zoeken"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Instellingen"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overloop"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Annuleren"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Aan"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Uit"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Sluiten"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scrollen is beperkt tijdens het rijden"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Functie niet beschikbaar tijdens het rijden"</string>
-</resources>
diff --git a/car-ui-lib/res/values-or/strings.xml b/car-ui-lib/res/values-or/strings.xml
deleted file mode 100644
index 2533631..0000000
--- a/car-ui-lib/res/values-or/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ସନ୍ଧାନ କରନ୍ତୁ…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"ତଳକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ଉପରକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ପଛକୁ ଫେରନ୍ତୁ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ସେଟିଂସ୍"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ଓଭରଫ୍ଲୋ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ଠିକ୍ ଅଛି"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ବାତିଲ୍ କରନ୍ତୁ"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ଚାଲୁ ଅଛି"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ବନ୍ଦ ଅଛି"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"ବନ୍ଦ କରନ୍ତୁ"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ଗାଡ଼ି ଚଲାଇବା ସମୟରେ ସ୍କ୍ରୋଲିଂ ସୀମିତ ଅଟେ"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ଗାଡ଼ି ଚଲାଇବା ସମୟରେ ଫିଚର୍ ଉପଲବ୍ଧ ହେବ ନାହିଁ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-pa/strings.xml b/car-ui-lib/res/values-pa/strings.xml
deleted file mode 100644
index 9910e95..0000000
--- a/car-ui-lib/res/values-pa/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ਖੋਜ…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"ਹੇਠਾਂ ਵੱਲ ਸਕ੍ਰੋਲ ਕਰੋ"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ਉੱਪਰ ਵੱਲ ਸਕ੍ਰੋਲ ਕਰੋ"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ਪਿੱਛੇ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"ਖੋਜ"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ਸੈਟਿੰਗਾਂ"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ਓਵਰਫ਼ਲੋ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ਠੀਕ ਹੈ"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ਰੱਦ ਕਰੋ"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ਚਾਲੂ"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ਬੰਦ"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"ਬੰਦ ਕਰੋ"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ਚਲਦੀ ਗੱਡੀ ਵਿੱਚ ਸਕ੍ਰੋਲ ਕਰਨ ਨੂੰ ਸੀਮਤ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ਚੱਲਦੀ ਗੱਡੀ ਵਿੱਚ ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-pl/strings.xml b/car-ui-lib/res/values-pl/strings.xml
deleted file mode 100644
index 8feefdb..0000000
--- a/car-ui-lib/res/values-pl/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Szukaj…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Przewiń w dół"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Przewiń w górę"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Wstecz"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Szukaj"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Ustawienia"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Rozszerzone menu"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Anuluj"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Wł."</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Wył."</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Zamknij"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Podczas jazdy można przewijać tylko w ograniczonym zakresie"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkcja niedostępna podczas jazdy"</string>
-</resources>
diff --git a/car-ui-lib/res/values-port/bools.xml b/car-ui-lib/res/values-port/bools.xml
deleted file mode 100644
index ed7d502..0000000
--- a/car-ui-lib/res/values-port/bools.xml
+++ /dev/null
@@ -1,25 +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>
-    <!-- Toolbar -->
-    <!-- Normally no resources should live in any other resource folder than default configuration. -->
-    <!-- Because OEMs will have to always add them to their RROs. -->
-    <!-- But we can't remove this resource from -port folder, because it was used as part of an earlier release -->
-    <!-- Whether tabs should use flex layout or not -->
-    <bool name="car_ui_toolbar_tab_flexible_layout">true</bool>
-</resources>
\ No newline at end of file
diff --git a/car-ui-lib/res/values-pt-rPT/strings.xml b/car-ui-lib/res/values-pt-rPT/strings.xml
deleted file mode 100644
index e2c6caa..0000000
--- a/car-ui-lib/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Pesquisar…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Deslocar para baixo"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Deslocar para cima"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Anterior"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Pesquisar"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Definições"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Menu adicional"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancelar"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Ativado"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Desativado"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Fechar"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Deslocamento limitado durante a condução"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funcionalidade não disponível durante a condução."</string>
-</resources>
diff --git a/car-ui-lib/res/values-pt/strings.xml b/car-ui-lib/res/values-pt/strings.xml
deleted file mode 100644
index 6b47812..0000000
--- a/car-ui-lib/res/values-pt/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Pesquisar…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Rolar para baixo"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Rolar para cima"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Voltar"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Pesquisa"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Configurações"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Menu flutuante"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ok"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Cancelar"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Ativada"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Desativada"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Fechar"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"O recurso de rolagem fica limitado enquanto você dirige"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Recurso indisponível enquanto você dirige"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ro/strings.xml b/car-ui-lib/res/values-ro/strings.xml
deleted file mode 100644
index 8d8e771..0000000
--- a/car-ui-lib/res/values-ro/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Căutați…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Derulați în jos"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Derulați în sus"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Înapoi"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Căutați"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Setări"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Suplimentar"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Anulați"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Activat"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Dezactivat"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Închideți"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Derularea este restricționată în timp ce conduceți"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funcția nu este disponibilă când conduceți"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ru/strings.xml b/car-ui-lib/res/values-ru/strings.xml
deleted file mode 100644
index 9db229e..0000000
--- a/car-ui-lib/res/values-ru/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Поиск…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Прокрутить вниз"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Прокрутить вверх"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Назад"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Поиск"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Настройки"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Дополнительное меню"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ОК"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Отмена"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Включено"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Выключено"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Закрыть"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Функция прокручивания ограничена во время вождения."</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Функция недоступна во время вождения."</string>
-</resources>
diff --git a/car-ui-lib/res/values-si/strings.xml b/car-ui-lib/res/values-si/strings.xml
deleted file mode 100644
index 0f18f5e..0000000
--- a/car-ui-lib/res/values-si/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"සොයන්න…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"පහළට අනුචලනය කරන්න"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"ඉහළට අනුචලනය කරන්න"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"ආපසු"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"සෙවීම"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"සැකසීම්"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ඉතිරියනය"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"හරි"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"අවලංගු කරන්න"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ක්‍රියාත්මකයි"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ක්‍රියාවිරහිතයි"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"වසන්න"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"රිය පදවන අතරතුර සීමිත අනුචලනය"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"රිය පදවන අතරේ විශේෂාංගය නොමැත"</string>
-</resources>
diff --git a/car-ui-lib/res/values-sk/strings.xml b/car-ui-lib/res/values-sk/strings.xml
deleted file mode 100644
index 34891ea..0000000
--- a/car-ui-lib/res/values-sk/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Vyhľadať…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Posunúť nadol"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Posunúť nahor"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Späť"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Hľadať"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Nastavenia"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Rozšírená ponuka"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ok"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Zrušiť"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Zap."</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Vyp."</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Zavrieť"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Posúvanie zobrazenia je počas jazdy obmedzené"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkcia nie je k dispozícii počas jazdy"</string>
-</resources>
diff --git a/car-ui-lib/res/values-sl/strings.xml b/car-ui-lib/res/values-sl/strings.xml
deleted file mode 100644
index 330494d..0000000
--- a/car-ui-lib/res/values-sl/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Iskanje …"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Pomik navzdol"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Pomik navzgor"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Nazaj"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Išči"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Nastavitve"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Element menija z dodatnimi elementi"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"V redu"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Prekliči"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Vklopljeno"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Izklopljeno"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Zapri"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Pomikanje je med vožnjo omejeno"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funkcija med vožnjo ni na voljo"</string>
-</resources>
diff --git a/car-ui-lib/res/values-sq/strings.xml b/car-ui-lib/res/values-sq/strings.xml
deleted file mode 100644
index e7cae6b..0000000
--- a/car-ui-lib/res/values-sq/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Kërko…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Lëviz poshtë"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Lëviz lart"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Pas"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Kërko"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Cilësimet"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Tejkalo"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Në rregull"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Anulo"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Aktiv"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Joaktiv"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Mbyll"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Lëvizja është e kufizuar gjatë drejtimit të makinës"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Veçoria nuk ofrohet gjatë drejtimit të makinës"</string>
-</resources>
diff --git a/car-ui-lib/res/values-sr/strings.xml b/car-ui-lib/res/values-sr/strings.xml
deleted file mode 100644
index 0b63d3f..0000000
--- a/car-ui-lib/res/values-sr/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Претражите…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Померите надоле"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Померите нагоре"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Назад"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Претражи"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Подешавања"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Преклопни мени"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Потврди"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Откажи"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Укључено"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Искључено"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Затвори"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Померање је ограничено током вожње"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Функција није доступна током вожње"</string>
-</resources>
diff --git a/car-ui-lib/res/values-sv/strings.xml b/car-ui-lib/res/values-sv/strings.xml
deleted file mode 100644
index 375ac74..0000000
--- a/car-ui-lib/res/values-sv/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Sök …"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Scrolla nedåt"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Scrolla uppåt"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Tillbaka"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Sök"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Inställningar"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Fler menyalternativ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Avbryt"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"På"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Av"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Stäng"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Scrollning begränsas när du kör"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Funktionen är inte tillgänglig när du kör"</string>
-</resources>
diff --git a/car-ui-lib/res/values-sw/strings.xml b/car-ui-lib/res/values-sw/strings.xml
deleted file mode 100644
index a2b549f..0000000
--- a/car-ui-lib/res/values-sw/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Tafuta…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Sogeza chini"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Sogeza juu"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Nyuma"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Tafuta"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Mipangilio"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Vipengee vya ziada"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Sawa"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Ghairi"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Imewashwa"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Imezimwa"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Funga"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Umedhibitiwa kusogeza unapoendesha gari"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Kipengele hakipatikani unapoendesha gari"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ta/strings.xml b/car-ui-lib/res/values-ta/strings.xml
deleted file mode 100644
index 4ca575a..0000000
--- a/car-ui-lib/res/values-ta/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"தேடுக…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"கீழே செல்லும்"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"மேலே செல்லும்"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"பின்செல்வதற்கான பட்டன்"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"அமைப்புகள்"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"ஓவர்ஃப்லோ"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"சரி"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ரத்துசெய்"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ஆன்"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ஆஃப்"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"மூடுக"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"வாகனம் ஓட்டிக் கொண்டிருப்பதனால் இதற்குமேல் ஸ்க்ரோல் செய்ய முடியாது"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"வாகனம் ஓட்டும்போது இந்த அம்சத்தைப் பயன்படுத்த இயலாது"</string>
-</resources>
diff --git a/car-ui-lib/res/values-te/strings.xml b/car-ui-lib/res/values-te/strings.xml
deleted file mode 100644
index 39e4c3e..0000000
--- a/car-ui-lib/res/values-te/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"వెతకండి…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"కిందికి స్క్రోల్ చేయండి"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"పైకి స్క్రోల్ చేయండి"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"వెనుకకు"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Search"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"సెట్టింగ్‌లు"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"అతివ్యాప్తి అంశాలు"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"సరే"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"రద్దు చేయండి"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"ఆన్‌లో ఉంది"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ఆఫ్‌లో ఉంది"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"మూసివేయండి"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"డ్రైవింగ్ చేస్తున్నప్పుడు స్క్రోలింగ్ పరిమితంగా ఉంటుంది"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"డ్రైవింగ్ చేస్తున్నప్పుడు ఈ ఫీచర్ అందుబాటులో ఉండదు"</string>
-</resources>
diff --git a/car-ui-lib/res/values-th/strings.xml b/car-ui-lib/res/values-th/strings.xml
deleted file mode 100644
index fa43930..0000000
--- a/car-ui-lib/res/values-th/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"ค้นหา…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"เลื่อนลง"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"เลื่อนขึ้น"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"กลับ"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"ค้นหา"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"การตั้งค่า"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"รายการเพิ่มเติม"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ตกลง"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"ยกเลิก"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"เปิด"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"ปิด"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"ปิด"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"การเลื่อนถูกจำกัดไม่ให้ใช้งานขณะขับรถ"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ฟีเจอร์ไม่พร้อมใช้งานขณะขับรถ"</string>
-</resources>
diff --git a/car-ui-lib/res/values-tl/strings.xml b/car-ui-lib/res/values-tl/strings.xml
deleted file mode 100644
index 7a95e0e..0000000
--- a/car-ui-lib/res/values-tl/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Maghanap…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Mag-scroll pababa"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Mag-scroll pataas"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Bumalik"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Paghahanap"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Mga Setting"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Overflow"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ok"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Kanselahin"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"I-on"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"I-off"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Isara"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Limitado ang pag-scroll habang nagmamaneho"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Hindi available ang feature habang nagmamaneho"</string>
-</resources>
diff --git a/car-ui-lib/res/values-tr/strings.xml b/car-ui-lib/res/values-tr/strings.xml
deleted file mode 100644
index 3a56e11..0000000
--- a/car-ui-lib/res/values-tr/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Ara…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Aşağı kaydır"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Yukarı kaydır"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Geri"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Ara"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Ayarlar"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Taşma"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Tamam"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"İptal"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Açık"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Kapalı"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Kapat"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Sürüş sırasında ekran kaydırma işlevi sınırlandırılmıştır"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Sürüş sırasında bu özellik kullanılamaz"</string>
-</resources>
diff --git a/car-ui-lib/res/values-uk/strings.xml b/car-ui-lib/res/values-uk/strings.xml
deleted file mode 100644
index 4188f47..0000000
--- a/car-ui-lib/res/values-uk/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Пошук…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Прокрутити вниз"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Прокрутити вгору"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Назад"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Пошук"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Налаштування"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Додаткове меню"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Скасувати"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Увімкнено"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Вимкнено"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Закрити"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Прокручування обмежено під час водіння"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Функція недоступна під час руху автомобіля"</string>
-</resources>
diff --git a/car-ui-lib/res/values-ur/strings.xml b/car-ui-lib/res/values-ur/strings.xml
deleted file mode 100644
index feecf75..0000000
--- a/car-ui-lib/res/values-ur/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"تلاش کریں…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"نیچے اسکرول کریں"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"اوپر اسکرول کریں"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"پیچھے"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"تلاش کریں"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"ترتیبات"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"اوورفلو"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"ٹھیک ہے"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"منسوخ کریں"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"آن ہے"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"آف ہے"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"بند کریں"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"ڈرائیونگ کے دوران اسکرولنگ محدود ہے"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"ڈرائیونگ کے دوران یہ خصوصیت دستیاب نہیں ہے"</string>
-</resources>
diff --git a/car-ui-lib/res/values-uz/strings.xml b/car-ui-lib/res/values-uz/strings.xml
deleted file mode 100644
index 2cda4e9..0000000
--- a/car-ui-lib/res/values-uz/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Qidirish…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Pastga surish"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Tepaga surish"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Orqaga"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Qidiruv"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Sozlamalar"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Kengaytirilgan"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"OK"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Bekor qilish"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Yoniq"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Yoqilmagan"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Yopish"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Avtomobilda harakatlanayotganda aylantirish funksiyasi cheklangan"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Avtomobilda harakatlanayotganda bu funksiya ishlamaydi"</string>
-</resources>
diff --git a/car-ui-lib/res/values-vi/strings.xml b/car-ui-lib/res/values-vi/strings.xml
deleted file mode 100644
index 2950aac..0000000
--- a/car-ui-lib/res/values-vi/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Tìm kiếm…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Cuộn xuống"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Cuộn lên"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Quay lại"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Tìm kiếm"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Cài đặt"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Trình đơn mục bổ sung"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Ok"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Hủy"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Đang bật"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Đang tắt"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Đóng"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Tính năng cuộn bị hạn chế khi đang lái xe"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Bạn không sử dụng được tính năng này khi đang lái xe"</string>
-</resources>
diff --git a/car-ui-lib/res/values-zh-rCN/strings.xml b/car-ui-lib/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 883d637..0000000
--- a/car-ui-lib/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"搜索…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"向下滚动"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"向上滚动"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"返回"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"搜索"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"设置"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"溢出菜单"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"确定"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"取消"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"开启"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"关闭"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"关闭"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"驾车时滚动操作受限"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"驾车时无法使用此功能"</string>
-</resources>
diff --git a/car-ui-lib/res/values-zh-rHK/strings.xml b/car-ui-lib/res/values-zh-rHK/strings.xml
deleted file mode 100644
index f215fa5..0000000
--- a/car-ui-lib/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"搜尋…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"向下捲動"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"向上捲動"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"返回"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"搜尋"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"設定"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"展開式選單"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"確定"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"取消"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"已開啟"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"已關閉"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"關閉"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"捲動功能在駕駛時受限制"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"無法在駕駛時使用此功能"</string>
-</resources>
diff --git a/car-ui-lib/res/values-zh-rTW/strings.xml b/car-ui-lib/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 20fb010..0000000
--- a/car-ui-lib/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"搜尋…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"向下捲動"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"向上捲動"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"返回"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"搜尋"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"設定"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"溢位"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"確定"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"取消"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"開啟"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"關閉"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"關閉"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"系統會限制開車時的捲動操作"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"開車時無法使用這項功能"</string>
-</resources>
diff --git a/car-ui-lib/res/values-zu/strings.xml b/car-ui-lib/res/values-zu/strings.xml
deleted file mode 100644
index 15aefff..0000000
--- a/car-ui-lib/res/values-zu/strings.xml
+++ /dev/null
@@ -1,33 +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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_ui_toolbar_default_search_hint" msgid="7807151740020494659">"Sesha…"</string>
-    <string name="car_ui_scrollbar_page_down_button" msgid="2419547312871553905">"Skrolela phansi"</string>
-    <string name="car_ui_scrollbar_page_up_button" msgid="4152120100101092092">"Skrolela phezulu"</string>
-    <string name="car_ui_toolbar_nav_icon_content_description" msgid="2689756063478650269">"Emuva"</string>
-    <string name="car_ui_toolbar_menu_item_search_title" msgid="8705757227447034030">"Sesha"</string>
-    <string name="car_ui_toolbar_menu_item_settings_title" msgid="6694060516340354337">"Izilungiselelo"</string>
-    <string name="car_ui_toolbar_menu_item_overflow_title" msgid="771643815366812499">"Ukuphuphuma"</string>
-    <string name="car_ui_dialog_preference_positive" msgid="1918267574135176336">"Kulungile"</string>
-    <string name="car_ui_dialog_preference_negative" msgid="4156315694902086271">"Khansela"</string>
-    <string name="car_ui_preference_switch_on" msgid="5512335363135043642">"Vuliwe"</string>
-    <string name="car_ui_preference_switch_off" msgid="4393435896926380920">"Valiwe"</string>
-    <string name="car_ui_alert_dialog_default_button" msgid="1775326289021319685">"Vala"</string>
-    <string name="car_ui_scrolling_limited_message" msgid="1036509082539078267">"Ukuskrola kukhawulelwe uma ushayela"</string>
-    <string name="car_ui_restricted_while_driving" msgid="8401317496175957541">"Isici asitholakali ngenkathi ushayela"</string>
-</resources>
diff --git a/car-ui-lib/res/values/attrs.xml b/car-ui-lib/res/values/attrs.xml
deleted file mode 100644
index 5698d25..0000000
--- a/car-ui-lib/res/values/attrs.xml
+++ /dev/null
@@ -1,142 +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>
-    <!-- Global theme options for CarUi -->
-    <declare-styleable name="CarUi">
-        <!-- When set to true, the window decor will contain an OEM-customizable layout -->
-        <attr name="carUiBaseLayout" format="boolean"/>
-        <!-- When set to true, a CarUi Toolbar will be provided in the window decor -->
-        <attr name="carUiToolbar" format="boolean"/>
-    </declare-styleable>
-
-    <declare-styleable name="CarUiToolbar">
-        <!-- Title of the toolbar, only displayed in certain conditions -->
-        <attr name="title" format="string"/>
-        <!-- Logo drawable for the toolbar. Appears when there's no back/close button shown -->
-        <attr name="logo" format="reference"/>
-        <!-- Hint for the search bar in the toolbar -->
-        <attr name="searchHint" format="string"/>
-        <!-- Whether or not to show the MenuItems while searching. Default false. -->
-        <attr name="showMenuItemsWhileSearching" format="boolean"/>
-        <!-- Initial state of the toolbar. See the Toolbar.State enum for more information -->
-        <attr name="state" format="enum">
-            <enum name="home" value="0"/>
-            <enum name="subpage" value="1"/>
-            <enum name="search" value="2"/>
-        </attr>
-        <!-- Whether or not the toolbar should have a background. Default true. -->
-        <attr name="showBackground" format="boolean"/>
-        <!-- Mode of the navigation button See the Toolbar.NavButtonMode enum for more information -->
-        <attr name="navButtonMode" format="enum">
-            <enum name="back" value="0"/>
-            <enum name="close" value="1"/>
-            <enum name="down" value="2"/>
-        </attr>
-        <!-- XML resource of MenuItems. See Toolbar.setMenuItems(int) for more information. -->
-        <attr name="menuItems" format="reference"/>
-        <!-- Whether or not to show tabs in the SUBPAGE state. Default false -->
-        <attr name="showTabsInSubpage" format="boolean"/>
-    </declare-styleable>
-
-    <declare-styleable name="CarUiToolbarMenuItem">
-        <!-- Id of MenuItem, used to differentiate them -->
-        <attr name="id" format="reference"/>
-        <!-- Show/hide the MenuItem -->
-        <attr name="visible" format="boolean"/>
-        <!-- Set this to true to make a search MenuItem. This will override every other property except id, visible, and onclick. -->
-        <attr name="search" format="boolean"/>
-        <!-- Set this to true to make a settings MenuItem. This will override every other property except id, visible, and onclick. -->
-        <attr name="settings" format="boolean"/>
-        <!-- Title -->
-        <attr name="title"/>
-        <!-- Icon -->
-        <attr name="icon" format="reference"/>
-        <!-- True to tint the icon to a consistent color. Default true, all the other booleans default to false -->
-        <attr name="tinted" format="boolean"/>
-        <!-- Show both the icon and title at the same time -->
-        <attr name="showIconAndTitle" format="boolean"/>
-        <!-- True if this MenuItem should be a switch -->
-        <attr name="checkable" format="boolean"/>
-        <!-- Whether the switch should be checked or not. Setting this implies checkable=true -->
-        <attr name="checked" format="boolean"/>
-        <!-- True if this MenuItem should be activatable, in which case it will visually toggle states when clicked -->
-        <attr name="activatable" format="boolean"/>
-        <!-- Whether the MenuItem starts activated. Setting this implies activatable=true -->
-        <attr name="activated" format="boolean"/>
-        <!-- How to display the MenuItem. "always" means always show it on the toolbar, "never" means never show it on the toolbar and instead show it in the overflow menu -->
-        <attr name="displayBehavior" format="enum">
-            <enum name="always" value="0"/>
-            <enum name="never" value="1"/>
-        </attr>
-        <!-- Ux restrictions required to interact with this MenuItem -->
-        <attr name="uxRestrictions">
-            <!-- Values are copied from android.car.drivingstate.CarUxRestrictions. Note:
-            UX_RESTRICTIONS_BASELINE is not allowed here because it's useless and confusing. -->
-            <flag name="UX_RESTRICTIONS_NO_DIALPAD" value="1"/>
-            <flag name="UX_RESTRICTIONS_NO_FILTERING" value="2"/>
-            <flag name="UX_RESTRICTIONS_LIMIT_STRING_LENGTH" value="4"/>
-            <flag name="UX_RESTRICTIONS_NO_KEYBOARD" value="8"/>
-            <flag name="UX_RESTRICTIONS_NO_VIDEO" value="16"/>
-            <flag name="UX_RESTRICTIONS_LIMIT_CONTENT" value="32"/>
-            <flag name="UX_RESTRICTIONS_NO_SETUP" value="64"/>
-            <flag name="UX_RESTRICTIONS_NO_TEXT_MESSAGE" value="128"/>
-            <flag name="UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION" value="256"/>
-            <flag name="UX_RESTRICTIONS_FULLY_RESTRICTED" value="511"/>
-        </attr>
-        <!-- The name of a method that takes a MenuItem as an argument in you'r toolbar's Activity. Will be called when the MenuItem is clicked -->
-        <attr name="onClick" format="string"/>
-    </declare-styleable>
-
-    <!-- Theme attribute to specifying a default style for all CarUiToolbars -->
-    <attr name="CarUiToolbarStyle" format="reference"/>
-
-    <declare-styleable name="CarUiRecyclerView">
-        <!-- Whether to enable the dividers or not. Linear and grid layout uses
-        car_ui_recyclerview_divider.xml and car_ui_divider.xml drawables
-        respectively for styling dividers. -->
-        <attr name="enableDivider" format="boolean" />
-        <!-- Top offset for car ui recycler view. -->
-        <attr name="topOffset" format="integer" />
-        <!-- Bottom offset for car ui recycler view for linear layout. -->
-        <attr name="bottomOffset" format="integer" />
-
-        <!-- Number of columns in a grid layout. -->
-        <attr name="numOfColumns" format="integer" />
-
-        <!-- car ui recycler view layout. -->
-        <attr name="layoutStyle" format="enum">
-            <!-- linear layout -->
-            <enum name="linear" value="0" />
-            <!-- grid layout -->
-            <enum name="grid" value="1" />
-        </attr>
-    </declare-styleable>
-
-    <declare-styleable name="CarUiPreference">
-        <!-- Toggle for showing chevron -->
-        <attr name="showChevron" format="boolean" />
-        <!-- Show ripple when disabled preference is clicked -->
-        <attr name="showRippleOnDisabledPreference" format="boolean" />
-    </declare-styleable>
-
-    <!-- Theme attribute to specify a default style for all CarUiPreferences -->
-    <attr name="carUiPreferenceStyle" format="reference" />
-
-    <!-- Theme attribute to specify a default style for all CarUiRecyclerViews -->
-    <attr name="carUiRecyclerViewStyle" format="reference" />
-
-    <attr name="state_ux_restricted" format="boolean" />
-</resources>
diff --git a/car-ui-lib/res/values/bools.xml b/car-ui-lib/res/values/bools.xml
deleted file mode 100644
index 955956d..0000000
--- a/car-ui-lib/res/values/bools.xml
+++ /dev/null
@@ -1,49 +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>
-    <!-- Toolbar -->
-
-    <!-- Whether tabs should use flex layout or not -->
-    <bool name="car_ui_toolbar_tab_flexible_layout">false</bool>
-    <!-- Whether the space for nav icon should be reserved, even if the nav icon is not visible -->
-    <bool name="car_ui_toolbar_nav_icon_reserve_space">true</bool>
-    <!-- Whether the logo (if provided) should be used in place of the nav icon when nav icon is
-         not visible -->
-    <bool name="car_ui_toolbar_logo_fills_nav_icon_space">true</bool>
-    <!-- Whether logo should be displayed. If set to false, logo won't be shown even if provided -->
-    <bool name="car_ui_toolbar_show_logo">true</bool>
-    <!-- Whether tabs should be displayed on a second row, or they should be placed in the first
-         row, replacing the title -->
-    <bool name="car_ui_toolbar_tabs_on_second_row">false</bool>
-
-    <!-- CarUiRecyclerView -->
-
-    <!-- Whether to display the Scroll Bar or not. Defaults to true. If this is set to false,
-         the CarUiRecyclerView will behave exactly like the RecyclerView. -->
-    <bool name="car_ui_scrollbar_enable">true</bool>
-
-    <!-- Preferences -->
-
-    <!-- Whether list, edit, dropdown and intent preferences should show a chevron or not -->
-    <bool name="car_ui_preference_show_chevron">false</bool>
-    <!-- whether list preference should be shown in full screen or as a dialog -->
-    <bool name="car_ui_preference_list_show_full_screen">true</bool>
-
-    <!-- List items -->
-
-    <bool name="car_ui_list_item_single_line_title">true</bool>
-</resources>
diff --git a/car-ui-lib/res/values/colors.xml b/car-ui-lib/res/values/colors.xml
deleted file mode 100644
index 78d1ecc..0000000
--- a/car-ui-lib/res/values/colors.xml
+++ /dev/null
@@ -1,55 +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>
-    <!-- General -->
-
-    <!-- Background color to use on full screen activities -->
-    <color name="car_ui_activity_background_color">#000000</color>
-    <!-- The ripple color. -->
-    <color name="car_ui_ripple_color">#27ffffff</color>
-
-    <!-- Toolbar -->
-
-    <!-- Color used on the navigation icon -->
-    <color name="car_ui_toolbar_nav_icon_color">@color/car_ui_text_color_primary</color>
-    <!-- Text color applied to the hint displayed inside the search box -->
-    <color name="car_ui_toolbar_search_hint_text_color">@color/car_ui_text_color_hint</color>
-    <!-- Tab selected color -->
-    <color name="car_ui_toolbar_tab_selected_color">@color/car_ui_text_color_primary</color>
-    <!-- Tab normal color -->
-    <color name="car_ui_toolbar_tab_unselected_color">@color/car_ui_text_color_secondary</color>
-
-    <!-- Recycler View  -->
-
-    <!-- Color of the scroll bar indicator in the CarUiRecyclerView. -->
-    <color name="car_ui_scrollbar_thumb">#99ffffff</color>
-    <!-- Color of the divider views between CarUiRecyclerView items -->
-    <color name="car_ui_recyclerview_divider_color">@android:color/transparent</color>
-
-    <!-- Preferences -->
-
-    <color name="car_ui_preference_category_title_text_color">@color/car_ui_color_accent</color>
-    <color name="car_ui_preference_summary_text_color">@color/car_ui_text_color_secondary</color>
-    <color name="car_ui_preference_title_text_color">@color/car_ui_text_color_primary</color>
-    <color name="car_ui_preference_edit_text_dialog_message_text_color">@color/car_ui_text_color_primary</color>
-    <color name="car_ui_preference_icon_color">@color/car_ui_text_color_primary</color>
-    <color name="car_ui_preference_switch_track_text_color">@color/car_ui_text_color_primary</color>
-
-    <!-- List item -->
-    <color name="car_ui_list_item_header_text_color">@color/car_ui_color_accent</color>
-    <color name="car_ui_list_item_title_text_color">@color/car_ui_text_color_primary</color>
-    <color name="car_ui_list_item_body_text_color">@color/car_ui_text_color_secondary</color>
-</resources>
diff --git a/car-ui-lib/res/values/dimens.xml b/car-ui-lib/res/values/dimens.xml
deleted file mode 100644
index 95a15ff..0000000
--- a/car-ui-lib/res/values/dimens.xml
+++ /dev/null
@@ -1,221 +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>
-    <!-- General resources -->
-
-    <dimen name="car_ui_touch_target_width">76dp</dimen>
-    <dimen name="car_ui_touch_target_height">76dp</dimen>
-    <dimen name="car_ui_primary_icon_size">44dp</dimen>
-    <item name="car_ui_letter_spacing_body1" format="float" type="dimen">0.0</item>
-    <item name="car_ui_letter_spacing_body3" format="float" type="dimen">0.0</item>
-
-    <!-- Horizontal margin between screen content and display border. In reference
-     implementation, this value matches the CarUiRecyclerView scrollbar width -->
-    <dimen name="car_ui_margin">112dp</dimen>
-
-    <!-- Paddings -->
-    <dimen name="car_ui_padding_0">4dp</dimen>
-    <dimen name="car_ui_padding_1">8dp</dimen>
-    <dimen name="car_ui_padding_2">16dp</dimen>
-    <dimen name="car_ui_padding_3">24dp</dimen>
-    <dimen name="car_ui_padding_4">32dp</dimen>
-    <dimen name="car_ui_padding_5">64dp</dimen>
-    <dimen name="car_ui_padding_6">96dp</dimen>
-
-    <!-- Type Sizings -->
-    <dimen name="car_ui_body1_size">32sp</dimen>
-    <dimen name="car_ui_body2_size">28sp</dimen>
-    <dimen name="car_ui_body3_size">24sp</dimen>
-    <dimen name="car_ui_sub1_size">22sp</dimen>
-    <dimen name="car_ui_sub2_size">20sp</dimen>
-    <dimen name="car_ui_sub3_size">18sp</dimen>
-
-    <!-- Tabs -->
-
-    <!-- Exact size of the tab textbox. Use @dimen/wrap_content if this must be flexible -->
-    <dimen name="car_ui_toolbar_tab_text_width">135dp</dimen>
-    <!-- Horizontal padding between tabs -->
-    <dimen name="car_ui_toolbar_tab_padding_x">12dp</dimen>
-    <!-- Tab icon width (if icons are enabled) -->
-    <dimen name="car_ui_toolbar_tab_icon_width">36dp</dimen>
-    <!-- Tab icon height (if icons are enabled) -->
-    <dimen name="car_ui_toolbar_tab_icon_height">36dp</dimen>
-
-    <!-- Toolbar -->
-
-    <!-- Default height for both toolbar rows. See car_ui_toolbar_first_row_height and
-     car_ui_toolbar_second_row_height -->
-    <dimen name="car_ui_toolbar_row_height">96dp</dimen>
-    <!-- Height of the top toolbar row. This can be customized independently. -->
-    <dimen name="car_ui_toolbar_first_row_height">@dimen/car_ui_toolbar_row_height</dimen>
-    <!-- Height of the bottom toolbar row (if the toolbar is used in two-rows mode. -->
-    <dimen name="car_ui_toolbar_second_row_height">@dimen/car_ui_toolbar_row_height</dimen>
-    <!-- Padding on the toolbar start (e.g.: distance between the container start and the start of
-    nav icon or logo) -->
-    <dimen name="car_ui_toolbar_start_inset">0dp</dimen>
-    <!-- End padding (e.g.: distance between the container end and the end of the menu items) -->
-    <dimen name="car_ui_toolbar_end_inset">0dp</dimen>
-    <!-- Top padding -->
-    <dimen name="car_ui_toolbar_top_inset">0dp</dimen>
-    <!-- Bottom padding -->
-    <dimen name="car_ui_toolbar_bottom_inset">0dp</dimen>
-    <!-- Toolbar title/tabs start margin. Toolbar navigation icon (or logo if no navigation icon is
-    used) will be centered in this space, and the title will start from here -->
-    <dimen name="car_ui_toolbar_margin">@dimen/car_ui_margin</dimen>
-    <!-- Navigation icon -->
-    <dimen name="car_ui_toolbar_nav_icon_size">@dimen/car_ui_primary_icon_size</dimen>
-    <!-- Logo -->
-    <dimen name="car_ui_toolbar_logo_size">@dimen/car_ui_primary_icon_size</dimen>
-    <!-- Margin between the logo and the title, when both logo and navigation icons are used -->
-    <dimen name="car_ui_toolbar_title_logo_padding">0dp</dimen>
-    <!-- Margin at the start of the title -->
-    <dimen name="car_ui_toolbar_title_margin_start">@dimen/car_ui_padding_2</dimen>
-    <!-- Margin at the start of the title when there is no logo present -->
-    <dimen name="car_ui_toolbar_title_no_logo_margin_start">0dp</dimen>
-    <!-- Space at the end and in between menu items -->
-    <dimen name="car_ui_toolbar_menu_item_margin">@dimen/car_ui_padding_2</dimen>
-    <!-- Ripple effect radius for icon menu items -->
-    <dimen name="car_ui_toolbar_menu_item_icon_ripple_radius">48dp</dimen>
-    <!-- Icon size for icon menu items -->
-    <dimen name="car_ui_toolbar_menu_item_icon_size">@dimen/car_ui_primary_icon_size</dimen>
-    <!-- Icon background size for icon menu items -->
-    <dimen name="car_ui_toolbar_menu_item_icon_background_size">54dp</dimen>
-    <!-- Height of the decoration view between the two rows of the toolbar (or below the toolbar
-    if this is a single row one -->
-    <!-- can't use 0dp for layout_height or the constraintlayout effect kicks in -->
-    <dimen name="car_ui_toolbar_separator_height">0.1dp</dimen>
-    <!-- Height of the decoration view below the toolbar -->
-    <!-- can't use 0dp for layout_height or the constraintlayout effect kicks in -->
-    <dimen name="car_ui_toolbar_bottom_view_height">0.1dp</dimen>
-    <!-- Height of the search box -->
-    <dimen name="car_ui_toolbar_search_height">0dp</dimen>
-    <!-- Space before the text search area, where the search icon is located -->
-    <dimen name="car_ui_toolbar_search_search_icon_container_width">@dimen/car_ui_touch_target_width</dimen>
-    <!-- Space after the text search area, where the cancel icon is located -->
-    <dimen name="car_ui_toolbar_search_close_icon_container_width">@dimen/car_ui_touch_target_width</dimen>
-    <!-- Size of the search icon inside the search box -->
-    <dimen name="car_ui_toolbar_search_search_icon_size">@dimen/car_ui_primary_icon_size</dimen>
-    <!-- Size of the close icon inside the search box -->
-    <dimen name="car_ui_toolbar_search_close_icon_size">@dimen/car_ui_primary_icon_size</dimen>
-
-    <!-- Internal artifacts. Do not overlay -->
-    <item name="wrap_content" format="integer" type="dimen">-2</item>
-
-    <!-- CarUiRecyclerView -->
-
-    <dimen name="car_ui_recyclerview_divider_height">0dp</dimen>
-    <dimen name="car_ui_recyclerview_divider_start_margin">0dp</dimen>
-    <dimen name="car_ui_recyclerview_divider_end_margin">0dp</dimen>
-    <dimen name="car_ui_recyclerview_divider_top_margin">0dp</dimen>
-    <dimen name="car_ui_recyclerview_divider_bottom_margin">0dp</dimen>
-
-    <!-- CarUiRecyclerView default scrollbar -->
-
-    <dimen name="car_ui_scrollbar_container_width">@dimen/car_ui_margin</dimen>
-    <dimen name="car_ui_scrollbar_button_size">@dimen/car_ui_touch_target_width</dimen>
-    <dimen name="car_ui_scrollbar_thumb_width">7dp</dimen>
-    <dimen name="car_ui_scrollbar_min_thumb_height">56dp</dimen>
-    <dimen name="car_ui_scrollbar_separator_margin">16dp</dimen>
-    <dimen name="car_ui_scrollbar_margin">@dimen/car_ui_margin</dimen>
-    <dimen name="car_ui_scrollbar_thumb_radius">100dp</dimen>
-
-    <item name="car_ui_button_disabled_alpha" format="float" type="dimen">0.2</item>
-    <item name="car_ui_scrollbar_milliseconds_per_inch" format="float" type="dimen">150.0</item>
-    <item name="car_ui_scrollbar_deceleration_times_divisor" format="float" type="dimen">0.45</item>
-    <item name="car_ui_scrollbar_decelerate_interpolator_factor" format="float" type="dimen">1.8</item>
-
-    <dimen name="car_ui_scrollbar_padding_top">0dp</dimen>
-    <dimen name="car_ui_scrollbar_padding_bottom">0dp</dimen>
-
-    <!-- Preferences -->
-
-    <dimen name="car_ui_preference_category_text_size">24sp</dimen>
-    <dimen name="car_ui_preference_summary_text_size">24sp</dimen>
-    <dimen name="car_ui_preference_title_text_size">32sp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_message_text_size">24sp</dimen>
-
-    <dimen name="car_ui_preference_content_margin_top">16dp</dimen>
-    <dimen name="car_ui_preference_content_margin_bottom">16dp</dimen>
-    <dimen name="car_ui_preference_icon_size">44dp</dimen>
-    <dimen name="car_ui_preference_icon_margin_end">16dp</dimen>
-
-    <dimen name="car_ui_preference_category_min_height">76dp</dimen>
-    <dimen name="car_ui_preference_category_icon_size">44dp</dimen>
-    <dimen name="car_ui_preference_category_icon_margin_end">16dp</dimen>
-
-    <dimen name="car_ui_preference_dropdown_padding_start">112dp</dimen>
-
-    <dimen name="car_ui_preference_edit_text_dialog_margin_top">32dp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_margin_bottom">32dp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_message_margin_bottom">32dp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_message_margin_start">24dp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_message_margin_end">24dp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_text_margin_start">24dp</dimen>
-    <dimen name="car_ui_preference_edit_text_dialog_text_margin_end">24dp</dimen>
-
-    <dimen name="car_ui_preference_switch_text_size">30sp</dimen>
-    <dimen name="car_ui_preference_switch_width">288dp</dimen>
-    <dimen name="car_ui_preference_switch_width_half">144dp</dimen>
-    <dimen name="car_ui_preference_switch_height">101dp</dimen>
-
-    <!-- Alert dialog   -->
-
-    <dimen name="car_ui_dialog_edittext_height">50dp</dimen>
-    <dimen name="car_ui_dialog_edittext_margin_top">10dp</dimen>
-    <dimen name="car_ui_dialog_edittext_margin_bottom">10dp</dimen>
-    <dimen name="car_ui_dialog_edittext_margin_start">22dp</dimen>
-    <dimen name="car_ui_dialog_edittext_margin_end">22dp</dimen>
-    <dimen name="car_ui_dialog_icon_size">56dp</dimen>
-    <dimen name="car_ui_dialog_title_margin">24dp</dimen>
-
-    <!-- List item  -->
-
-    <dimen name="car_ui_list_item_header_text_size">24sp</dimen>
-    <dimen name="car_ui_list_item_title_text_size">32sp</dimen>
-    <dimen name="car_ui_list_item_body_text_size">24sp</dimen>
-    <dimen name="car_ui_list_item_height">116dp</dimen>
-    <dimen name="car_ui_list_item_header_height">76dp</dimen>
-    <dimen name="car_ui_list_item_header_start_inset">0dp</dimen>
-    <dimen name="car_ui_list_item_start_inset">0dp</dimen>
-    <dimen name="car_ui_list_item_end_inset">0dp</dimen>
-    <dimen name="car_ui_header_list_item_text_start_margin">0dp</dimen>
-    <dimen name="car_ui_list_item_text_start_margin">24dp</dimen>
-    <dimen name="car_ui_list_item_text_no_icon_start_margin">24dp</dimen>
-
-    <!-- List item icons  -->
-
-    <dimen name="car_ui_list_item_icon_size">@dimen/car_ui_primary_icon_size</dimen>
-    <dimen name="car_ui_list_item_content_icon_width">@dimen/car_ui_list_item_icon_container_width</dimen>
-    <dimen name="car_ui_list_item_content_icon_height">@dimen/car_ui_list_item_icon_container_width</dimen>
-    <dimen name="car_ui_list_item_avatar_icon_width">@dimen/car_ui_primary_icon_size</dimen>
-    <dimen name="car_ui_list_item_avatar_icon_height">@dimen/car_ui_primary_icon_size</dimen>
-    <dimen name="car_ui_list_item_supplemental_icon_size">@dimen/car_ui_primary_icon_size</dimen>
-    <dimen name="car_ui_list_item_icon_container_width">112dp</dimen>
-    <dimen name="car_ui_list_item_action_divider_width">1dp</dimen>
-    <dimen name="car_ui_list_item_action_divider_height">60dp</dimen>
-
-    <!-- List item actions  -->
-
-    <dimen name="car_ui_list_item_radio_button_height">@dimen/car_ui_list_item_height</dimen>
-    <dimen name="car_ui_list_item_radio_button_start_inset">@dimen/car_ui_list_item_start_inset</dimen>
-    <dimen name="car_ui_list_item_radio_button_end_inset">@dimen/car_ui_list_item_end_inset</dimen>
-    <dimen name="car_ui_list_item_radio_button_icon_container_width">@dimen/car_ui_list_item_icon_container_width</dimen>
-    <dimen name="car_ui_list_item_check_box_height">@dimen/car_ui_list_item_height</dimen>
-    <dimen name="car_ui_list_item_check_box_start_inset">@dimen/car_ui_list_item_start_inset</dimen>
-    <dimen name="car_ui_list_item_check_box_end_inset">@dimen/car_ui_list_item_end_inset</dimen>
-    <dimen name="car_ui_list_item_check_box_icon_container_width">@dimen/car_ui_list_item_icon_container_width</dimen>
-
-</resources>
diff --git a/car-ui-lib/res/values/ids.xml b/car-ui-lib/res/values/ids.xml
deleted file mode 100644
index fcff109..0000000
--- a/car-ui-lib/res/values/ids.xml
+++ /dev/null
@@ -1,19 +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>
-    <!-- Id used for the search button when using Toolbar.createSearch() method -->
-    <item name="search" type="id"/>
-</resources>
\ No newline at end of file
diff --git a/car-ui-lib/res/values/integers.xml b/car-ui-lib/res/values/integers.xml
deleted file mode 100644
index 1ffe098..0000000
--- a/car-ui-lib/res/values/integers.xml
+++ /dev/null
@@ -1,22 +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>
-    <!-- Default max string length -->
-    <integer name="car_ui_default_max_string_length">120</integer>
-    <integer name="car_ui_scrollbar_longpress_initial_delay">1000</integer>
-    <integer name="car_ui_scrollbar_longpress_repeat_interval">100</integer>
-</resources>
diff --git a/car-ui-lib/res/values/strings.xml b/car-ui-lib/res/values/strings.xml
deleted file mode 100644
index 627c542..0000000
--- a/car-ui-lib/res/values/strings.xml
+++ /dev/null
@@ -1,63 +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>
-    <!--
-    Configuration for a default scrollbar for the CarUiRecyclerView. This component must inherit
-    abstract class ScrollBar. If the ScrollBar is enabled, the component will be initialized from
-    CarUiRecyclerView#createScrollBarFromConfig(). If no component is provided,
-    {@link DefaultScrollbar} class will be used.
-    -->
-    <string name="car_ui_scrollbar_component" translatable="false"/>
-    <!-- Search hint, displayed inside the search box [CHAR LIMIT=50] -->
-    <string name="car_ui_toolbar_default_search_hint">Search&#8230;</string>
-    <!-- CarUxRestrictions Utility -->
-    <string name="car_ui_ellipsis" translatable="false">&#8230;</string>
-    <!-- Content description for car ui recycler view scroll bar down arrow [CHAR LIMIT=30] -->
-    <string name="car_ui_scrollbar_page_down_button">Scroll down</string>
-    <!-- Content description for car ui recycler view scroll bar up arrow [CHAR LIMIT=30] -->
-    <string name="car_ui_scrollbar_page_up_button">Scroll up</string>
-    <!-- The content description on the toolbar back button -->
-    <string name="car_ui_toolbar_nav_icon_content_description">Back</string>
-    <!-- Title of the search menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
-    <string name="car_ui_toolbar_menu_item_search_title">Search</string>
-    <!-- Title of the settings menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
-    <string name="car_ui_toolbar_menu_item_settings_title">Settings</string>
-    <!-- Title of the overflow menu item. Only used for content descriptions. [CHAR_LIMIT=50] -->
-    <string name="car_ui_toolbar_menu_item_overflow_title">Overflow</string>
-
-    <!-- Positive option for a preference dialog. [CHAR_LIMIT=30] -->
-    <string name="car_ui_dialog_preference_positive">Ok</string>
-    <!-- Negative option for a preference dialog. [CHAR_LIMIT=30] -->
-    <string name="car_ui_dialog_preference_negative">Cancel</string>
-    <!-- Text to show when a preference switch is on. [CHAR_LIMIT=30] -->
-    <string name="car_ui_preference_switch_on">On</string>
-    <!-- Text to show when a preference switch is off. [CHAR_LIMIT=30] -->
-    <string name="car_ui_preference_switch_off">Off</string>
-    <!-- Font family to use for preference category titles. [CHAR_LIMIT=NONE] -->
-    <string name="car_ui_preference_category_title_font_family" translatable="false">sans-serif-medium</string>
-
-    <!-- Font family to use for list item headers. [CHAR_LIMIT=NONE] -->
-    <string name="car_ui_list_item_header_font_family" translatable="false">sans-serif-medium</string>
-
-    <!-- Text to show when no button is provided and a default button is used. -->
-    <string name="car_ui_alert_dialog_default_button">Close</string>
-
-    <!-- Shown at the bottom of a content limited list when user has scrolled past the limit while driving -->
-    <string name="car_ui_scrolling_limited_message">Scrolling limited while driving</string>
-
-    <!-- Shown in a toast when the user attempts to do something distracting while driving [CHAR_LIMIT=200] -->
-    <string name="car_ui_restricted_while_driving">Feature not available while driving</string>
-</resources>
diff --git a/car-ui-lib/res/values/styles.xml b/car-ui-lib/res/values/styles.xml
deleted file mode 100644
index 77dd80c..0000000
--- a/car-ui-lib/res/values/styles.xml
+++ /dev/null
@@ -1,329 +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 xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <!-- Styles for CarUi tab view -->
-
-    <style name="Widget.CarUi" parent="android:Widget.DeviceDefault"/>
-
-    <style name="Widget.CarUi.Button.Borderless.Colored"
-           parent="android:Widget.DeviceDefault.Button.Borderless.Colored"/>
-
-    <style name="Widget.CarUi.Button" parent="android:Widget.DeviceDefault.Button"/>
-
-    <style name="Widget.CarUi.Toolbar"/>
-
-    <style name="Widget.CarUi.SeekbarPreference"/>
-
-    <style name="Widget.CarUi.Toolbar.Container"/>
-
-    <style name="Widget.CarUi.Toolbar.NavIconContainer"/>
-
-    <style name="Widget.CarUi.Toolbar.Logo"/>
-
-    <style name="Widget.CarUi.Toolbar.LogoContainer">
-        <item name="android:paddingEnd">@dimen/car_ui_toolbar_title_logo_padding</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.ProgressBar"
-           parent="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal">
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.NavIcon">
-        <item name="android:tint">@color/car_ui_toolbar_nav_icon_color</item>
-        <item name="android:src">@drawable/car_ui_icon_arrow_back</item>
-        <item name="android:background">@drawable/car_ui_toolbar_menu_item_icon_ripple</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.Title">
-        <item name="android:textAppearance">@style/TextAppearance.CarUi.Widget.Toolbar.Title</item>
-        <item name="android:textAlignment">viewStart</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.Subtitle">
-        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
-        <item name="android:textAlignment">viewStart</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.TextButton" parent="Widget.CarUi.Button.Borderless.Colored">
-        <item name="android:drawableTint">@color/car_ui_toolbar_menu_item_icon_color</item>
-        <item name="android:drawablePadding">10dp</item>
-        <item name="android:maxWidth">350dp</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.TextButton.WithIcon">
-        <item name="android:textColor">@color/car_ui_toolbar_menu_item_icon_color</item>
-    </style>
-
-    <!-- Style applied to the seekbar widget within the seekbar preference -->
-    <style name="Widget.CarUi.SeekbarPreference.Seekbar">
-        <item name="android:background">@null</item>
-        <item name="android:clickable">false</item>
-        <item name="android:focusable">false</item>
-    </style>
-
-    <!-- Style applied to the decoration view between toolbar rows -->
-    <style name="Widget.CarUi.Toolbar.SeparatorView">
-        <item name="android:height">0.01dp</item>
-        <item name="android:background">@android:color/transparent</item>
-    </style>
-
-    <!-- Style applied to the decoration view below the toolbar -->
-    <style name="Widget.CarUi.Toolbar.BottomView">
-        <item name="android:height">0.01dp</item>
-        <item name="android:background">@android:color/transparent</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.MenuItem"/>
-
-    <style name="Widget.CarUi.Toolbar.MenuItem.Container">
-        <item name="android:divider">@drawable/car_ui_toolbar_menu_item_divider</item>
-        <item name="android:showDividers">beginning|middle|end</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.MenuItem.IndividualContainer">
-        <item name="android:minHeight">@dimen/car_ui_touch_target_height</item>
-        <item name="android:minWidth">@dimen/car_ui_touch_target_width</item>
-        <item name="android:layout_gravity">center_vertical</item>
-    </style>
-
-    <!-- Style applied to the edit box inside the toolbar search area -->
-    <style name="Widget.CarUi.Toolbar.Search.EditText"
-        parent="android:Widget.DeviceDefault.EditText"/>
-
-    <style name="Widget.CarUi.Toolbar.Search.SearchIcon" parent="Widget.CarUi.Toolbar"/>
-
-    <style name="Widget.CarUi.Toolbar.Search.CloseIcon" parent="Widget.CarUi.Toolbar">
-        <item name="android:background">@drawable/car_ui_toolbar_menu_item_icon_ripple</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.Tab"/>
-
-    <style name="Widget.CarUi.Toolbar.Tab.Container">
-        <item name="android:orientation">vertical</item>
-        <item name="android:paddingStart">@dimen/car_ui_toolbar_tab_padding_x</item>
-        <item name="android:paddingEnd">@dimen/car_ui_toolbar_tab_padding_x</item>
-        <item name="android:gravity">center</item>
-        <item name="android:background">?android:attr/selectableItemBackground</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.Tab.Icon">
-        <item name="android:scaleType">fitCenter</item>
-        <item name="android:tint">@color/car_ui_toolbar_tab_item_selector</item>
-        <item name="android:tintMode">src_in</item>
-    </style>
-
-    <style name="Widget.CarUi.Toolbar.Tab.Text">
-        <item name="android:singleLine">true</item>
-        <item name="android:gravity">center</item>
-        <item name="android:textAppearance">@style/TextAppearance.CarUi.Widget.Toolbar.Tab</item>
-    </style>
-
-    <style name="Widget.CarUi.CarUiRecyclerView">
-        <item name="android:scrollbars">vertical</item>
-    </style>
-
-    <style name="Widget.CarUi.AlertDialog"/>
-
-    <style name="Widget.CarUi.AlertDialog.HeaderContainer">
-        <item name="android:orientation">horizontal</item>
-        <item name="android:gravity">center_vertical|start</item>
-        <item name="android:paddingTop">18dp</item>
-        <item name="android:paddingBottom">18dp</item>
-    </style>
-
-    <style name="Widget.CarUi.AlertDialog.TitleContainer">
-        <item name="android:layout_marginStart">@dimen/car_ui_dialog_title_margin</item>
-        <item name="android:layout_marginEnd">@dimen/car_ui_dialog_title_margin</item>
-        <item name="android:orientation">vertical</item>
-    </style>
-
-    <style name="Widget.CarUi.AlertDialog.Icon">
-        <item name="android:layout_marginStart">@dimen/car_ui_dialog_title_margin</item>
-        <item name="android:scaleType">fitCenter</item>
-    </style>
-
-    <!-- Preference Styles -->
-
-    <style name="Preference.CarUi">
-        <item name="allowDividerBelow">false</item>
-        <item name="allowDividerAbove">false</item>
-        <item name="android:layout">@layout/car_ui_preference</item>
-    </style>
-
-    <style name="Preference.CarUi.Category">
-        <item name="android:layout">@layout/car_ui_preference_category</item>
-        <!-- The title should not dim if the category is disabled, instead only the preference children should dim. -->
-        <item name="android:shouldDisableView">false</item>
-        <item name="android:selectable">false</item>
-    </style>
-
-    <style name="Preference.CarUi.CheckBoxPreference">
-        <item name="android:widgetLayout">@layout/car_ui_preference_widget_checkbox</item>
-    </style>
-
-    <style name="Preference.CarUi.DialogPreference">
-        <item name="android:positiveButtonText">@string/car_ui_dialog_preference_positive</item>
-        <item name="android:negativeButtonText">@string/car_ui_dialog_preference_negative</item>
-    </style>
-
-    <style name="Preference.CarUi.DialogPreference.EditTextPreference">
-        <item name="android:dialogLayout">@layout/car_ui_preference_dialog_edittext</item>
-    </style>
-
-    <style name="Preference.CarUi.DropDown">
-        <item name="android:layout">@layout/car_ui_preference_dropdown</item>
-    </style>
-
-    <style name="Preference.CarUi.Icon"/>
-
-    <style name="Preference.CarUi.Information">
-        <item name="android:enabled">false</item>
-        <item name="android:shouldDisableView">false</item>
-    </style>
-
-    <style name="Preference.CarUi.Preference"/>
-
-    <style name="Preference.CarUi.PreferenceScreen"/>
-
-    <style name="Preference.CarUi.SeekBarPreference">
-        <item name="android:layout">@layout/car_ui_preference_widget_seekbar</item>
-        <item name="adjustable">true</item>
-        <item name="showSeekBarValue">false</item>
-    </style>
-
-    <style name="Preference.CarUi.SwitchPreference">
-        <item name="android:widgetLayout">@layout/car_ui_preference_widget_switch</item>
-        <item name="android:switchTextOn">@string/car_ui_preference_switch_on</item>
-        <item name="android:switchTextOff">@string/car_ui_preference_switch_off</item>
-    </style>
-
-    <style name="PreferenceFragment.CarUi">
-        <item name="android:divider">?android:attr/listDivider</item>
-        <!-- TODO(b/150230923) change this to car_ui_preference_fragment -->
-        <item name="android:layout">@layout/car_ui_preference_fragment_with_toolbar</item>
-    </style>
-
-    <!-- TODO(b/150230923) remove this when other apps are ready -->
-    <style name="PreferenceFragment.CarUi.WithToolbar">
-        <item name="android:layout">@layout/car_ui_preference_fragment</item>
-    </style>
-
-    <style name="PreferenceFragmentList.CarUi">
-        <item name="android:paddingTop">0dp</item>
-        <item name="android:paddingBottom">0dp</item>
-        <item name="android:paddingLeft">0dp</item>
-        <item name="android:paddingStart">0dp</item>
-        <item name="android:paddingRight">0dp</item>
-        <item name="android:paddingEnd">0dp</item>
-    </style>
-
-    <!-- TextAppearance -->
-
-    <style name="TextAppearance.CarUi" parent="android:TextAppearance.DeviceDefault">
-        <item name="android:textColor">?android:attr/textColorPrimary</item>
-        <item name="android:textAlignment">viewStart</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Body1">
-        <item name="android:textSize">@dimen/car_ui_body1_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Body2">
-        <item name="android:textSize">@dimen/car_ui_body2_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Body3">
-        <item name="android:textSize">@dimen/car_ui_body3_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Sub1">
-        <item name="android:textSize">@dimen/car_ui_sub1_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Sub2">
-        <item name="android:textSize">@dimen/car_ui_sub2_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Sub3">
-        <item name="android:textSize">@dimen/car_ui_sub3_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.PreferenceCategoryTitle">
-        <item name="android:fontFamily">@string/car_ui_preference_category_title_font_family</item>
-        <item name="android:textColor">@color/car_ui_preference_category_title_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_category_text_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.PreferenceSummary">
-        <item name="android:textColor">@color/car_ui_preference_summary_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_summary_text_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.PreferenceTitle">
-        <item name="android:textColor">@color/car_ui_preference_title_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_title_text_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.PreferenceEditTextDialogMessage">
-        <item name="android:textColor">@color/car_ui_preference_edit_text_dialog_message_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_preference_edit_text_dialog_message_text_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.AlertDialog.Title" parent="TextAppearance.CarUi.Body3"/>
-    <style name="TextAppearance.CarUi.AlertDialog.Subtitle" parent="TextAppearance.CarUi.Sub3"/>
-
-    <style name="TextAppearance.CarUi.Widget" parent="android:TextAppearance.DeviceDefault.Widget">
-        <item name="android:textAlignment">viewStart</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Widget.Toolbar"/>
-
-    <style name="TextAppearance.CarUi.Widget.Toolbar.Title">
-        <item name="android:singleLine">true</item>
-        <item name="android:textSize">32sp</item>
-        <item name="android:letterSpacing">@dimen/car_ui_letter_spacing_body1</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Widget.Toolbar.Tab">
-        <item name="android:textSize">24sp</item>
-        <item name="android:letterSpacing">@dimen/car_ui_letter_spacing_body3</item>
-        <item name="android:textColor">@color/car_ui_toolbar_tab_item_selector</item>
-        <item name="android:textStyle">normal</item>
-        <item name="android:textFontWeight">400</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.Widget.Toolbar.Tab.Selected">
-        <item name="android:textFontWeight">500</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.ListItem.Header">
-        <item name="android:fontFamily">@string/car_ui_list_item_header_font_family</item>
-        <item name="android:textColor">@color/car_ui_list_item_header_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_list_item_header_text_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.ListItem">
-        <item name="android:textColor">@color/car_ui_list_item_title_text_color</item>
-        <item name="android:textSize">@dimen/car_ui_list_item_title_text_size</item>
-    </style>
-
-    <style name="TextAppearance.CarUi.ListItem.Body">
-        <item name="android:textSize">@dimen/car_ui_list_item_body_text_size</item>
-        <item name="android:textColor">@color/car_ui_list_item_body_text_color</item>
-    </style>
-
-</resources>
diff --git a/car-ui-lib/res/values/themes.xml b/car-ui-lib/res/values/themes.xml
deleted file mode 100644
index 34bbf3c..0000000
--- a/car-ui-lib/res/values/themes.xml
+++ /dev/null
@@ -1,242 +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 xmlns:android="http://schemas.android.com/apk/res/android">
-    <!-- TODO: for internal TODOs, expand theme/style to leaf resources as necessary -->
-    <style name="Theme.CarUi" parent="@android:style/Theme.DeviceDefault.NoActionBar">
-        <!-- TODO(b/150230923) change to true when other apps are ready -->
-        <item name="carUiBaseLayout">false</item>
-        <item name="carUiToolbar">false</item>
-
-        <!-- Attributes from: Base.V7.Theme.AppCompat -->
-
-        <item name="windowNoTitle">true</item>
-        <item name="windowActionBar">false</item>
-        <item name="windowActionBarOverlay">false</item>
-        <item name="windowActionModeOverlay">false</item>
-        <item name="actionBarPopupTheme">@null</item>
-
-        <item name="colorBackgroundFloating">?android:attr/colorBackgroundFloating</item>
-
-        <!-- Used by MediaRouter -->
-        <item name="isLightTheme">false</item>
-
-        <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
-        <item name="selectableItemBackgroundBorderless">?android:attr/selectableItemBackgroundBorderless</item>
-        <item name="borderlessButtonStyle">?android:attr/borderlessButtonStyle</item>
-        <item name="homeAsUpIndicator">?android:attr/homeAsUpIndicator</item>
-
-        <item name="dividerVertical">?android:attr/dividerVertical</item>
-        <item name="dividerHorizontal">?android:attr/dividerHorizontal</item>
-
-        <!-- Action Bar Styles -->
-        <item name="actionBarTabStyle">?android:attr/actionBarTabStyle</item>
-        <item name="actionBarTabBarStyle">?android:attr/actionBarTabBarStyle</item>
-        <item name="actionBarTabTextStyle">?android:attr/actionBarTabTextStyle</item>
-        <item name="actionButtonStyle">?android:attr/actionButtonStyle</item>
-        <item name="actionOverflowButtonStyle">?android:attr/actionOverflowButtonStyle</item>
-        <item name="actionOverflowMenuStyle">?android:attr/actionOverflowMenuStyle</item>
-        <item name="actionBarStyle">?android:attr/actionBarStyle</item>
-        <item name="actionBarSplitStyle">?android:attr/actionBarSplitStyle</item>
-        <item name="actionBarWidgetTheme">?android:attr/actionBarWidgetTheme</item>
-        <item name="actionBarTheme">?android:attr/actionBarTheme</item>
-        <item name="actionBarSize">?android:attr/actionBarSize</item>
-        <item name="actionBarDivider">?android:attr/actionBarDivider</item>
-        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
-        <item name="actionMenuTextAppearance">?android:attr/actionMenuTextAppearance</item>
-        <item name="actionMenuTextColor">?android:attr/actionMenuTextColor</item>
-
-        <!-- Dropdown Spinner Attributes -->
-        <item name="actionDropDownStyle">?android:attr/actionDropDownStyle</item>
-
-        <!-- Action Mode -->
-        <item name="actionModeStyle">?android:attr/actionModeStyle</item>
-        <item name="actionModeBackground">?android:attr/actionModeBackground</item>
-        <item name="actionModeSplitBackground">?android:attr/actionModeSplitBackground</item>
-        <item name="actionModeCloseDrawable">?android:attr/actionModeCloseDrawable</item>
-        <item name="actionModeCloseButtonStyle">?android:attr/actionModeCloseButtonStyle</item>
-
-        <item name="actionModeCutDrawable">?android:attr/actionModeCutDrawable</item>
-        <item name="actionModeCopyDrawable">?android:attr/actionModeCopyDrawable</item>
-        <item name="actionModePasteDrawable">?android:attr/actionModePasteDrawable</item>
-        <item name="actionModeSelectAllDrawable">?android:attr/actionModeSelectAllDrawable</item>
-        <item name="actionModeShareDrawable">?android:attr/actionModeShareDrawable</item>
-
-        <!-- Panel attributes -->
-        <!-- TODO: panelMenuListWidth -->
-        <item name="panelMenuListWidth">@dimen/abc_panel_menu_list_width</item>
-        <!-- TODO: panelMenuListTheme -->
-        <item name="panelMenuListTheme">@style/Theme.AppCompat.CompactMenu</item>
-        <item name="panelBackground">?android:attr/panelBackground</item>
-        <item name="listChoiceBackgroundIndicator">?android:attr/listChoiceBackgroundIndicator</item>
-
-        <!-- List attributes -->
-        <item name="textAppearanceListItem">?android:attr/textAppearanceListItem</item>
-        <item name="textAppearanceListItemSmall">?android:attr/textAppearanceListItemSmall</item>
-        <item name="textAppearanceListItemSecondary">?android:attr/textAppearanceListItemSecondary</item>
-        <item name="listPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
-        <item name="listPreferredItemHeightSmall">?android:attr/listPreferredItemHeightSmall</item>
-        <item name="listPreferredItemHeightLarge">?android:attr/listPreferredItemHeightLarge</item>
-        <item name="listPreferredItemPaddingLeft">?android:attr/listPreferredItemPaddingLeft</item>
-        <item name="listPreferredItemPaddingRight">?android:attr/listPreferredItemPaddingRight</item>
-
-        <!-- Spinner styles -->
-        <item name="spinnerStyle">?android:attr/spinnerStyle</item>
-
-        <!-- Required for use of support_simple_spinner_dropdown_item.xml -->
-        <item name="spinnerDropDownItemStyle">?android:attr/spinnerDropDownItemStyle</item>
-        <item name="dropdownListPreferredItemHeight">?attr/listPreferredItemHeightSmall</item>
-
-        <!-- Popup Menu styles -->
-        <item name="popupMenuStyle">?android:attr/popupMenuStyle</item>
-        <item name="textAppearanceLargePopupMenu">?android:attr/textAppearanceLargePopupMenu</item>
-        <item name="textAppearanceSmallPopupMenu">?android:attr/textAppearanceSmallPopupMenu</item>
-        <item name="textAppearancePopupMenuHeader">?android:attr/textAppearancePopupMenuHeader</item>
-        <item name="listPopupWindowStyle">?android:attr/listPopupWindowStyle</item>
-        <item name="dropDownListViewStyle">?android:attr/dropDownListViewStyle</item>
-        <item name="listMenuViewStyle">?android:attr/listMenuViewStyle</item>
-
-        <!-- SearchView attributes -->
-        <item name="searchViewStyle">?android:attr/searchViewStyle</item>
-        <!-- TODO: textColorSearchUrl -->
-        <item name="textColorSearchUrl">@color/abc_search_url_text</item>
-        <item name="textAppearanceSearchResultTitle">?android:attr/textAppearanceSearchResultTitle</item>
-        <item name="textAppearanceSearchResultSubtitle">?android:attr/textAppearanceSearchResultSubtitle</item>
-
-        <!-- ShareActionProvider attributes -->
-        <!-- TODO: activityChooserViewStyle -->
-        <item name="activityChooserViewStyle">@style/Widget.AppCompat.ActivityChooserView</item>
-
-        <!-- Toolbar styles -->
-        <item name="toolbarStyle">?android:attr/toolbarStyle</item>
-        <!-- TODO: toolbarNavigationButtonStyle -->
-        <item name="toolbarNavigationButtonStyle">@style/Widget.AppCompat.Toolbar.Button.Navigation</item>
-
-        <item name="editTextStyle">?android:attr/editTextStyle</item>
-        <item name="editTextBackground">?android:attr/editTextBackground</item>
-        <item name="editTextColor">?android:attr/editTextColor</item>
-        <item name="autoCompleteTextViewStyle">?android:attr/autoCompleteTextViewStyle</item>
-
-        <!-- Color palette -->
-        <item name="colorPrimaryDark">?android:attr/colorPrimaryDark</item>
-        <item name="colorPrimary">?android:attr/colorPrimary</item>
-        <item name="colorAccent">?android:attr/colorAccent</item>
-
-        <item name="colorControlNormal">?android:attr/colorControlNormal</item>
-        <item name="colorControlActivated">?android:attr/colorControlActivated</item>
-        <item name="colorControlHighlight">?android:attr/colorControlHighlight</item>
-        <item name="colorButtonNormal">?android:attr/colorButtonNormal</item>
-        <!-- TODO: colorSwitchThumbNormal -->
-        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
-        <item name="controlBackground">?attr/selectableItemBackgroundBorderless</item>
-
-        <!-- TODO: drawerArrowStyle -->
-        <item name="drawerArrowStyle">@style/Widget.AppCompat.DrawerArrowToggle</item>
-
-        <item name="checkboxStyle">?android:attr/checkboxStyle</item>
-        <item name="radioButtonStyle">?android:attr/radioButtonStyle</item>
-        <item name="switchStyle">?android:attr/switchStyle</item>
-
-        <item name="ratingBarStyle">?android:attr/ratingBarStyle</item>
-        <item name="ratingBarStyleIndicator">?android:attr/ratingBarStyleIndicator</item>
-        <item name="ratingBarStyleSmall">?android:attr/ratingBarStyleSmall</item>
-        <item name="seekBarStyle">?android:attr/seekBarStyle</item>
-
-        <!-- Button styles -->
-        <item name="buttonStyle">?android:attr/buttonStyle</item>
-        <item name="buttonStyleSmall">?android:attr/buttonStyleSmall</item>
-
-        <item name="imageButtonStyle">?android:attr/imageButtonStyle</item>
-
-        <item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
-        <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
-        <item name="buttonBarPositiveButtonStyle">?android:attr/buttonBarPositiveButtonStyle</item>
-        <item name="buttonBarNegativeButtonStyle">?android:attr/buttonBarNegativeButtonStyle</item>
-        <item name="buttonBarNeutralButtonStyle">?android:attr/buttonBarNeutralButtonStyle</item>
-
-        <!-- Dialog attributes -->
-        <item name="dialogTheme">?android:attr/dialogTheme</item>
-        <item name="dialogPreferredPadding">?android:attr/dialogPreferredPadding</item>
-        <item name="dialogCornerRadius">?android:attr/dialogCornerRadius</item>
-
-        <item name="alertDialogTheme">?android:attr/alertDialogTheme</item>
-        <item name="alertDialogStyle">?android:attr/alertDialogStyle</item>
-        <item name="alertDialogCenterButtons">false</item>
-        <item name="textColorAlertDialogListItem">?android:attr/textColorAlertDialogListItem</item>
-        <item name="listDividerAlertDialog">?android:attr/listDividerAlertDialog</item>
-
-        <!-- Define these here; ContextThemeWrappers around themes that define them should
-             always clear these values. -->
-        <item name="windowFixedWidthMajor">@null</item>
-        <item name="windowFixedWidthMinor">@null</item>
-        <item name="windowFixedHeightMajor">@null</item>
-        <item name="windowFixedHeightMinor">@null</item>
-
-        <!-- Tooltip attributes -->
-        <!-- TODO: tooltipFrameBackground -->
-        <item name="tooltipFrameBackground">@drawable/tooltip_frame_light</item>
-        <!-- TODO: tooltipForegroundColor -->
-        <item name="tooltipForegroundColor">@color/foreground_material_light</item>
-
-        <item name="colorError">?android:attr/colorError</item>
-
-        <!-- Attributes from: Platform.AppCompat -->
-
-        <item name="android:windowNoTitle">true</item>
-        <item name="android:windowActionBar">false</item>
-
-        <item name="listChoiceIndicatorSingleAnimated">?android:attr/listChoiceIndicatorSingle</item>
-        <item name="listChoiceIndicatorMultipleAnimated">?android:attr/listChoiceIndicatorMultiple</item>
-
-        <item name="preferenceTheme">@style/CarUiPreferenceTheme</item>
-
-        <!-- Used by CarUiRecyclerView -->
-        <item name="carUiRecyclerViewStyle">@style/Widget.CarUi.CarUiRecyclerView</item>
-    </style>
-
-    <!-- TODO(b/150230923) remove this when other apps are ready -->
-    <style name="Theme.CarUi.WithToolbar">
-        <item name="carUiBaseLayout">true</item>
-        <item name="carUiToolbar">true</item>
-        <item name="preferenceTheme">@style/CarUiPreferenceTheme.WithToolbar</item>
-    </style>
-
-    <style name="Theme.CarUi.NoToolbar">
-        <item name="carUiBaseLayout">true</item>
-        <item name="carUiToolbar">false</item>
-    </style>
-
-    <style name="CarUiPreferenceTheme">
-        <item name="checkBoxPreferenceStyle">@style/Preference.CarUi.CheckBoxPreference</item>
-        <item name="dialogPreferenceStyle">@style/Preference.CarUi.DialogPreference</item>
-        <item name="dropdownPreferenceStyle">@style/Preference.CarUi.DropDown</item>
-        <item name="editTextPreferenceStyle">@style/Preference.CarUi.DialogPreference.EditTextPreference</item>
-        <item name="preferenceCategoryStyle">@style/Preference.CarUi.Category</item>
-        <item name="preferenceFragmentCompatStyle">@style/PreferenceFragment.CarUi</item>
-        <item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.CarUi</item>
-        <item name="preferenceFragmentStyle">@style/PreferenceFragment.CarUi</item>
-        <item name="preferenceScreenStyle">@style/Preference.CarUi.PreferenceScreen</item>
-        <item name="preferenceStyle">@style/Preference.CarUi</item>
-        <item name="seekBarPreferenceStyle">@style/Preference.CarUi.SeekBarPreference</item>
-        <item name="switchPreferenceStyle">@style/Preference.CarUi.SwitchPreference</item>
-    </style>
-
-    <!-- TODO(b/150230923) remove this when other apps are ready -->
-    <style name="CarUiPreferenceTheme.WithToolbar">
-        <item name="preferenceFragmentCompatStyle">@style/PreferenceFragment.CarUi.WithToolbar</item>
-        <item name="preferenceFragmentStyle">@style/PreferenceFragment.CarUi.WithToolbar</item>
-    </style>
-
-</resources>
diff --git a/car-ui-lib/settings.gradle b/car-ui-lib/settings.gradle
index 56f7f65..4deba21 100644
--- a/car-ui-lib/settings.gradle
+++ b/car-ui-lib/settings.gradle
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
+include ':car-ui-lib'
+project(':car-ui-lib').projectDir = new File('./car-ui-lib')
 include ':PaintBooth'
-project(':PaintBooth').projectDir = new File('./tests/paintbooth')
-include ':RoboTests'
-project(':RoboTests').projectDir = new File('./tests/robotests')
+project(':PaintBooth').projectDir = new File('./paintbooth')
+include ':shared-library'
+project(':shared-library').projectDir = new File('./sharedlibrary')
+
 rootProject.name='Chassis'
diff --git a/car-ui-lib/sharedlibrary/AndroidManifest-gradle.xml b/car-ui-lib/sharedlibrary/AndroidManifest-gradle.xml
new file mode 100644
index 0000000..53744fd
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/AndroidManifest-gradle.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2020 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui.sharedlibrary">
+  <application>
+      <library android:name="com.android.car.ui.sharedlibrary" />
+  </application>
+</manifest>
diff --git a/car-ui-lib/sharedlibrary/AndroidManifest.xml b/car-ui-lib/sharedlibrary/AndroidManifest.xml
new file mode 100644
index 0000000..89a2407
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2020 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.car.ui.sharedlibrary">
+  <uses-sdk
+      android:minSdkVersion="28"
+      android:targetSdkVersion="30"/>
+  <application>
+      <library android:name="com.android.car.ui.sharedlibrary"/>
+  </application>
+</manifest>
diff --git a/car-ui-lib/sharedlibrary/README.md b/car-ui-lib/sharedlibrary/README.md
new file mode 100644
index 0000000..6835846
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/README.md
@@ -0,0 +1,5 @@
+# Android Automotive 'Chassis' shared library
+Please refer to [Android Automotive 'Chassiss' library](../README.md)
+
+**Required**
+This module needs to be, and is included in PRODUCT_PACKAGES in vendor/auto/embeded/products/car.mk. It needs to be pre-installed with the system image.
diff --git a/car-ui-lib/sharedlibrary/build.gradle b/car-ui-lib/sharedlibrary/build.gradle
new file mode 100644
index 0000000..f5a4831
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/build.gradle
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// Library-level build file
+
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 30
+
+    defaultConfig {
+        minSdkVersion 28
+        targetSdkVersion 30
+        versionCode 1
+        versionName "1.0"
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest-gradle.xml'
+        }
+    }
+}
+
+dependencies {
+}
diff --git a/car-ui-lib/sharedlibrary/src/main/res/values/public.xml b/car-ui-lib/sharedlibrary/src/main/res/values/public.xml
new file mode 100644
index 0000000..7ec6c82
--- /dev/null
+++ b/car-ui-lib/sharedlibrary/src/main/res/values/public.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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>
+    <!-- Any resource or attribute that is or can be referenced from RRO needs to be public go/rro-on-r -->
+    <!-- Keep in mind public resources are ignored when building with gradle -->
+
+    <!-- To add new resources to this file follow the following naming convention -->
+    <!-- 0cXXXX is used for styles -->
+    <!-- 0dXXXX is used for attributes -->
+    <!-- 0eXXXX is used for drawables -->
+    <!-- The first time that a resource type is seen, Android resource manager, assigns YY of the ID (0xXXYYXXXX) of the resource to that type.
+         And you'll get a compile error if you use the same type with a different YY -->
+
+</resources>
diff --git a/car-ui-lib/src/com/android/car/ui/AlertDialogBuilder.java b/car-ui-lib/src/com/android/car/ui/AlertDialogBuilder.java
deleted file mode 100644
index bb301e3..0000000
--- a/car-ui-lib/src/com/android/car/ui/AlertDialogBuilder.java
+++ /dev/null
@@ -1,681 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.text.InputFilter;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.TextView;
-
-import androidx.annotation.ArrayRes;
-import androidx.annotation.AttrRes;
-import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.StringRes;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.recyclerview.CarUiListItemAdapter;
-import com.android.car.ui.recyclerview.CarUiRadioButtonListItemAdapter;
-import com.android.car.ui.utils.CarUiUtils;
-
-/**
- * Wrapper for AlertDialog.Builder
- */
-public class AlertDialogBuilder {
-
-    private AlertDialog.Builder mBuilder;
-    private Context mContext;
-    private boolean mPositiveButtonSet;
-    private boolean mNeutralButtonSet;
-    private boolean mNegativeButtonSet;
-    private CharSequence mTitle;
-    private CharSequence mSubtitle;
-    private Drawable mIcon;
-
-    public AlertDialogBuilder(Context context) {
-        // Resource id specified as 0 uses the parent contexts resolved value for alertDialogTheme.
-        this(context, /* themeResId= */0);
-    }
-
-    public AlertDialogBuilder(Context context, int themeResId) {
-        mBuilder = new AlertDialog.Builder(context, themeResId);
-        mContext = context;
-    }
-
-    public Context getContext() {
-        return mBuilder.getContext();
-    }
-
-    /**
-     * Set the title using the given resource id.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setTitle(@StringRes int titleId) {
-        return setTitle(mContext.getText(titleId));
-    }
-
-    /**
-     * Set the title displayed in the {@link Dialog}.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setTitle(CharSequence title) {
-        mTitle = title;
-        mBuilder.setTitle(title);
-        return this;
-    }
-
-    /**
-     * Sets a subtitle to be displayed in the {@link Dialog}.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setSubtitle(@StringRes int subtitle) {
-        return setSubtitle(mContext.getString(subtitle));
-    }
-
-    /**
-     * Sets a subtitle to be displayed in the {@link Dialog}.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setSubtitle(CharSequence subtitle) {
-        mSubtitle = subtitle;
-        return this;
-    }
-
-    /**
-     * Set the message to display using the given resource id.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setMessage(@StringRes int messageId) {
-        mBuilder.setMessage(messageId);
-        return this;
-    }
-
-    /**
-     * Set the message to display.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setMessage(CharSequence message) {
-        mBuilder.setMessage(message);
-        return this;
-    }
-
-    /**
-     * Set the resource id of the {@link Drawable} to be used in the title.
-     * <p>
-     * Takes precedence over values set using {@link #setIcon(Drawable)}.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setIcon(@DrawableRes int iconId) {
-        return setIcon(mContext.getDrawable(iconId));
-    }
-
-    /**
-     * Set the {@link Drawable} to be used in the title.
-     * <p>
-     * <strong>Note:</strong> To ensure consistent styling, the drawable
-     * should be inflated or constructed using the alert dialog's themed
-     * context obtained via {@link #getContext()}.
-     *
-     * @return this Builder object to allow for chaining of calls to set
-     * methods
-     */
-    public AlertDialogBuilder setIcon(Drawable icon) {
-        mIcon = icon;
-        mBuilder.setIcon(icon);
-        return this;
-    }
-
-    /**
-     * Set an icon as supplied by a theme attribute. e.g.
-     * {@link android.R.attr#alertDialogIcon}.
-     * <p>
-     * Takes precedence over values set using {@link #setIcon(int)} or
-     * {@link #setIcon(Drawable)}.
-     *
-     * @param attrId ID of a theme attribute that points to a drawable resource.
-     */
-    public AlertDialogBuilder setIconAttribute(@AttrRes int attrId) {
-        mBuilder.setIconAttribute(attrId);
-        return this;
-    }
-
-    /**
-     * Set a listener to be invoked when the positive button of the dialog is pressed.
-     *
-     * @param textId The resource id of the text to display in the positive button
-     * @param listener The {@link DialogInterface.OnClickListener} to use.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setPositiveButton(@StringRes int textId,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setPositiveButton(textId, listener);
-        mPositiveButtonSet = true;
-        return this;
-    }
-
-    /**
-     * Set a listener to be invoked when the positive button of the dialog is pressed.
-     *
-     * @param text The text to display in the positive button
-     * @param listener The {@link DialogInterface.OnClickListener} to use.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setPositiveButton(CharSequence text,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setPositiveButton(text, listener);
-        mPositiveButtonSet = true;
-        return this;
-    }
-
-    /**
-     * Set a listener to be invoked when the negative button of the dialog is pressed.
-     *
-     * @param textId The resource id of the text to display in the negative button
-     * @param listener The {@link DialogInterface.OnClickListener} to use.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setNegativeButton(@StringRes int textId,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setNegativeButton(textId, listener);
-        mNegativeButtonSet = true;
-        return this;
-    }
-
-    /**
-     * Set a listener to be invoked when the negative button of the dialog is pressed.
-     *
-     * @param text The text to display in the negative button
-     * @param listener The {@link DialogInterface.OnClickListener} to use.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setNegativeButton(CharSequence text,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setNegativeButton(text, listener);
-        mNegativeButtonSet = true;
-        return this;
-    }
-
-    /**
-     * Set a listener to be invoked when the neutral button of the dialog is pressed.
-     *
-     * @param textId The resource id of the text to display in the neutral button
-     * @param listener The {@link DialogInterface.OnClickListener} to use.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setNeutralButton(@StringRes int textId,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setNeutralButton(textId, listener);
-        mNeutralButtonSet = true;
-        return this;
-    }
-
-    /**
-     * Set a listener to be invoked when the neutral button of the dialog is pressed.
-     *
-     * @param text The text to display in the neutral button
-     * @param listener The {@link DialogInterface.OnClickListener} to use.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setNeutralButton(CharSequence text,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setNeutralButton(text, listener);
-        mNeutralButtonSet = true;
-        return this;
-    }
-
-    /**
-     * Sets whether the dialog is cancelable or not.  Default is true.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setCancelable(boolean cancelable) {
-        mBuilder.setCancelable(cancelable);
-        return this;
-    }
-
-    /**
-     * Sets the callback that will be called if the dialog is canceled.
-     *
-     * <p>Even in a cancelable dialog, the dialog may be dismissed for reasons other than
-     * being canceled or one of the supplied choices being selected.
-     * If you are interested in listening for all cases where the dialog is dismissed
-     * and not just when it is canceled, see
-     * {@link #setOnDismissListener(android.content.DialogInterface.OnDismissListener)
-     * setOnDismissListener}.</p>
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     * @see #setCancelable(boolean)
-     * @see #setOnDismissListener(android.content.DialogInterface.OnDismissListener)
-     */
-    public AlertDialogBuilder setOnCancelListener(
-            DialogInterface.OnCancelListener onCancelListener) {
-        mBuilder.setOnCancelListener(onCancelListener);
-        return this;
-    }
-
-    /**
-     * Sets the callback that will be called when the dialog is dismissed for any reason.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setOnDismissListener(
-            DialogInterface.OnDismissListener onDismissListener) {
-        mBuilder.setOnDismissListener(onDismissListener);
-        return this;
-    }
-
-    /**
-     * Sets the callback that will be called if a key is dispatched to the dialog.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setOnKeyListener(DialogInterface.OnKeyListener onKeyListener) {
-        mBuilder.setOnKeyListener(onKeyListener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content, you will be notified of the
-     * selected item via the supplied listener. This should be an array type i.e. R.array.foo
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setItems(@ArrayRes int itemsId,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setItems(itemsId, listener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content, you will be notified of the
-     * selected item via the supplied listener.
-     *
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setItems(CharSequence[] items,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setItems(items, listener);
-        return this;
-    }
-
-    /**
-     * This was not supposed to be in the Chassis API because it allows custom views.
-     *
-     * @deprecated Use {@link #setAdapter(CarUiListItemAdapter)} instead.
-     */
-    @Deprecated
-    public AlertDialogBuilder setAdapter(final ListAdapter adapter,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setAdapter(adapter, listener);
-        return this;
-    }
-
-    /**
-     * Display all the {@link com.android.car.ui.recyclerview.CarUiListItem CarUiListItems} in a
-     * {@link CarUiListItemAdapter}. You should set click listeners on the CarUiListItems as
-     * opposed to a callback in this function.
-     */
-    public AlertDialogBuilder setAdapter(final CarUiListItemAdapter adapter) {
-        setCustomList(adapter);
-        return this;
-    }
-
-    private void setCustomList(@NonNull CarUiListItemAdapter adapter) {
-        View customList = LayoutInflater.from(mContext).inflate(
-                R.layout.car_ui_alert_dialog_list, null);
-        RecyclerView mList = CarUiUtils.requireViewByRefId(customList, R.id.list);
-        mList.setLayoutManager(new LinearLayoutManager(mContext));
-        mList.setAdapter(adapter);
-        mBuilder.setView(customList);
-    }
-
-    /**
-     * Set a list of items, which are supplied by the given {@link Cursor}, to be
-     * displayed in the dialog as the content, you will be notified of the
-     * selected item via the supplied listener.
-     *
-     * @param cursor The {@link Cursor} to supply the list of items
-     * @param listener The listener that will be called when an item is clicked.
-     * @param labelColumn The column name on the cursor containing the string to display
-     * in the label.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setCursor(final Cursor cursor,
-            final DialogInterface.OnClickListener listener,
-            String labelColumn) {
-        mBuilder.setCursor(cursor, listener, labelColumn);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content,
-     * you will be notified of the selected item via the supplied listener.
-     * This should be an array type, e.g. R.array.foo. The list will have
-     * a check mark displayed to the right of the text for each checked
-     * item. Clicking on an item in the list will not dismiss the dialog.
-     * Clicking on a button will dismiss the dialog.
-     *
-     * @param itemsId the resource id of an array i.e. R.array.foo
-     * @param checkedItems specifies which items are checked. It should be null in which case no
-     * items are checked. If non null it must be exactly the same length as the array of
-     * items.
-     * @param listener notified when an item on the list is clicked. The dialog will not be
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems,
-            final DialogInterface.OnMultiChoiceClickListener listener) {
-        mBuilder.setMultiChoiceItems(itemsId, checkedItems, listener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content,
-     * you will be notified of the selected item via the supplied listener.
-     * The list will have a check mark displayed to the right of the text
-     * for each checked item. Clicking on an item in the list will not
-     * dismiss the dialog. Clicking on a button will dismiss the dialog.
-     *
-     * @param items the text of the items to be displayed in the list.
-     * @param checkedItems specifies which items are checked. It should be null in which case no
-     * items are checked. If non null it must be exactly the same length as the array of
-     * items.
-     * @param listener notified when an item on the list is clicked. The dialog will not be
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems,
-            final DialogInterface.OnMultiChoiceClickListener listener) {
-        mBuilder.setMultiChoiceItems(items, checkedItems, listener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content,
-     * you will be notified of the selected item via the supplied listener.
-     * The list will have a check mark displayed to the right of the text
-     * for each checked item. Clicking on an item in the list will not
-     * dismiss the dialog. Clicking on a button will dismiss the dialog.
-     *
-     * @param cursor the cursor used to provide the items.
-     * @param isCheckedColumn specifies the column name on the cursor to use to determine
-     * whether a checkbox is checked or not. It must return an integer value where 1
-     * means checked and 0 means unchecked.
-     * @param labelColumn The column name on the cursor containing the string to display in the
-     * label.
-     * @param listener notified when an item on the list is clicked. The dialog will not be
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setMultiChoiceItems(Cursor cursor, String isCheckedColumn,
-            String labelColumn,
-            final DialogInterface.OnMultiChoiceClickListener listener) {
-        mBuilder.setMultiChoiceItems(cursor, isCheckedColumn, labelColumn, listener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content, you will be notified of
-     * the selected item via the supplied listener. This should be an array type i.e.
-     * R.array.foo The list will have a check mark displayed to the right of the text for the
-     * checked item. Clicking on an item in the list will not dismiss the dialog. Clicking on a
-     * button will dismiss the dialog.
-     *
-     * @param itemsId the resource id of an array i.e. R.array.foo
-     * @param checkedItem specifies which item is checked. If -1 no items are checked.
-     * @param listener notified when an item on the list is clicked. The dialog will not be
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setSingleChoiceItems(itemsId, checkedItem, listener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content, you will be notified of
-     * the selected item via the supplied listener. The list will have a check mark displayed to
-     * the right of the text for the checked item. Clicking on an item in the list will not
-     * dismiss the dialog. Clicking on a button will dismiss the dialog.
-     *
-     * @param cursor the cursor to retrieve the items from.
-     * @param checkedItem specifies which item is checked. If -1 no items are checked.
-     * @param labelColumn The column name on the cursor containing the string to display in the
-     * label.
-     * @param listener notified when an item on the list is clicked. The dialog will not be
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setSingleChoiceItems(Cursor cursor, int checkedItem,
-            String labelColumn,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setSingleChoiceItems(cursor, checkedItem, labelColumn, listener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content, you will be notified of
-     * the selected item via the supplied listener. The list will have a check mark displayed to
-     * the right of the text for the checked item. Clicking on an item in the list will not
-     * dismiss the dialog. Clicking on a button will dismiss the dialog.
-     *
-     * @param items the items to be displayed.
-     * @param checkedItem specifies which item is checked. If -1 no items are checked.
-     * @param listener notified when an item on the list is clicked. The dialog will not be
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setSingleChoiceItems(CharSequence[] items, int checkedItem,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setSingleChoiceItems(items, checkedItem, listener);
-        return this;
-    }
-
-    /**
-     * This was not supposed to be in the Chassis API because it allows custom views.
-     *
-     * @deprecated Use {@link #setSingleChoiceItems(CarUiRadioButtonListItemAdapter,
-     * DialogInterface.OnClickListener)} instead.
-     */
-    @Deprecated
-    public AlertDialogBuilder setSingleChoiceItems(ListAdapter adapter, int checkedItem,
-            final DialogInterface.OnClickListener listener) {
-        mBuilder.setSingleChoiceItems(adapter, checkedItem, listener);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content, you will be notified of
-     * the selected item via the supplied listener. The list will have a check mark displayed to
-     * the right of the text for the checked item. Clicking on an item in the list will not
-     * dismiss the dialog. Clicking on a button will dismiss the dialog.
-     *
-     * @param adapter The {@link CarUiRadioButtonListItemAdapter} to supply the list of items
-     * @param listener notified when an item on the list is clicked. The dialog will not be
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     *
-     * @deprecated Use {@link #setSingleChoiceItems(CarUiRadioButtonListItemAdapter)} instead.
-     */
-    @Deprecated
-    public AlertDialogBuilder setSingleChoiceItems(CarUiRadioButtonListItemAdapter adapter,
-            final DialogInterface.OnClickListener listener) {
-        setCustomList(adapter);
-        return this;
-    }
-
-    /**
-     * Set a list of items to be displayed in the dialog as the content,The list will have a check
-     * mark displayed to the right of the text for the checked item. Clicking on an item in the list
-     * will not dismiss the dialog. Clicking on a button will dismiss the dialog.
-     *
-     * @param adapter The {@link CarUiRadioButtonListItemAdapter} to supply the list of items
-     * dismissed when an item is clicked. It will only be dismissed if clicked on a
-     * button, if no buttons are supplied it's up to the user to dismiss the dialog.
-     * @return This Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setSingleChoiceItems(CarUiRadioButtonListItemAdapter adapter) {
-        setCustomList(adapter);
-        return this;
-    }
-
-    /**
-     * Sets a listener to be invoked when an item in the list is selected.
-     *
-     * @param listener the listener to be invoked
-     * @return this Builder object to allow for chaining of calls to set methods
-     * @see AdapterView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
-     */
-    public AlertDialogBuilder setOnItemSelectedListener(
-            final AdapterView.OnItemSelectedListener listener) {
-        mBuilder.setOnItemSelectedListener(listener);
-        return this;
-    }
-
-    /**
-     * Sets a custom edit text box within the alert dialog.
-     *
-     * @param prompt the string that will be set on the edit text view
-     * @param textChangedListener textWatcher whose methods are called whenever this TextView's text
-     * changes {@link null} otherwise.
-     * @param inputFilters list of input filters, {@link null} if no filter is needed
-     * @param inputType See {@link EditText#setInputType(int)}, except
-     *                  {@link android.text.InputType#TYPE_NULL} will not be set.
-     * @return this Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setEditBox(String prompt, TextWatcher textChangedListener,
-            InputFilter[] inputFilters, int inputType) {
-        View contentView = LayoutInflater.from(mContext).inflate(
-                R.layout.car_ui_alert_dialog_edit_text, null);
-
-        EditText editText = CarUiUtils.requireViewByRefId(contentView, R.id.textbox);
-        editText.setText(prompt);
-
-        if (textChangedListener != null) {
-            editText.addTextChangedListener(textChangedListener);
-        }
-
-        if (inputFilters != null) {
-            editText.setFilters(inputFilters);
-        }
-
-        if (inputType != 0) {
-            editText.setInputType(inputType);
-        }
-
-        mBuilder.setView(contentView);
-        return this;
-    }
-
-    /**
-     * Sets a custom edit text box within the alert dialog.
-     *
-     * @param prompt the string that will be set on the edit text view
-     * @param textChangedListener textWatcher whose methods are called whenever this TextView's text
-     * changes {@link null} otherwise.
-     * @param inputFilters list of input filters, {@link null} if no filter is needed
-     * @return this Builder object to allow for chaining of calls to set methods
-     */
-    public AlertDialogBuilder setEditBox(String prompt, TextWatcher textChangedListener,
-            InputFilter[] inputFilters) {
-        return setEditBox(prompt, textChangedListener, inputFilters, 0);
-    }
-
-
-    /** Final steps common to both {@link #create()} and {@link #show()} */
-    private void prepareDialog() {
-        View customTitle = LayoutInflater.from(mContext).inflate(
-                R.layout.car_ui_alert_dialog_title_with_subtitle, null);
-
-        TextView mTitleView =
-                CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_title);
-        TextView mSubtitleView =
-                CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_subtitle);
-        ImageView mIconView =
-                CarUiUtils.requireViewByRefId(customTitle, R.id.car_ui_alert_icon);
-
-        mTitleView.setText(mTitle);
-        mTitleView.setVisibility(TextUtils.isEmpty(mTitle) ? View.GONE : View.VISIBLE);
-        mSubtitleView.setText(mSubtitle);
-        mSubtitleView.setVisibility(TextUtils.isEmpty(mSubtitle) ? View.GONE : View.VISIBLE);
-        mIconView.setImageDrawable(mIcon);
-        mIconView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
-        mBuilder.setCustomTitle(customTitle);
-
-        if (!mNeutralButtonSet && !mNegativeButtonSet && !mPositiveButtonSet) {
-            String mDefaultButtonText = mContext.getString(
-                    R.string.car_ui_alert_dialog_default_button);
-            mBuilder.setNegativeButton(mDefaultButtonText, (dialog, which) -> {
-            });
-        }
-    }
-
-    /**
-     * Creates an {@link AlertDialog} with the arguments supplied to this
-     * builder.
-     * <p>
-     * Calling this method does not display the dialog. If no additional
-     * processing is needed, {@link #show()} may be called instead to both
-     * create and display the dialog.
-     */
-    public AlertDialog create() {
-        prepareDialog();
-        return mBuilder.create();
-    }
-
-    /**
-     * Creates an {@link AlertDialog} with the arguments supplied to this
-     * builder and immediately displays the dialog.
-     * <p>
-     * Calling this method is functionally identical to:
-     * <pre>
-     *     AlertDialog dialog = builder.create();
-     *     dialog.show();
-     * </pre>
-     */
-    public AlertDialog show() {
-        prepareDialog();
-        return mBuilder.show();
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/core/BaseLayoutController.java b/car-ui-lib/src/com/android/car/ui/core/BaseLayoutController.java
deleted file mode 100644
index e1209d9..0000000
--- a/car-ui-lib/src/com/android/car/ui/core/BaseLayoutController.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.core;
-
-import android.app.Activity;
-import android.content.res.TypedArray;
-import android.os.Build;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
-
-import androidx.annotation.LayoutRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
-
-import com.android.car.ui.R;
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.toolbar.ToolbarController;
-import com.android.car.ui.toolbar.ToolbarControllerImpl;
-import com.android.car.ui.utils.CarUiUtils;
-
-import java.util.Map;
-import java.util.WeakHashMap;
-
-/**
- * BaseLayoutController accepts an {@link Activity} and sets up the base layout inside of it.
- * It also exposes a {@link ToolbarController} to access the toolbar. This may be null if
- * used with a base layout without a Toolbar.
- */
-class BaseLayoutController {
-
-    private static final Map<Activity, BaseLayoutController> sBaseLayoutMap = new WeakHashMap<>();
-
-    private InsetsUpdater mInsetsUpdater;
-
-    /**
-     * Gets a BaseLayoutController for the given {@link Activity}. Must have called
-     * {@link #build(Activity)} with the same activity earlier, otherwise will return null.
-     */
-    @Nullable
-    /* package */ static BaseLayoutController getBaseLayout(Activity activity) {
-        return sBaseLayoutMap.get(activity);
-    }
-
-    @Nullable
-    private ToolbarController mToolbarController;
-
-    private BaseLayoutController(Activity activity) {
-        installBaseLayout(activity);
-    }
-
-    /**
-     * Create a new BaseLayoutController for the given {@link Activity}.
-     *
-     * <p>You can get a reference to it by calling {@link #getBaseLayout(Activity)}.
-     */
-    /* package */
-    static void build(Activity activity) {
-        if (getThemeBoolean(activity, R.attr.carUiBaseLayout)) {
-            sBaseLayoutMap.put(activity, new BaseLayoutController(activity));
-        }
-    }
-
-    /**
-     * Destroy the BaseLayoutController for the given {@link Activity}.
-     */
-    /* package */
-    static void destroy(Activity activity) {
-        sBaseLayoutMap.remove(activity);
-    }
-
-    /**
-     * Gets the {@link ToolbarController} for activities created with carUiBaseLayout and
-     * carUiToolbar set to true.
-     */
-    @Nullable
-    /* package */ ToolbarController getToolbarController() {
-        return mToolbarController;
-    }
-
-    /* package */ Insets getInsets() {
-        return mInsetsUpdater.getInsets();
-    }
-
-    /* package */ void dispatchNewInsets(Insets insets) {
-        mInsetsUpdater.dispatchNewInsets(insets);
-    }
-
-    /* package */ void replaceInsetsChangedListenerWith(InsetsChangedListener listener) {
-        mInsetsUpdater.replaceInsetsChangedListenerWith(listener);
-    }
-
-    /**
-     * Installs the base layout into an activity, moving its content view under the base layout.
-     *
-     * <p>This function must be called during the onCreate() of the {@link Activity}.
-     *
-     * @param activity The {@link Activity} to install a base layout in.
-     */
-    private void installBaseLayout(Activity activity) {
-        boolean toolbarEnabled = getThemeBoolean(activity, R.attr.carUiToolbar);
-        boolean legacyToolbar = Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q;
-        @LayoutRes final int baseLayoutRes;
-
-        if (toolbarEnabled) {
-            baseLayoutRes = legacyToolbar
-                    ? R.layout.car_ui_base_layout_toolbar_legacy
-                    : R.layout.car_ui_base_layout_toolbar;
-        } else {
-            baseLayoutRes = R.layout.car_ui_base_layout;
-        }
-
-        View baseLayout = LayoutInflater.from(activity)
-                .inflate(baseLayoutRes, null, false);
-
-        // Replace windowContentView with baseLayout
-        ViewGroup windowContentView = CarUiUtils.findViewByRefId(
-                activity.getWindow().getDecorView(), android.R.id.content);
-        ViewGroup contentViewParent = (ViewGroup) windowContentView.getParent();
-        int contentIndex = contentViewParent.indexOfChild(windowContentView);
-        contentViewParent.removeView(windowContentView);
-        contentViewParent.addView(baseLayout, contentIndex, windowContentView.getLayoutParams());
-
-        // Add windowContentView to the baseLayout's content view
-        FrameLayout contentView = CarUiUtils.requireViewByRefId(baseLayout,
-                R.id.car_ui_base_layout_content_container);
-        contentView.addView(windowContentView, new FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT));
-
-        if (toolbarEnabled) {
-            if (legacyToolbar) {
-                mToolbarController = CarUiUtils.requireViewByRefId(baseLayout, R.id.car_ui_toolbar);
-            } else {
-                mToolbarController = new ToolbarControllerImpl(baseLayout);
-            }
-        }
-
-        mInsetsUpdater = new InsetsUpdater(activity, baseLayout, windowContentView);
-        mInsetsUpdater.installListeners();
-    }
-
-    /**
-     * Gets the boolean value of an Attribute from an {@link Activity Activity's}
-     * {@link android.content.res.Resources.Theme}.
-     */
-    private static boolean getThemeBoolean(Activity activity, int attr) {
-        TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{attr});
-
-        try {
-            return a.getBoolean(0, false);
-        } finally {
-            a.recycle();
-        }
-    }
-
-    /**
-     * InsetsUpdater waits for layout changes, and when there is one, calculates the appropriate
-     * insets into the content view.
-     *
-     * <p>It then calls {@link InsetsChangedListener#onCarUiInsetsChanged(Insets)} on the
-     * {@link Activity} and any {@link Fragment Fragments} the Activity might have. If
-     * none of the Activity/Fragments implement {@link InsetsChangedListener}, it will set
-     * padding on the content view equal to the insets.
-     */
-    private static class InsetsUpdater implements ViewTreeObserver.OnGlobalLayoutListener {
-        // These tags mark views that should overlay the content view in the base layout.
-        // OEMs should add them to views in their base layout, ie: android:tag="car_ui_left_inset"
-        // Apps will then be able to draw under these views, but will be encouraged to not put
-        // any user-interactable content there.
-        private static final String LEFT_INSET_TAG = "car_ui_left_inset";
-        private static final String RIGHT_INSET_TAG = "car_ui_right_inset";
-        private static final String TOP_INSET_TAG = "car_ui_top_inset";
-        private static final String BOTTOM_INSET_TAG = "car_ui_bottom_inset";
-
-        private final Activity mActivity;
-        private final View mLeftInsetView;
-        private final View mRightInsetView;
-        private final View mTopInsetView;
-        private final View mBottomInsetView;
-        private InsetsChangedListener mInsetsChangedListenerDelegate;
-
-        private boolean mInsetsDirty = true;
-        @NonNull
-        private Insets mInsets = new Insets();
-
-        /**
-         * Constructs an InsetsUpdater that calculates and dispatches insets to an {@link Activity}.
-         *
-         * @param activity    The activity that is using base layouts
-         * @param baseLayout  The root view of the base layout
-         * @param contentView The android.R.id.content View
-         */
-        InsetsUpdater(Activity activity, View baseLayout, View contentView) {
-            mActivity = activity;
-
-            mLeftInsetView = baseLayout.findViewWithTag(LEFT_INSET_TAG);
-            mRightInsetView = baseLayout.findViewWithTag(RIGHT_INSET_TAG);
-            mTopInsetView = baseLayout.findViewWithTag(TOP_INSET_TAG);
-            mBottomInsetView = baseLayout.findViewWithTag(BOTTOM_INSET_TAG);
-
-            final View.OnLayoutChangeListener layoutChangeListener =
-                    (View v, int left, int top, int right, int bottom,
-                            int oldLeft, int oldTop, int oldRight, int oldBottom) -> {
-                        if (left != oldLeft || top != oldTop
-                                || right != oldRight || bottom != oldBottom) {
-                            mInsetsDirty = true;
-                        }
-                    };
-
-            if (mLeftInsetView != null) {
-                mLeftInsetView.addOnLayoutChangeListener(layoutChangeListener);
-            }
-            if (mRightInsetView != null) {
-                mRightInsetView.addOnLayoutChangeListener(layoutChangeListener);
-            }
-            if (mTopInsetView != null) {
-                mTopInsetView.addOnLayoutChangeListener(layoutChangeListener);
-            }
-            if (mBottomInsetView != null) {
-                mBottomInsetView.addOnLayoutChangeListener(layoutChangeListener);
-            }
-            contentView.addOnLayoutChangeListener(layoutChangeListener);
-        }
-
-        /**
-         * Install a global layout listener, during which the insets will be recalculated and
-         * dispatched.
-         */
-        void installListeners() {
-            // The global layout listener will run after all the individual layout change listeners
-            // so that we only updateInsets once per layout, even if multiple inset views changed
-            mActivity.getWindow().getDecorView().getViewTreeObserver()
-                    .addOnGlobalLayoutListener(this);
-        }
-
-        @NonNull
-        Insets getInsets() {
-            return mInsets;
-        }
-
-        public void replaceInsetsChangedListenerWith(InsetsChangedListener listener) {
-            mInsetsChangedListenerDelegate = listener;
-        }
-
-        /**
-         * onGlobalLayout() should recalculate the amount of insets we need, and then dispatch them.
-         */
-        @Override
-        public void onGlobalLayout() {
-            if (!mInsetsDirty) {
-                return;
-            }
-
-            View content = CarUiUtils.requireViewByRefId(mActivity.getWindow().getDecorView(),
-                    android.R.id.content);
-
-            // Calculate how much each inset view overlays the content view
-            int top = 0;
-            int left = 0;
-            int right = 0;
-            int bottom = 0;
-            if (mTopInsetView != null) {
-                top = Math.max(0, getBottomOfView(mTopInsetView) - getTopOfView(content));
-            }
-            if (mBottomInsetView != null) {
-                bottom = Math.max(0, getBottomOfView(content) - getTopOfView(mBottomInsetView));
-            }
-            if (mLeftInsetView != null) {
-                left = Math.max(0, getRightOfView(mLeftInsetView) - getLeftOfView(content));
-            }
-            if (mRightInsetView != null) {
-                right = Math.max(0, getRightOfView(content) - getLeftOfView(mRightInsetView));
-            }
-            Insets insets = new Insets(left, top, right, bottom);
-
-            mInsetsDirty = false;
-            if (!insets.equals(mInsets)) {
-                mInsets = insets;
-                dispatchNewInsets(insets);
-            }
-        }
-
-        /**
-         * Dispatch the new {@link Insets} to the {@link Activity} and all of its
-         * {@link Fragment Fragments}. If none of those implement {@link InsetsChangedListener},
-         * we will set the value of the insets as padding on the content view.
-         *
-         * @param insets The newly-changed insets.
-         */
-        /* package */ void dispatchNewInsets(Insets insets) {
-            mInsets = insets;
-
-            boolean handled = false;
-
-            if (mInsetsChangedListenerDelegate != null) {
-                mInsetsChangedListenerDelegate.onCarUiInsetsChanged(insets);
-                handled = true;
-            } else {
-                // If an explicit InsetsChangedListener is not provided,
-                // pass the insets to activities and fragments
-                if (mActivity instanceof InsetsChangedListener) {
-                    ((InsetsChangedListener) mActivity).onCarUiInsetsChanged(insets);
-                    handled = true;
-                }
-
-                if (mActivity instanceof FragmentActivity) {
-                    for (Fragment fragment : ((FragmentActivity) mActivity)
-                            .getSupportFragmentManager().getFragments()) {
-                        if (fragment instanceof InsetsChangedListener) {
-                            ((InsetsChangedListener) fragment).onCarUiInsetsChanged(insets);
-                            handled = true;
-                        }
-                    }
-                }
-            }
-
-            if (!handled) {
-                CarUiUtils.requireViewByRefId(mActivity.getWindow().getDecorView(),
-                        android.R.id.content).setPadding(insets.getLeft(), insets.getTop(),
-                        insets.getRight(), insets.getBottom());
-            }
-        }
-
-        private static int getLeftOfView(View v) {
-            int[] position = new int[2];
-            v.getLocationOnScreen(position);
-            return position[0];
-        }
-
-        private static int getRightOfView(View v) {
-            int[] position = new int[2];
-            v.getLocationOnScreen(position);
-            return position[0] + v.getWidth();
-        }
-
-        private static int getTopOfView(View v) {
-            int[] position = new int[2];
-            v.getLocationOnScreen(position);
-            return position[1];
-        }
-
-        private static int getBottomOfView(View v) {
-            int[] position = new int[2];
-            v.getLocationOnScreen(position);
-            return position[1] + v.getHeight();
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/core/CarUi.java b/car-ui-lib/src/com/android/car/ui/core/CarUi.java
deleted file mode 100644
index ad67121..0000000
--- a/car-ui-lib/src/com/android/car/ui/core/CarUi.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.core;
-
-import android.app.Activity;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.toolbar.ToolbarController;
-
-import java.lang.reflect.Method;
-
-/**
- * Public interface for general CarUi static functions.
- */
-public class CarUi {
-
-    /** Prevent instantiating this class */
-    private CarUi() {}
-
-    /**
-     * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses
-     * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true.
-     *
-     * See also: {@link #requireToolbar(Activity)}
-     */
-    @Nullable
-    public static ToolbarController getToolbar(Activity activity) {
-        BaseLayoutController controller = getBaseLayoutController(activity);
-        if (controller != null) {
-            return controller.getToolbarController();
-        }
-        return null;
-    }
-
-    /**
-     * Gets the {@link ToolbarController} for an activity. Requires that the Activity uses
-     * Theme.CarUi.WithToolbar, or otherwise sets carUiBaseLayout and carUiToolbar to true.
-     *
-     * <p>See also: {@link #getToolbar(Activity)}
-     *
-     * @throws IllegalArgumentException When the CarUi Toolbar cannot be found.
-     */
-    @NonNull
-    public static ToolbarController requireToolbar(Activity activity) {
-        ToolbarController result = getToolbar(activity);
-        if (result == null) {
-            throw new IllegalArgumentException("Activity " + activity
-                    + " does not have a CarUi Toolbar!"
-                    + " Are you using Theme.CarUi.WithToolbar?");
-        }
-
-        return result;
-    }
-
-    /**
-     * Registering a listener to receive the InsetsChanged updates instead of the Activity.
-     */
-    public static void replaceInsetsChangedListenerWith(Activity activity,
-            InsetsChangedListener listener) {
-        BaseLayoutController controller = getBaseLayoutController(activity);
-        if (controller != null) {
-            controller.replaceInsetsChangedListenerWith(listener);
-        }
-    }
-
-    /**
-     * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities
-     * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true.
-     *
-     * <p>Note that you likely don't want to use this without also using
-     * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets
-     * will automatically be applied to your Activity's content view.
-     */
-    @Nullable
-    public static Insets getInsets(Activity activity) {
-        BaseLayoutController controller = getBaseLayoutController(activity);
-        if (controller != null) {
-            return controller.getInsets();
-        }
-        return null;
-    }
-
-    /**
-     * Gets the current {@link Insets} of the given {@link Activity}. Only applies to Activities
-     * using the base layout, ie have the theme attribute "carUiBaseLayout" set to true.
-     *
-     * <p>Note that you likely don't want to use this without also using
-     * {@link com.android.car.ui.baselayout.InsetsChangedListener}, as without it the Insets
-     * will automatically be applied to your Activity's content view.
-     *
-     * @throws IllegalArgumentException When the activity is not using base layouts.
-     */
-    @NonNull
-    public static Insets requireInsets(Activity activity) {
-        Insets result = getInsets(activity);
-        if (result == null) {
-            throw new IllegalArgumentException("Activity " + activity
-                    + " does not have a base layout!"
-                    + " Are you using Theme.CarUi.WithToolbar or Theme.CarUi.NoToolbar?");
-        }
-
-        return result;
-    }
-
-    /* package */ static BaseLayoutController getBaseLayoutController(Activity activity) {
-        if (activity.getClassLoader().equals(CarUi.class.getClassLoader())) {
-            return BaseLayoutController.getBaseLayout(activity);
-        } else {
-            // Note: (b/156532465)
-            // The usage of the alternate classloader is to accommodate GMSCore.
-            // Some activities are loaded dynamically from external modules.
-            try {
-                Class baseLayoutControllerClass = activity.getClassLoader()
-                        .loadClass(BaseLayoutController.class.getName());
-                Method method = baseLayoutControllerClass
-                        .getDeclaredMethod("getBaseLayout", Activity.class);
-                return (BaseLayoutController) method.invoke(null, activity);
-            } catch (ReflectiveOperationException e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/core/CarUiInstaller.java b/car-ui-lib/src/com/android/car/ui/core/CarUiInstaller.java
deleted file mode 100644
index 7e725ae..0000000
--- a/car-ui-lib/src/com/android/car/ui/core/CarUiInstaller.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.core;
-
-import static com.android.car.ui.core.CarUi.getBaseLayoutController;
-
-import android.app.Activity;
-import android.app.Application;
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.car.ui.baselayout.Insets;
-
-import java.lang.reflect.Method;
-
-/**
- * {@link ContentProvider ContentProvider's} onCreate() methods are "called for all registered
- * content providers on the application main thread at application launch time." This means we
- * can use a content provider to register for Activity lifecycle callbacks before any activities
- * have started, for installing the CarUi base layout into all activities.
- */
-public class CarUiInstaller extends ContentProvider {
-
-    private static final String TAG = "CarUiInstaller";
-    private static final String CAR_UI_INSET_LEFT = "CAR_UI_INSET_LEFT";
-    private static final String CAR_UI_INSET_RIGHT = "CAR_UI_INSET_RIGHT";
-    private static final String CAR_UI_INSET_TOP = "CAR_UI_INSET_TOP";
-    private static final String CAR_UI_INSET_BOTTOM = "CAR_UI_INSET_BOTTOM";
-
-    @Override
-    public boolean onCreate() {
-        Context context = getContext();
-        if (context == null) {
-            Log.e(TAG, "CarUiInstaller had a null context!");
-            return false;
-        }
-        Log.i(TAG, "CarUiInstaller started for " + context.getPackageName());
-
-        Application application = (Application) context.getApplicationContext();
-        application.registerActivityLifecycleCallbacks(
-                new Application.ActivityLifecycleCallbacks() {
-                    private Insets mInsets = null;
-                    private boolean mIsActivityStartedForFirstTime = false;
-
-                    @Override
-                    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
-                        if (activity.getClassLoader()
-                                .equals(CarUiInstaller.class.getClassLoader())) {
-                            BaseLayoutController.build(activity);
-                        } else {
-                            callBaseLayoutControllerMethod("build", activity);
-                        }
-
-                        if (savedInstanceState != null) {
-                            int inset_left = savedInstanceState.getInt(CAR_UI_INSET_LEFT);
-                            int inset_top = savedInstanceState.getInt(CAR_UI_INSET_TOP);
-                            int inset_right = savedInstanceState.getInt(CAR_UI_INSET_RIGHT);
-                            int inset_bottom = savedInstanceState.getInt(CAR_UI_INSET_BOTTOM);
-                            mInsets = new Insets(inset_left, inset_top, inset_right, inset_bottom);
-                        }
-
-                        mIsActivityStartedForFirstTime = true;
-                    }
-
-                    @Override
-                    public void onActivityPostStarted(Activity activity) {
-                        BaseLayoutController controller = getBaseLayoutController(activity);
-                        if (mInsets != null && controller != null
-                                && mIsActivityStartedForFirstTime) {
-                            controller.dispatchNewInsets(mInsets);
-                            mIsActivityStartedForFirstTime = false;
-                        }
-                    }
-
-                    @Override
-                    public void onActivityStarted(Activity activity) {
-                    }
-
-                    @Override
-                    public void onActivityResumed(Activity activity) {
-                    }
-
-                    @Override
-                    public void onActivityPaused(Activity activity) {
-                    }
-
-                    @Override
-                    public void onActivityStopped(Activity activity) {
-                    }
-
-                    @Override
-                    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
-                        BaseLayoutController controller = getBaseLayoutController(activity);
-                        if (controller != null) {
-                            Insets insets = controller.getInsets();
-                            outState.putInt(CAR_UI_INSET_LEFT, insets.getLeft());
-                            outState.putInt(CAR_UI_INSET_TOP, insets.getTop());
-                            outState.putInt(CAR_UI_INSET_RIGHT, insets.getRight());
-                            outState.putInt(CAR_UI_INSET_BOTTOM, insets.getBottom());
-                        }
-                    }
-
-                    @Override
-                    public void onActivityDestroyed(Activity activity) {
-                        if (activity.getClassLoader()
-                                .equals(CarUiInstaller.class.getClassLoader())) {
-                            BaseLayoutController.destroy(activity);
-                        } else {
-                            callBaseLayoutControllerMethod("destroy", activity);
-                        }
-                    }
-                });
-
-        return true;
-    }
-
-    @Nullable
-    @Override
-    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
-            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
-        return null;
-    }
-
-    @Nullable
-    @Override
-    public String getType(@NonNull Uri uri) {
-        return null;
-    }
-
-    @Nullable
-    @Override
-    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
-        return null;
-    }
-
-    @Override
-    public int delete(@NonNull Uri uri, @Nullable String selection,
-            @Nullable String[] selectionArgs) {
-        return 0;
-    }
-
-    @Override
-    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
-            @Nullable String[] selectionArgs) {
-        return 0;
-    }
-
-    private static void callBaseLayoutControllerMethod(String methodName, Activity activity) {
-        // Note: (b/156532465)
-        // The usage of the alternate classloader is to accommodate GMSCore.
-        // Some activities are loaded dynamically from external modules.
-        try {
-            Class baseLayoutControllerClass =
-                    activity.getClassLoader()
-                            .loadClass(BaseLayoutController.class.getName());
-            Method method = baseLayoutControllerClass
-                    .getDeclaredMethod(methodName, Activity.class);
-            method.invoke(null, activity);
-        } catch (ReflectiveOperationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiDialogFragment.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiDialogFragment.java
deleted file mode 100644
index 4a61b3f..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiDialogFragment.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.TextView;
-
-import androidx.annotation.CallSuper;
-import androidx.annotation.LayoutRes;
-import androidx.annotation.NonNull;
-import androidx.fragment.app.DialogFragment;
-import androidx.preference.DialogPreference;
-
-import com.android.car.ui.utils.CarUiUtils;
-
-/**
- * Abstract base class which presents a dialog associated with a {@link
- * androidx.preference.DialogPreference}. Since the preference object may not be available during
- * fragment re-creation, the necessary information for displaying the dialog is read once during
- * the initial call to {@link #onCreate(Bundle)} and saved/restored in the saved instance state.
- * Custom subclasses should also follow this pattern.
- *
- * <p>Note: this is borrowed as-is from {@link androidx.preference.PreferenceDialogFragmentCompat}
- * with updates to formatting to match the project style and the removal of the {@link
- * DialogPreference.TargetFragment} interface requirement. See {@link PreferenceDialogFragment}
- * for a version of this class with the check preserved. Automotive applications should use
- * children of this fragment in order to launch the system themed platform {@link AlertDialog}
- * instead of the one in the support library.
- */
-
-public abstract class CarUiDialogFragment extends DialogFragment implements
-        DialogInterface.OnClickListener {
-
-    private static final String SAVE_STATE_TITLE = "CarUiDialogFragment.title";
-    private static final String SAVE_STATE_POSITIVE_TEXT = "CarUiDialogFragment.positiveText";
-    private static final String SAVE_STATE_NEGATIVE_TEXT = "CarUiDialogFragment.negativeText";
-    private static final String SAVE_STATE_MESSAGE = "CarUiDialogFragment.message";
-    private static final String SAVE_STATE_LAYOUT = "CarUiDialogFragment.layout";
-    private static final String SAVE_STATE_ICON = "CarUiDialogFragment.icon";
-
-    protected CharSequence mDialogTitle;
-    protected CharSequence mPositiveButtonText;
-    protected CharSequence mNegativeButtonText;
-    protected CharSequence mDialogMessage;
-    @LayoutRes
-    protected int mDialogLayoutRes;
-
-    protected BitmapDrawable mDialogIcon;
-
-    /** Which button was clicked. */
-    private int mWhichButtonClicked;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        if (savedInstanceState != null) {
-            mDialogTitle = savedInstanceState.getCharSequence(SAVE_STATE_TITLE);
-            mPositiveButtonText = savedInstanceState.getCharSequence(SAVE_STATE_POSITIVE_TEXT);
-            mNegativeButtonText = savedInstanceState.getCharSequence(SAVE_STATE_NEGATIVE_TEXT);
-            mDialogMessage = savedInstanceState.getCharSequence(SAVE_STATE_MESSAGE);
-            mDialogLayoutRes = savedInstanceState.getInt(SAVE_STATE_LAYOUT, 0);
-            Bitmap bitmap = savedInstanceState.getParcelable(SAVE_STATE_ICON);
-            if (bitmap != null) {
-                mDialogIcon = new BitmapDrawable(getResources(), bitmap);
-            }
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(@NonNull Bundle outState) {
-        super.onSaveInstanceState(outState);
-
-        outState.putCharSequence(SAVE_STATE_TITLE, mDialogTitle);
-        outState.putCharSequence(SAVE_STATE_POSITIVE_TEXT, mPositiveButtonText);
-        outState.putCharSequence(SAVE_STATE_NEGATIVE_TEXT, mNegativeButtonText);
-        outState.putCharSequence(SAVE_STATE_MESSAGE, mDialogMessage);
-        outState.putInt(SAVE_STATE_LAYOUT, mDialogLayoutRes);
-        if (mDialogIcon != null) {
-            outState.putParcelable(SAVE_STATE_ICON, mDialogIcon.getBitmap());
-        }
-    }
-
-    @Override
-    @NonNull
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        Context context = getActivity();
-        mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
-
-        AlertDialog.Builder builder = new AlertDialog.Builder(context)
-                .setTitle(mDialogTitle)
-                .setIcon(mDialogIcon)
-                .setPositiveButton(mPositiveButtonText, this)
-                .setNegativeButton(mNegativeButtonText, this);
-
-        View contentView = onCreateDialogView(context);
-        if (contentView != null) {
-            onBindDialogView(contentView);
-            builder.setView(contentView);
-        } else {
-            builder.setMessage(mDialogMessage);
-        }
-
-        onPrepareDialogBuilder(builder);
-
-        // Create the dialog
-        Dialog dialog = builder.create();
-        if (needInputMethod()) {
-            // Request input only after the dialog is shown. This is to prevent an issue where the
-            // dialog view collapsed the content on small displays.
-            dialog.setOnShowListener(d -> requestInputMethod(dialog));
-        }
-
-        return dialog;
-    }
-
-    /**
-     * Prepares the dialog builder to be shown when the preference is clicked. Use this to set
-     * custom properties on the dialog.
-     *
-     * <p>Do not {@link AlertDialog.Builder#create()} or {@link AlertDialog.Builder#show()}.
-     */
-    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
-    }
-
-    /**
-     * Returns whether the preference needs to display a soft input method when the dialog is
-     * displayed. Default is false. Subclasses should override this method if they need the soft
-     * input method brought up automatically.
-     *
-     * <p>Note: Ensure your subclass manually requests focus (ideally in {@link
-     * #onBindDialogView(View)}) for the input field in order to
-     * correctly attach the input method to the field.
-     */
-    protected boolean needInputMethod() {
-        return false;
-    }
-
-    /**
-     * Sets the required flags on the dialog window to enable input method window to show up.
-     */
-    private void requestInputMethod(Dialog dialog) {
-        Window window = dialog.getWindow();
-        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
-    }
-
-    /**
-     * Creates the content view for the dialog (if a custom content view is required). By default,
-     * it inflates the dialog layout resource if it is set.
-     *
-     * @return the content View for the dialog.
-     * @see DialogPreference#setLayoutResource(int)
-     */
-    protected View onCreateDialogView(Context context) {
-        int resId = mDialogLayoutRes;
-        if (resId == 0) {
-            return null;
-        }
-
-        LayoutInflater inflater = LayoutInflater.from(context);
-        return inflater.inflate(resId, null);
-    }
-
-    /**
-     * Binds views in the content View of the dialog to data.
-     *
-     * <p>Make sure to call through to the superclass implementation.
-     *
-     * @param view the content View of the dialog, if it is custom.
-     */
-    @CallSuper
-    protected void onBindDialogView(View view) {
-        View dialogMessageView = CarUiUtils.findViewByRefId(view, android.R.id.message);
-
-        if (dialogMessageView != null) {
-            CharSequence message = mDialogMessage;
-            int newVisibility = View.GONE;
-
-            if (!TextUtils.isEmpty(message)) {
-                if (dialogMessageView instanceof TextView) {
-                    ((TextView) dialogMessageView).setText(message);
-                }
-
-                newVisibility = View.VISIBLE;
-            }
-
-            if (dialogMessageView.getVisibility() != newVisibility) {
-                dialogMessageView.setVisibility(newVisibility);
-            }
-        }
-    }
-
-    @Override
-    public void onClick(DialogInterface dialog, int which) {
-        mWhichButtonClicked = which;
-    }
-
-    @Override
-    public void onDismiss(DialogInterface dialog) {
-        super.onDismiss(dialog);
-        onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
-    }
-
-    /**
-     * Called when the dialog is dismissed.
-     *
-     * @param positiveResult {@code true} if the dialog was dismissed with {@link
-     *                       DialogInterface#BUTTON_POSITIVE}.
-     */
-    protected abstract void onDialogClosed(boolean positiveResult);
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiEditTextPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiEditTextPreference.java
deleted file mode 100644
index 4480714..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiEditTextPreference.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import androidx.preference.EditTextPreference;
-
-import com.android.car.ui.R;
-
-/**
- * This class extends the base {@link EditTextPreference} class. Adds the drawable icon to
- * the preference.
- */
-public class CarUiEditTextPreference extends EditTextPreference {
-
-    private final Context mContext;
-    private boolean mShowChevron = true;
-
-    public CarUiEditTextPreference(Context context, AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        mContext = context;
-    }
-
-    public CarUiEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        mContext = context;
-    }
-
-    public CarUiEditTextPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mContext = context;
-    }
-
-    public CarUiEditTextPreference(Context context) {
-        super(context);
-        mContext = context;
-    }
-
-    @Override
-    public void onAttached() {
-        super.onAttached();
-
-        boolean allowChevron = mContext.getResources().getBoolean(
-                R.bool.car_ui_preference_show_chevron);
-
-        if (!allowChevron || !mShowChevron) {
-            return;
-        }
-
-        setWidgetLayoutResource(R.layout.car_ui_preference_chevron);
-    }
-
-    public void setShowChevron(boolean showChevron) {
-        mShowChevron = showChevron;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiMultiSelectListPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiMultiSelectListPreference.java
deleted file mode 100644
index 4752082..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiMultiSelectListPreference.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import androidx.preference.MultiSelectListPreference;
-
-import com.android.car.ui.R;
-
-/**
- * This class extends the base {@link CarUiMultiSelectListPreference} class. Adds the drawable icon
- * to the preference.
- */
-public class CarUiMultiSelectListPreference extends MultiSelectListPreference {
-
-    private final Context mContext;
-
-    public CarUiMultiSelectListPreference(Context context) {
-        super(context);
-        mContext = context;
-    }
-
-    public CarUiMultiSelectListPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mContext = context;
-    }
-
-    public CarUiMultiSelectListPreference(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        mContext = context;
-    }
-
-    public CarUiMultiSelectListPreference(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        mContext = context;
-    }
-
-    protected boolean[] getSelectedItems() {
-        return super.getSelectedItems();
-    }
-
-    @Override
-    public void onAttached() {
-        super.onAttached();
-
-        boolean showChevron = mContext.getResources().getBoolean(
-                R.bool.car_ui_preference_show_chevron);
-
-        if (!showChevron) {
-            return;
-        }
-
-        setWidgetLayoutResource(R.layout.car_ui_preference_chevron);
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
deleted file mode 100644
index 635cad9..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiPreference.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Toast;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.car.ui.R;
-import com.android.car.ui.utils.CarUiUtils;
-
-/**
- * This class extends the base {@link Preference} class. Adds the support to add a drawable icon to
- * the preference if there is one of fragment, intent or onPreferenceClickListener set.
- */
-public class CarUiPreference extends Preference implements DisabledPreferenceCallback {
-
-    private Context mContext;
-    private boolean mShowChevron;
-    private String mMessageToShowWhenDisabledPreferenceClicked;
-
-    private boolean mShouldShowRippleOnDisabledPreference;
-    private Drawable mBackground;
-    private View mPreference;
-
-    public CarUiPreference(Context context, AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        init(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    public CarUiPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, R.style.Preference_CarUi_Preference);
-    }
-
-    public CarUiPreference(Context context, AttributeSet attrs) {
-        this(context, attrs, R.attr.carUiPreferenceStyle);
-    }
-
-    public CarUiPreference(Context context) {
-        this(context, null);
-    }
-
-    public void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        mContext = context;
-
-        TypedArray a = getContext().obtainStyledAttributes(
-                attrs,
-                R.styleable.CarUiPreference,
-                defStyleAttr,
-                defStyleRes);
-
-        mShowChevron = a.getBoolean(R.styleable.CarUiPreference_showChevron, true);
-        mShouldShowRippleOnDisabledPreference = a.getBoolean(
-                R.styleable.CarUiPreference_showRippleOnDisabledPreference, false);
-    }
-
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        boolean viewEnabled = isEnabled();
-        mPreference = holder.itemView;
-        mBackground = CarUiUtils.setPreferenceViewEnabled(viewEnabled, holder.itemView, mBackground,
-                mShouldShowRippleOnDisabledPreference);
-    }
-
-    @Override
-    public void onAttached() {
-        super.onAttached();
-
-        boolean allowChevron = mContext.getResources().getBoolean(
-                R.bool.car_ui_preference_show_chevron);
-
-        if (!allowChevron || !mShowChevron) {
-            return;
-        }
-
-        if (getOnPreferenceClickListener() != null || getIntent() != null
-                || getFragment() != null) {
-            setWidgetLayoutResource(R.layout.car_ui_preference_chevron);
-        }
-    }
-
-    /**
-     * This is similar to {@link Preference#performClick()} with the only difference that we do not
-     * return when view is not enabled.
-     */
-    @Override
-    public void performClick() {
-        if (isEnabled()) {
-            super.performClick();
-        } else if (mMessageToShowWhenDisabledPreferenceClicked != null
-                && !mMessageToShowWhenDisabledPreferenceClicked.isEmpty()) {
-            Toast.makeText(mContext, mMessageToShowWhenDisabledPreferenceClicked,
-                    Toast.LENGTH_LONG).show();
-        }
-    }
-
-    public void setShowChevron(boolean showChevron) {
-        mShowChevron = showChevron;
-    }
-
-    /**
-     * Sets the ripple on the disabled preference.
-     */
-    @Override
-    public void setShouldShowRippleOnDisabledPreference(boolean showRipple) {
-        mShouldShowRippleOnDisabledPreference = showRipple;
-        CarUiUtils.updateRippleStateOnDisabledPreference(isEnabled(),
-                mShouldShowRippleOnDisabledPreference, mBackground, mPreference);
-    }
-
-    @Override
-    public void setMessageToShowWhenDisabledPreferenceClicked(String message) {
-        mMessageToShowWhenDisabledPreferenceClicked = message;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/CarUiSwitchPreference.java b/car-ui-lib/src/com/android/car/ui/preference/CarUiSwitchPreference.java
deleted file mode 100644
index 1ccadf8..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/CarUiSwitchPreference.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2020 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.car.ui.preference;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Toast;
-
-import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
-
-import com.android.car.ui.R;
-import com.android.car.ui.utils.CarUiUtils;
-
-/**
- * This class extends the base {@link SwitchPreference} class. Adds the functionality to show
- * message when preference is disabled.
- */
-public class CarUiSwitchPreference extends SwitchPreference implements DisabledPreferenceCallback {
-
-    private String mMessageToShowWhenDisabledPreferenceClicked;
-
-    private boolean mShouldShowRippleOnDisabledPreference;
-    private Drawable mBackground;
-    private View mPreference;
-    private Context mContext;
-
-    public CarUiSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        init(context, attrs);
-    }
-
-    public CarUiSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        init(context, attrs);
-    }
-
-    public CarUiSwitchPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init(context, attrs);
-    }
-
-    public CarUiSwitchPreference(Context context) {
-        super(context);
-        init(context, null);
-    }
-
-    private void init(Context context, AttributeSet attrs) {
-        mContext = context;
-        TypedArray preferenceAttributes = getContext().obtainStyledAttributes(attrs,
-                R.styleable.CarUiPreference);
-        mShouldShowRippleOnDisabledPreference = preferenceAttributes.getBoolean(
-                R.styleable.CarUiPreference_showRippleOnDisabledPreference, false);
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        mPreference = holder.itemView;
-        mBackground = CarUiUtils.setPreferenceViewEnabled(isEnabled(), holder.itemView, mBackground,
-                mShouldShowRippleOnDisabledPreference);
-    }
-
-    /**
-     * This is similar to {@link Preference#performClick()} with the only difference that we do not
-     * return when view is not enabled.
-     */
-    @Override
-    public void performClick() {
-        if (isEnabled()) {
-            super.performClick();
-        } else if (mMessageToShowWhenDisabledPreferenceClicked != null
-                && !mMessageToShowWhenDisabledPreferenceClicked.isEmpty()) {
-            Toast.makeText(mContext, mMessageToShowWhenDisabledPreferenceClicked,
-                    Toast.LENGTH_LONG).show();
-        }
-    }
-
-    /**
-     * Sets the ripple on the disabled preference.
-     */
-    @Override
-    public void setShouldShowRippleOnDisabledPreference(boolean showRipple) {
-        mShouldShowRippleOnDisabledPreference = showRipple;
-        CarUiUtils.updateRippleStateOnDisabledPreference(isEnabled(),
-                mShouldShowRippleOnDisabledPreference, mBackground, mPreference);
-    }
-
-    @Override
-    public void setMessageToShowWhenDisabledPreferenceClicked(String message) {
-        mMessageToShowWhenDisabledPreferenceClicked = message;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/DisabledPreferenceCallback.java b/car-ui-lib/src/com/android/car/ui/preference/DisabledPreferenceCallback.java
deleted file mode 100644
index b7a12bc..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/DisabledPreferenceCallback.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2020 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.car.ui.preference;
-
-/**
- * Interface for preferences to handle clicks when its disabled.
- */
-public interface DisabledPreferenceCallback {
-
-    /**
-     * Sets if the ripple effect should be shown on disabled preference.
-     */
-    default void setShouldShowRippleOnDisabledPreference(boolean showRipple) {}
-
-    /**
-     * Sets the message to be displayed when the disabled preference is clicked.
-     */
-    default void setMessageToShowWhenDisabledPreferenceClicked(String message) {}
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java b/car-ui-lib/src/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java
deleted file mode 100644
index 7df5228..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/EditTextPreferenceDialogFragment.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.text.InputType;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.preference.EditTextPreference;
-
-import com.android.car.ui.utils.CarUiUtils;
-
-/**
- * Presents a dialog with an {@link EditText} associated with an {@link EditTextPreference}.
- *
- * <p>Note: this is borrowed as-is from androidx.preference.EditTextPreferenceDialogFragmentCompat
- * with updates to formatting to match the project style. Automotive applications should use this
- * implementations in order to launch the system themed platform {@link AlertDialog} instead of the
- * one in the support library.
- */
-public class EditTextPreferenceDialogFragment extends PreferenceDialogFragment implements
-        TextView.OnEditorActionListener {
-
-    private static final String SAVE_STATE_TEXT = "EditTextPreferenceDialogFragment.text";
-
-    private EditText mEditText;
-    private CharSequence mText;
-    private boolean mAllowEnterToSubmit = true;
-
-    /**
-     * Returns a new instance of {@link EditTextPreferenceDialogFragment} for the {@link
-     * EditTextPreference} with the given {@code key}.
-     */
-    public static EditTextPreferenceDialogFragment newInstance(String key) {
-        EditTextPreferenceDialogFragment fragment =
-                new EditTextPreferenceDialogFragment();
-        Bundle b = new Bundle(/* capacity= */ 1);
-        b.putString(ARG_KEY, key);
-        fragment.setArguments(b);
-        return fragment;
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        if (savedInstanceState == null) {
-            mText = getEditTextPreference().getText();
-        } else {
-            mText = savedInstanceState.getCharSequence(SAVE_STATE_TEXT);
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(@NonNull Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putCharSequence(SAVE_STATE_TEXT, mText);
-    }
-
-    @Override
-    protected void onBindDialogView(View view) {
-        super.onBindDialogView(view);
-
-        mEditText = CarUiUtils.findViewByRefId(view, android.R.id.edit);
-
-        if (mEditText == null) {
-            throw new IllegalStateException(
-                    "Dialog view must contain an EditText with id @android:id/edit");
-        }
-
-        mEditText.requestFocus();
-        mEditText.setText(mText);
-        mEditText.setInputType(InputType.TYPE_CLASS_TEXT);
-        mEditText.setImeOptions(EditorInfo.IME_ACTION_DONE);
-        mEditText.setOnEditorActionListener(this);
-
-        // Place cursor at the end
-        mEditText.setSelection(mEditText.getText().length());
-    }
-
-    private EditTextPreference getEditTextPreference() {
-        return (EditTextPreference) getPreference();
-    }
-
-    @Override
-    protected boolean needInputMethod() {
-        return true;
-    }
-
-    @Override
-    protected void onDialogClosed(boolean positiveResult) {
-        if (positiveResult) {
-            String value = mEditText.getText().toString();
-            if (getEditTextPreference().callChangeListener(value)) {
-                getEditTextPreference().setText(value);
-            }
-        }
-    }
-
-    /** Allows enabling and disabling the ability to press enter to dismiss the dialog. */
-    public void setAllowEnterToSubmit(boolean isAllowed) {
-        mAllowEnterToSubmit = isAllowed;
-    }
-
-    /** Allows verifying if enter to submit is currently enabled. */
-    public boolean getAllowEnterToSubmit() {
-        return mAllowEnterToSubmit;
-    }
-
-    @Override
-    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
-        if (actionId == EditorInfo.IME_ACTION_DONE && mAllowEnterToSubmit) {
-            CharSequence newValue = v.getText();
-
-            getEditTextPreference().callChangeListener(newValue);
-            dismiss();
-
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
deleted file mode 100644
index 0a4ddde..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/ListPreferenceFragment.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import static com.android.car.ui.preference.PreferenceDialogFragment.ARG_KEY;
-
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.preference.DialogPreference;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-
-import com.android.car.ui.R;
-import com.android.car.ui.recyclerview.CarUiContentListItem;
-import com.android.car.ui.recyclerview.CarUiListItem;
-import com.android.car.ui.recyclerview.CarUiListItemAdapter;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.utils.CarUiUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A fragment that provides a layout with a list of options associated with a {@link
- * ListPreference}.
- */
-public class ListPreferenceFragment extends Fragment {
-
-    private ListPreference mPreference;
-    private CarUiContentListItem mSelectedItem;
-    private List<CarUiListItem> mListItems;
-    private CharSequence[] mEntryValues;
-
-    /**
-     * Returns a new instance of {@link ListPreferenceFragment} for the {@link ListPreference} with
-     * the given {@code key}.
-     */
-    static ListPreferenceFragment newInstance(String key) {
-        ListPreferenceFragment fragment = new ListPreferenceFragment();
-        Bundle b = new Bundle(/* capacity= */ 1);
-        b.putString(ARG_KEY, key);
-        fragment.setArguments(b);
-        return fragment;
-    }
-
-    @Nullable
-    @Override
-    public View onCreateView(
-            @NonNull LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.car_ui_list_preference, container, false);
-    }
-
-    @Override
-    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        final CarUiRecyclerView carUiRecyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
-        final Toolbar toolbar = CarUiUtils.requireViewByRefId(view, R.id.toolbar);
-
-        carUiRecyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
-        toolbar.registerToolbarHeightChangeListener(newHeight -> {
-            if (carUiRecyclerView.getPaddingTop() == newHeight) {
-                return;
-            }
-
-            int oldHeight = carUiRecyclerView.getPaddingTop();
-            carUiRecyclerView.setPadding(0, newHeight, 0, 0);
-            carUiRecyclerView.scrollBy(0, oldHeight - newHeight);
-        });
-
-        carUiRecyclerView.setClipToPadding(false);
-        mPreference = getListPreference();
-        toolbar.setTitle(mPreference.getTitle());
-
-        CharSequence[] entries = mPreference.getEntries();
-        mEntryValues = mPreference.getEntryValues();
-
-        if (entries == null || mEntryValues == null) {
-            throw new IllegalStateException(
-                    "ListPreference requires an entries array and an entryValues array.");
-        }
-
-        if (entries.length != mEntryValues.length) {
-            throw new IllegalStateException(
-                    "ListPreference entries array length does not match entryValues array length.");
-        }
-
-        int selectedEntryIndex = mPreference.findIndexOfValue(mPreference.getValue());
-        mListItems = new ArrayList<>();
-        CarUiListItemAdapter adapter = new CarUiListItemAdapter(mListItems);
-
-        for (int i = 0; i < entries.length; i++) {
-            String entry = entries[i].toString();
-            CarUiContentListItem item = new CarUiContentListItem(
-                    CarUiContentListItem.Action.RADIO_BUTTON);
-            item.setTitle(entry);
-
-            if (i == selectedEntryIndex) {
-                item.setChecked(true);
-                mSelectedItem = item;
-            }
-
-            item.setOnCheckedChangeListener((listItem, isChecked) -> {
-                if (mSelectedItem != null) {
-                    mSelectedItem.setChecked(false);
-                    adapter.notifyItemChanged(mListItems.indexOf(mSelectedItem));
-                }
-                mSelectedItem = listItem;
-            });
-
-            mListItems.add(item);
-        }
-
-        carUiRecyclerView.setAdapter(adapter);
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-        updatePreference();
-    }
-
-    private void updatePreference() {
-        if (mSelectedItem != null) {
-            int selectedIndex = mListItems.indexOf(mSelectedItem);
-            String entryValue = mEntryValues[selectedIndex].toString();
-
-            if (mPreference.callChangeListener(entryValue)) {
-                mPreference.setValue(entryValue);
-            }
-        }
-    }
-
-    private ListPreference getListPreference() {
-        if (getArguments() == null) {
-            throw new IllegalStateException("Preference arguments cannot be null");
-        }
-
-        String key = getArguments().getString(ARG_KEY);
-        DialogPreference.TargetFragment fragment =
-                (DialogPreference.TargetFragment) getTargetFragment();
-
-        if (key == null) {
-            throw new IllegalStateException(
-                    "ListPreference key not found in Fragment arguments");
-        }
-
-        if (fragment == null) {
-            throw new IllegalStateException(
-                    "Target fragment must be registered before displaying ListPreference "
-                            + "screen.");
-        }
-
-        Preference preference = fragment.findPreference(key);
-
-        if (!(preference instanceof ListPreference)) {
-            throw new IllegalStateException(
-                    "Cannot use ListPreferenceFragment with a preference that is not of type "
-                            + "ListPreference");
-        }
-
-        return (ListPreference) preference;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
deleted file mode 100644
index 8427c5f..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import static com.android.car.ui.preference.PreferenceDialogFragment.ARG_KEY;
-
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.preference.DialogPreference;
-import androidx.preference.Preference;
-
-import com.android.car.ui.R;
-import com.android.car.ui.recyclerview.CarUiContentListItem;
-import com.android.car.ui.recyclerview.CarUiListItem;
-import com.android.car.ui.recyclerview.CarUiListItemAdapter;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.utils.CarUiUtils;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A fragment that provides a layout with a list of options associated with a {@link
- * CarUiMultiSelectListPreference}.
- */
-public class MultiSelectListPreferenceFragment extends Fragment {
-
-    private CarUiMultiSelectListPreference mPreference;
-    private Set<String> mNewValues;
-
-    /**
-     * Returns a new instance of {@link MultiSelectListPreferenceFragment} for the {@link
-     * CarUiMultiSelectListPreference} with the given {@code key}.
-     */
-    static MultiSelectListPreferenceFragment newInstance(String key) {
-        MultiSelectListPreferenceFragment fragment = new MultiSelectListPreferenceFragment();
-        Bundle b = new Bundle(/* capacity= */ 1);
-        b.putString(ARG_KEY, key);
-        fragment.setArguments(b);
-        return fragment;
-    }
-
-    @Nullable
-    @Override
-    public View onCreateView(
-            @NonNull LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.car_ui_list_preference, container, false);
-    }
-
-    @Override
-    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        final CarUiRecyclerView recyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
-        final Toolbar toolbar = CarUiUtils.requireViewByRefId(view, R.id.toolbar);
-
-        recyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
-        toolbar.registerToolbarHeightChangeListener(newHeight -> {
-            if (recyclerView.getPaddingTop() == newHeight) {
-                return;
-            }
-
-            int oldHeight = recyclerView.getPaddingTop();
-            recyclerView.setPadding(0, newHeight, 0, 0);
-            recyclerView.scrollBy(0, oldHeight - newHeight);
-        });
-
-        mPreference = getPreference();
-
-        recyclerView.setClipToPadding(false);
-        toolbar.setTitle(mPreference.getTitle());
-
-        mNewValues = new HashSet<>(mPreference.getValues());
-        CharSequence[] entries = mPreference.getEntries();
-        CharSequence[] entryValues = mPreference.getEntryValues();
-
-        if (entries == null || entryValues == null) {
-            throw new IllegalStateException(
-                    "MultiSelectListPreference requires an entries array and an entryValues array"
-                            + ".");
-        }
-
-        if (entries.length != entryValues.length) {
-            throw new IllegalStateException(
-                    "MultiSelectListPreference entries array length does not match entryValues "
-                            + "array length.");
-        }
-
-        List<CarUiListItem> listItems = new ArrayList<>();
-        boolean[] selectedItems = mPreference.getSelectedItems();
-
-        for (int i = 0; i < entries.length; i++) {
-            String entry = entries[i].toString();
-            String entryValue = entryValues[i].toString();
-            CarUiContentListItem item = new CarUiContentListItem(
-                    CarUiContentListItem.Action.CHECK_BOX);
-            item.setTitle(entry);
-            item.setChecked(selectedItems[i]);
-            item.setOnCheckedChangeListener((listItem, isChecked) -> {
-                if (isChecked) {
-                    mNewValues.add(entryValue);
-                } else {
-                    mNewValues.remove(entryValue);
-                }
-            });
-
-            listItems.add(item);
-        }
-
-        CarUiListItemAdapter adapter = new CarUiListItemAdapter(listItems);
-        recyclerView.setAdapter(adapter);
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-        updatePreference();
-    }
-
-    private void updatePreference() {
-        if (mPreference.callChangeListener(mNewValues)) {
-            mPreference.setValues(mNewValues);
-        }
-    }
-
-    private CarUiMultiSelectListPreference getPreference() {
-        if (getArguments() == null) {
-            throw new IllegalStateException("Preference arguments cannot be null");
-        }
-
-        String key = getArguments().getString(ARG_KEY);
-        DialogPreference.TargetFragment fragment =
-                (DialogPreference.TargetFragment) getTargetFragment();
-
-        if (key == null) {
-            throw new IllegalStateException(
-                    "MultiSelectListPreference key not found in Fragment arguments");
-        }
-
-        if (fragment == null) {
-            throw new IllegalStateException(
-                    "Target fragment must be registered before displaying "
-                            + "MultiSelectListPreference screen.");
-        }
-
-        Preference preference = fragment.findPreference(key);
-
-        if (!(preference instanceof CarUiMultiSelectListPreference)) {
-            throw new IllegalStateException(
-                    "Cannot use MultiSelectListPreferenceFragment with a preference that is "
-                            + "not of type CarUiMultiSelectListPreference");
-        }
-
-        return (CarUiMultiSelectListPreference) preference;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/PreferenceDialogFragment.java b/car-ui-lib/src/com/android/car/ui/preference/PreferenceDialogFragment.java
deleted file mode 100644
index 8b2e79e..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/PreferenceDialogFragment.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-
-import androidx.fragment.app.Fragment;
-import androidx.preference.DialogPreference;
-import androidx.preference.PreferenceFragmentCompat;
-
-/**
- * Abstract base class which presents a dialog associated with a {@link
- * androidx.preference.DialogPreference}. Since the preference object may not be available during
- * fragment re-creation, the necessary information for displaying the dialog is read once during
- * the initial call to {@link #onCreate(Bundle)} and saved/restored in the saved instance state.
- * Custom subclasses should also follow this pattern.
- *
- * <p>Note: this has the same functionality and interface as {@link
- * androidx.preference.PreferenceDialogFragmentCompat} with updates to formatting to match the
- * project style. This class preserves the {@link DialogPreference.TargetFragment} interface
- * requirement that was removed in {@link CarUiDialogFragment}. Automotive applications should use
- * children of this fragment in order to launch the system themed platform {@link AlertDialog}
- * instead of the one in the support library.
- */
-public abstract class PreferenceDialogFragment extends CarUiDialogFragment implements
-        DialogInterface.OnClickListener {
-
-    protected static final String ARG_KEY = "key";
-
-    private DialogPreference mPreference;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        Fragment rawFragment = getTargetFragment();
-        if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
-            throw new IllegalStateException(
-                    "Target fragment must implement TargetFragment interface");
-        }
-
-        DialogPreference.TargetFragment fragment =
-                (DialogPreference.TargetFragment) rawFragment;
-
-        String key = getArguments().getString(ARG_KEY);
-        if (savedInstanceState == null) {
-            mPreference = (DialogPreference) fragment.findPreference(key);
-            mDialogTitle = mPreference.getDialogTitle();
-            mPositiveButtonText = mPreference.getPositiveButtonText();
-            mNegativeButtonText = mPreference.getNegativeButtonText();
-            mDialogMessage = mPreference.getDialogMessage();
-            mDialogLayoutRes = mPreference.getDialogLayoutResource();
-
-            Drawable icon = mPreference.getDialogIcon();
-            if (icon == null || icon instanceof BitmapDrawable) {
-                mDialogIcon = (BitmapDrawable) icon;
-            } else {
-                Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(),
-                        icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
-                Canvas canvas = new Canvas(bitmap);
-                icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
-                icon.draw(canvas);
-                mDialogIcon = new BitmapDrawable(getResources(), bitmap);
-            }
-        }
-    }
-
-    /**
-     * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has
-     * been called on the {@link PreferenceFragmentCompat} which launched this dialog.
-     *
-     * @return the {@link DialogPreference} associated with this dialog.
-     */
-    public DialogPreference getPreference() {
-        if (mPreference == null) {
-            String key = getArguments().getString(ARG_KEY);
-            DialogPreference.TargetFragment fragment =
-                    (DialogPreference.TargetFragment) getTargetFragment();
-            mPreference = (DialogPreference) fragment.findPreference(key);
-        }
-        return mPreference;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/preference/PreferenceFragment.java b/car-ui-lib/src/com/android/car/ui/preference/PreferenceFragment.java
deleted file mode 100644
index 260cf6f..0000000
--- a/car-ui-lib/src/com/android/car/ui/preference/PreferenceFragment.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.preference;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.Pair;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.DialogFragment;
-import androidx.fragment.app.Fragment;
-import androidx.preference.DialogPreference;
-import androidx.preference.DropDownPreference;
-import androidx.preference.EditTextPreference;
-import androidx.preference.ListPreference;
-import androidx.preference.MultiSelectListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.core.CarUi;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.toolbar.ToolbarController;
-import com.android.car.ui.utils.CarUiUtils;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A PreferenceFragmentCompat is the entry point to using the Preference library.
- *
- * <p>Using this fragment will replace regular Preferences with CarUi equivalents. Because of this,
- * certain properties that cannot be read out of Preferences will be lost upon calling
- * {@link #setPreferenceScreen(PreferenceScreen)}. These include the preference viewId,
- * defaultValue, and enabled state.
- */
-public abstract class PreferenceFragment extends PreferenceFragmentCompat implements
-        InsetsChangedListener {
-
-    private static final String TAG = "CarUiPreferenceFragment";
-    private static final String DIALOG_FRAGMENT_TAG =
-            "com.android.car.ui.PreferenceFragment.DIALOG";
-
-    @Override
-    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-
-        ToolbarController baseLayoutToolbar = CarUi.getToolbar(getActivity());
-        if (baseLayoutToolbar != null) {
-            baseLayoutToolbar.setState(Toolbar.State.SUBPAGE);
-            if (getPreferenceScreen() != null) {
-                baseLayoutToolbar.setTitle(getPreferenceScreen().getTitle());
-            }
-        }
-
-        // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
-        final RecyclerView recyclerView = CarUiUtils.findViewByRefId(view, R.id.recycler_view);
-        final Toolbar toolbar = CarUiUtils.findViewByRefId(view, R.id.toolbar);
-        if (recyclerView == null || toolbar == null) {
-            return;
-        }
-
-        recyclerView.setPadding(0, toolbar.getHeight(), 0, 0);
-        toolbar.registerToolbarHeightChangeListener(newHeight -> {
-            if (recyclerView.getPaddingTop() == newHeight) {
-                return;
-            }
-
-            int oldHeight = recyclerView.getPaddingTop();
-            recyclerView.setPadding(0, newHeight, 0, 0);
-            recyclerView.scrollBy(0, oldHeight - newHeight);
-        });
-
-        recyclerView.setClipToPadding(false);
-        if (getPreferenceScreen() != null) {
-            toolbar.setTitle(getPreferenceScreen().getTitle());
-        }
-    }
-
-    @Override
-    public void onCarUiInsetsChanged(Insets insets) {
-        View view = requireView();
-        CarUiUtils.requireViewByRefId(view, R.id.recycler_view)
-                .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        CarUiUtils.requireViewByRefId(view.getRootView(), android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
-    }
-
-    /**
-     * Called when a preference in the tree requests to display a dialog. Subclasses should override
-     * this method to display custom dialogs or to handle dialogs for custom preference classes.
-     *
-     * <p>Note: this is borrowed as-is from androidx.preference.PreferenceFragmentCompat with
-     * updates to launch Car UI library {@link DialogFragment} instead of the ones in the
-     * support library.
-     *
-     * @param preference The {@link Preference} object requesting the dialog
-     */
-    @Override
-    public void onDisplayPreferenceDialog(Preference preference) {
-
-        if (getActivity() instanceof OnPreferenceDisplayDialogCallback
-                && ((OnPreferenceDisplayDialogCallback) getActivity())
-                .onPreferenceDisplayDialog(this, preference)) {
-            return;
-        }
-
-        // check if dialog is already showing
-        if (requireFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
-            return;
-        }
-
-        final Fragment f;
-        if (preference instanceof EditTextPreference) {
-            f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
-        } else if (preference instanceof ListPreference) {
-            f = ListPreferenceFragment.newInstance(preference.getKey());
-        } else if (preference instanceof MultiSelectListPreference) {
-            f = MultiSelectListPreferenceFragment.newInstance(preference.getKey());
-        } else {
-            throw new IllegalArgumentException(
-                    "Cannot display dialog for an unknown Preference type: "
-                            + preference.getClass().getSimpleName()
-                            + ". Make sure to implement onPreferenceDisplayDialog() to handle "
-                            + "displaying a custom dialog for this Preference.");
-        }
-
-        f.setTargetFragment(this, 0);
-
-        if (f instanceof DialogFragment) {
-            ((DialogFragment) f).show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
-        } else {
-            if (getActivity() == null) {
-                throw new IllegalStateException(
-                        "Preference fragment is not attached to an Activity.");
-            }
-
-            if (getView() == null) {
-                throw new IllegalStateException(
-                        "Preference fragment must have a layout.");
-            }
-
-            Context context = getContext();
-            getActivity().getSupportFragmentManager().beginTransaction()
-                    .setCustomAnimations(
-                            CarUiUtils.getAttrResourceId(context,
-                                    android.R.attr.fragmentOpenEnterAnimation),
-                            CarUiUtils.getAttrResourceId(context,
-                                    android.R.attr.fragmentOpenExitAnimation),
-                            CarUiUtils.getAttrResourceId(context,
-                                    android.R.attr.fragmentCloseEnterAnimation),
-                            CarUiUtils.getAttrResourceId(context,
-                                    android.R.attr.fragmentCloseExitAnimation))
-                    .replace(((ViewGroup) getView().getParent()).getId(), f)
-                    .addToBackStack(null)
-                    .commit();
-        }
-    }
-
-    /**
-     * This override of setPreferenceScreen replaces preferences with their CarUi versions first.
-     */
-    @Override
-    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
-        // We do a search of the tree and every time we see a PreferenceGroup we remove
-        // all it's children, replace them with CarUi versions, and then re-add them
-
-        Map<Preference, String> dependencies = new HashMap<>();
-        List<Preference> children = new ArrayList<>();
-
-        // Stack of preferences to process
-        Deque<Preference> stack = new ArrayDeque<>();
-        stack.addFirst(preferenceScreen);
-
-        while (!stack.isEmpty()) {
-            Preference preference = stack.removeFirst();
-
-            if (preference instanceof PreferenceGroup) {
-                PreferenceGroup pg = (PreferenceGroup) preference;
-
-                children.clear();
-                for (int i = 0; i < pg.getPreferenceCount(); i++) {
-                    children.add(pg.getPreference(i));
-                }
-
-                pg.removeAll();
-
-                for (Preference child : children) {
-                    Preference replacement = getReplacementFor(child);
-
-                    dependencies.put(replacement, child.getDependency());
-                    pg.addPreference(replacement);
-                    stack.addFirst(replacement);
-                }
-            }
-        }
-
-        super.setPreferenceScreen(preferenceScreen);
-
-        // Set the dependencies after all the swapping has been done and they've been
-        // associated with this fragment, or we could potentially fail to find preferences
-        // or use the wrong preferenceManager
-        for (Map.Entry<Preference, String> entry : dependencies.entrySet()) {
-            entry.getKey().setDependency(entry.getValue());
-        }
-    }
-
-    // Mapping from regular preferences to CarUi preferences.
-    // Order is important, subclasses must come before their base classes
-    private static final List<Pair<Class<? extends Preference>, Class<? extends Preference>>>
-            sPreferenceMapping = Arrays.asList(
-            new Pair<>(DropDownPreference.class, CarUiDropDownPreference.class),
-            new Pair<>(ListPreference.class, CarUiListPreference.class),
-            new Pair<>(MultiSelectListPreference.class, CarUiMultiSelectListPreference.class),
-            new Pair<>(EditTextPreference.class, CarUiEditTextPreference.class),
-            new Pair<>(SwitchPreference.class, CarUiSwitchPreference.class),
-            new Pair<>(Preference.class, CarUiPreference.class)
-    );
-
-    /**
-     * Gets the CarUi version of the passed in preference. If there is no suitable replacement, this
-     * method will return it's input.
-     *
-     * <p>When given a Preference that extends a replaceable preference, we log a warning instead
-     * of replacing it so that we don't remove any functionality.
-     */
-    private static Preference getReplacementFor(Preference preference) {
-        Class<? extends Preference> clazz = preference.getClass();
-
-        for (Pair<Class<? extends Preference>, Class<? extends Preference>> replacement
-                : sPreferenceMapping) {
-            Class<? extends Preference> source = replacement.first;
-            Class<? extends Preference> target = replacement.second;
-            if (source.isAssignableFrom(clazz)) {
-                if (clazz == source) {
-                    try {
-                        return copyPreference(preference, (Preference) target
-                                .getDeclaredConstructor(Context.class)
-                                .newInstance(preference.getContext()));
-                    } catch (ReflectiveOperationException e) {
-                        throw new RuntimeException(e);
-                    }
-                } else if (clazz == target || source == Preference.class) {
-                    // Don't warn about subclasses of Preference because there are many legitimate
-                    // uses for non-carui Preference subclasses, like Preference groups.
-                    return preference;
-                } else {
-                    Log.w(TAG, "Subclass of " + source.getSimpleName() + " was used, "
-                            + "preventing us from substituting it with " + target.getSimpleName());
-                    return preference;
-                }
-            }
-        }
-
-        return preference;
-    }
-
-    /**
-     * Copies all the properties of one preference to another.
-     *
-     * @return the {@code to} parameter
-     */
-    private static Preference copyPreference(Preference from, Preference to) {
-        // viewId and defaultValue don't have getters
-        // isEnabled() is not completely symmetrical with setEnabled(), so we can't use it.
-        to.setTitle(from.getTitle());
-        to.setOnPreferenceClickListener(from.getOnPreferenceClickListener());
-        to.setOnPreferenceChangeListener(from.getOnPreferenceChangeListener());
-        to.setIcon(from.getIcon());
-        to.setFragment(from.getFragment());
-        to.setIntent(from.getIntent());
-        to.setKey(from.getKey());
-        to.setOrder(from.getOrder());
-        to.setSelectable(from.isSelectable());
-        to.setPersistent(from.isPersistent());
-        to.setIconSpaceReserved(from.isIconSpaceReserved());
-        to.setWidgetLayoutResource(from.getWidgetLayoutResource());
-        to.setPreferenceDataStore(from.getPreferenceDataStore());
-        to.setShouldDisableView(from.getShouldDisableView());
-        to.setSingleLineTitle(from.isSingleLineTitle());
-        to.setVisible(from.isVisible());
-        to.setLayoutResource(from.getLayoutResource());
-        to.setCopyingEnabled(from.isCopyingEnabled());
-
-        if (from.getSummaryProvider() != null) {
-            to.setSummaryProvider(from.getSummaryProvider());
-        } else {
-            to.setSummary(from.getSummary());
-        }
-
-        if (from.peekExtras() != null) {
-            to.getExtras().putAll(from.peekExtras());
-        }
-
-        if (from instanceof DialogPreference) {
-            DialogPreference fromDialog = (DialogPreference) from;
-            DialogPreference toDialog = (DialogPreference) to;
-            toDialog.setDialogTitle(fromDialog.getDialogTitle());
-            toDialog.setDialogIcon(fromDialog.getDialogIcon());
-            toDialog.setDialogMessage(fromDialog.getDialogMessage());
-            toDialog.setDialogLayoutResource(fromDialog.getDialogLayoutResource());
-            toDialog.setNegativeButtonText(fromDialog.getNegativeButtonText());
-            toDialog.setPositiveButtonText(fromDialog.getPositiveButtonText());
-        }
-
-        // DropDownPreference extends ListPreference and doesn't add any extra api surface,
-        // so we don't need a case for it
-        if (from instanceof ListPreference) {
-            ListPreference fromList = (ListPreference) from;
-            ListPreference toList = (ListPreference) to;
-            toList.setEntries(fromList.getEntries());
-            toList.setEntryValues(fromList.getEntryValues());
-            toList.setValue(fromList.getValue());
-        } else if (from instanceof EditTextPreference) {
-            EditTextPreference fromText = (EditTextPreference) from;
-            EditTextPreference toText = (EditTextPreference) to;
-            toText.setText(fromText.getText());
-        } else if (from instanceof MultiSelectListPreference) {
-            MultiSelectListPreference fromMulti = (MultiSelectListPreference) from;
-            MultiSelectListPreference toMulti = (MultiSelectListPreference) to;
-            toMulti.setEntries(fromMulti.getEntries());
-            toMulti.setEntryValues(fromMulti.getEntryValues());
-            toMulti.setValues(fromMulti.getValues());
-        }
-
-        // We don't need to add checks for things that we will never replace,
-        // like PreferenceGroup or CheckBoxPreference
-
-        return to;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
deleted file mode 100644
index 3fbe006..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiContentListItem.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-/**
- * Definition of list items that can be inserted into {@link CarUiListItemAdapter}.
- */
-public class CarUiContentListItem extends CarUiListItem {
-
-    /**
-     * Callback to be invoked when the checked state of a list item changed.
-     */
-    public interface OnCheckedChangeListener {
-        /**
-         * Called when the checked state of a list item has changed.
-         *
-         * @param item      whose checked state changed.
-         * @param isChecked new checked state of list item.
-         */
-        void onCheckedChanged(@NonNull CarUiContentListItem item, boolean isChecked);
-    }
-
-    /**
-     * Callback to be invoked when an item is clicked.
-     */
-    public interface OnClickListener {
-        /**
-         * Called when the item has been clicked.
-         *
-         * @param item whose checked state changed.
-         */
-        void onClick(@NonNull CarUiContentListItem item);
-    }
-
-    public enum IconType {
-        /**
-         * For an icon type of CONTENT, the primary icon is a larger than {@code STANDARD}.
-         */
-        CONTENT,
-        /**
-         * For an icon type of STANDARD, the primary icon is the standard size.
-         */
-        STANDARD,
-        /**
-         * For an icon type of AVATAR, the primary icon is masked to provide an icon with a modified
-         * shape.
-         */
-        AVATAR
-    }
-
-    /**
-     * Enum of secondary action types of a list item.
-     */
-    public enum Action {
-        /**
-         * For an action value of NONE, no action element is shown for a list item.
-         */
-        NONE,
-        /**
-         * For an action value of SWITCH, a switch is shown for the action element of the list item.
-         */
-        SWITCH,
-        /**
-         * For an action value of CHECK_BOX, a checkbox is shown for the action element of the list
-         * item.
-         */
-        CHECK_BOX,
-        /**
-         * For an action value of RADIO_BUTTON, a radio button is shown for the action element of
-         * the list item.
-         */
-        RADIO_BUTTON,
-        /**
-         * For an action value of ICON, an icon is shown for the action element of the list item.
-         */
-        ICON
-    }
-
-    private Drawable mIcon;
-    @Nullable
-    private Drawable mSupplementalIcon;
-    private CharSequence mTitle;
-    private CharSequence mBody;
-    private Action mAction;
-    private IconType mPrimaryIconType;
-    private boolean mIsActionDividerVisible;
-    private boolean mIsChecked;
-    private boolean mIsEnabled = true;
-    private boolean mIsActivated;
-    private OnClickListener mOnClickListener;
-    private OnCheckedChangeListener mOnCheckedChangeListener;
-    private View.OnClickListener mSupplementalIconOnClickListener;
-
-
-    public CarUiContentListItem(Action action) {
-        mAction = action;
-        mPrimaryIconType = IconType.STANDARD;
-    }
-
-    /**
-     * Returns the title of the item.
-     */
-    @Nullable
-    public CharSequence getTitle() {
-        return mTitle;
-    }
-
-    /**
-     * Sets the title of the item.
-     *
-     * @param title text to display as title.
-     */
-    public void setTitle(@NonNull CharSequence title) {
-        mTitle = title;
-    }
-
-    /**
-     * Returns the body text of the item.
-     */
-    @Nullable
-    public CharSequence getBody() {
-        return mBody;
-    }
-
-    /**
-     * Sets the body of the item.
-     *
-     * @param body text to display as body text.
-     */
-    public void setBody(@NonNull CharSequence body) {
-        mBody = body;
-    }
-
-    /**
-     * Returns the icon of the item.
-     */
-    @Nullable
-    public Drawable getIcon() {
-        return mIcon;
-    }
-
-    /**
-     * Sets the icon of the item.
-     *
-     * @param icon the icon to display.
-     */
-    public void setIcon(@Nullable Drawable icon) {
-        mIcon = icon;
-    }
-
-    /**
-     * Returns the primary icon type for the item.
-     */
-    public IconType getPrimaryIconType() {
-        return mPrimaryIconType;
-    }
-
-    /**
-     * Sets the primary icon type for the item.
-     *
-     * @param icon the icon type for the item.
-     */
-    public void setPrimaryIconType(IconType icon) {
-        mPrimaryIconType = icon;
-    }
-
-    /**
-     * Returns {@code true} if the item is activated.
-     */
-    public boolean isActivated() {
-        return mIsActivated;
-    }
-
-    /**
-     * Sets the activated state of the item.
-     *
-     * @param activated the activated state for the item.
-     */
-    public void setActivated(boolean activated) {
-        mIsActivated = activated;
-    }
-
-    /**
-     * Returns {@code true} if the item is enabled.
-     */
-    public boolean isEnabled() {
-        return mIsEnabled;
-    }
-
-    /**
-     * Sets the enabled state of the item.
-     *
-     * @param enabled the enabled state for the item.
-     */
-    public void setEnabled(boolean enabled) {
-        mIsEnabled = enabled;
-    }
-
-    /**
-     * Returns {@code true} if the item is checked. Will always return {@code false} when the action
-     * type for the item is {@code Action.NONE}.
-     */
-    public boolean isChecked() {
-        return mIsChecked;
-    }
-
-    /**
-     * Sets the checked state of the item.
-     *
-     * @param checked the checked state for the item.
-     */
-    public void setChecked(boolean checked) {
-        if (checked == mIsChecked) {
-            return;
-        }
-
-        // Checked state can only be set when action type is checkbox, radio button or switch.
-        if (mAction == Action.CHECK_BOX || mAction == Action.SWITCH
-                || mAction == Action.RADIO_BUTTON) {
-            mIsChecked = checked;
-
-            if (mOnCheckedChangeListener != null) {
-                mOnCheckedChangeListener.onCheckedChanged(this, mIsChecked);
-            }
-        }
-    }
-
-    /**
-     * Sets the visibility of the action divider.
-     *
-     * @param visible visibility of the action divider.
-     */
-    public void setActionDividerVisible(boolean visible) {
-        mIsActionDividerVisible = visible;
-    }
-
-    /**
-     * Returns {@code true} if the action divider is visible.
-     */
-    public boolean isActionDividerVisible() {
-        return mIsActionDividerVisible;
-    }
-
-    /**
-     * Returns the action type for the item.
-     */
-    public Action getAction() {
-        return mAction;
-    }
-
-    /**
-     * Returns the supplemental icon for the item.
-     */
-    @Nullable
-    public Drawable getSupplementalIcon() {
-        if (mAction != Action.ICON) {
-            return null;
-        }
-
-        return mSupplementalIcon;
-    }
-
-    /**
-     * Sets supplemental icon to be displayed in a list item.
-     *
-     * @param icon the Drawable to set as the icon, or null to clear the content.
-     */
-    public void setSupplementalIcon(@Nullable Drawable icon) {
-        setSupplementalIcon(icon, null);
-    }
-
-    /**
-     * Sets supplemental icon to be displayed in a list item.
-     *
-     * @param icon     the Drawable to set as the icon, or null to clear the content.
-     * @param listener the callback that is invoked when the icon is clicked.
-     */
-    public void setSupplementalIcon(@Nullable Drawable icon,
-            @Nullable View.OnClickListener listener) {
-        if (mAction != Action.ICON) {
-            throw new IllegalStateException(
-                    "Cannot set supplemental icon on list item that does not have an action of "
-                            + "type ICON");
-        }
-
-        mSupplementalIcon = icon;
-        mSupplementalIconOnClickListener = listener;
-    }
-
-    @Nullable
-    public View.OnClickListener getSupplementalIconOnClickListener() {
-        return mSupplementalIconOnClickListener;
-    }
-
-    /**
-     * Registers a callback to be invoked when the item is clicked.
-     *
-     * @param listener callback to be invoked when item is clicked.
-     */
-    public void setOnItemClickedListener(@Nullable OnClickListener listener) {
-        mOnClickListener = listener;
-    }
-
-    /**
-     * Returns the {@link OnClickListener} registered for this item.
-     */
-    @Nullable
-    public OnClickListener getOnClickListener() {
-        return mOnClickListener;
-    }
-
-    /**
-     * Registers a callback to be invoked when the checked state of list item changes.
-     *
-     * <p>Checked state changes can take place when the action type is {@code Action.SWITCH} or
-     * {@code Action.CHECK_BOX}.
-     *
-     * @param listener callback to be invoked when the checked state shown in the UI changes.
-     */
-    public void setOnCheckedChangeListener(
-            @Nullable OnCheckedChangeListener listener) {
-        mOnCheckedChangeListener = listener;
-    }
-
-    /**
-     * Returns the {@link OnCheckedChangeListener} registered for this item.
-     */
-    @Nullable
-    public OnCheckedChangeListener getOnCheckedChangeListener() {
-        return mOnCheckedChangeListener;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiHeaderListItem.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiHeaderListItem.java
deleted file mode 100644
index 57fd755..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiHeaderListItem.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import androidx.annotation.NonNull;
-
-/**
- * Definition of list item header that can be inserted into {@link CarUiListItemAdapter}.
- */
-public class CarUiHeaderListItem extends CarUiListItem {
-
-    private CharSequence mTitle;
-    private CharSequence mBody;
-
-    public CarUiHeaderListItem(@NonNull CharSequence title) {
-        this(title, "");
-    }
-
-    public CarUiHeaderListItem(@NonNull CharSequence title, @NonNull CharSequence body) {
-        mTitle = title;
-        mBody = body;
-    }
-
-    /**
-     * Returns the title text for the header.
-     */
-    public CharSequence getTitle() {
-        return mTitle;
-    }
-
-    /**
-     * Returns the body text for the header.
-     */
-    public CharSequence getBody() {
-        return mBody;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
deleted file mode 100644
index 65a6d40..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import static com.android.car.ui.utils.CarUiUtils.findViewByRefId;
-
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.ImageView;
-import android.widget.RadioButton;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-
-import java.util.List;
-
-/**
- * Adapter for {@link CarUiRecyclerView} to display {@link CarUiContentListItem} and {@link
- * CarUiHeaderListItem}.
- *
- * <ul>
- * <li> Implements {@link CarUiRecyclerView.ItemCap} - defaults to unlimited item count.
- * </ul>
- */
-public class CarUiListItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements
-        CarUiRecyclerView.ItemCap {
-
-    static final int VIEW_TYPE_LIST_ITEM = 1;
-    static final int VIEW_TYPE_LIST_HEADER = 2;
-
-    private List<? extends CarUiListItem> mItems;
-    private int mMaxItems = CarUiRecyclerView.ItemCap.UNLIMITED;
-
-    public CarUiListItemAdapter(List<? extends CarUiListItem> items) {
-        this.mItems = items;
-    }
-
-    @NonNull
-    @Override
-    public RecyclerView.ViewHolder onCreateViewHolder(
-            @NonNull ViewGroup parent, int viewType) {
-        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
-
-        switch (viewType) {
-            case VIEW_TYPE_LIST_ITEM:
-                return new ListItemViewHolder(
-                        inflater.inflate(R.layout.car_ui_list_item, parent, false));
-            case VIEW_TYPE_LIST_HEADER:
-                return new HeaderViewHolder(
-                        inflater.inflate(R.layout.car_ui_header_list_item, parent, false));
-            default:
-                throw new IllegalStateException("Unknown item type.");
-        }
-    }
-
-    /**
-     * Returns the data set held by the adapter.
-     *
-     * <p>Any changes performed to this mutable list must be followed with an invocation of the
-     * appropriate notify method for the adapter.
-     */
-    @NonNull
-    public List<? extends CarUiListItem> getItems() {
-        return mItems;
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        if (mItems.get(position) instanceof CarUiContentListItem) {
-            return VIEW_TYPE_LIST_ITEM;
-        } else if (mItems.get(position) instanceof CarUiHeaderListItem) {
-            return VIEW_TYPE_LIST_HEADER;
-        }
-
-        throw new IllegalStateException("Unknown view type.");
-    }
-
-    @Override
-    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
-        switch (holder.getItemViewType()) {
-            case VIEW_TYPE_LIST_ITEM:
-                if (!(holder instanceof ListItemViewHolder)) {
-                    throw new IllegalStateException("Incorrect view holder type for list item.");
-                }
-
-                CarUiListItem item = mItems.get(position);
-                if (!(item instanceof CarUiContentListItem)) {
-                    throw new IllegalStateException(
-                            "Expected item to be bound to viewholder to be instance of "
-                                    + "CarUiContentListItem.");
-                }
-
-                ((ListItemViewHolder) holder).bind((CarUiContentListItem) item);
-                break;
-            case VIEW_TYPE_LIST_HEADER:
-                if (!(holder instanceof HeaderViewHolder)) {
-                    throw new IllegalStateException("Incorrect view holder type for list item.");
-                }
-
-                CarUiListItem header = mItems.get(position);
-                if (!(header instanceof CarUiHeaderListItem)) {
-                    throw new IllegalStateException(
-                            "Expected item to be bound to viewholder to be instance of "
-                                    + "CarUiHeaderListItem.");
-                }
-
-                ((HeaderViewHolder) holder).bind((CarUiHeaderListItem) header);
-                break;
-            default:
-                throw new IllegalStateException("Unknown item view type.");
-        }
-    }
-
-    @Override
-    public int getItemCount() {
-        return mMaxItems == CarUiRecyclerView.ItemCap.UNLIMITED
-                ? mItems.size()
-                : Math.min(mItems.size(), mMaxItems);
-    }
-
-    @Override
-    public void setMaxItems(int maxItems) {
-        mMaxItems = maxItems;
-    }
-
-    /**
-     * Holds views of {@link CarUiContentListItem}.
-     */
-    static class ListItemViewHolder extends RecyclerView.ViewHolder {
-
-        final TextView mTitle;
-        final TextView mBody;
-        final ImageView mIcon;
-        final ImageView mContentIcon;
-        final ImageView mAvatarIcon;
-        final ViewGroup mIconContainer;
-        final ViewGroup mActionContainer;
-        final View mActionDivider;
-        final Switch mSwitch;
-        final CheckBox mCheckBox;
-        final RadioButton mRadioButton;
-        final ImageView mSupplementalIcon;
-        final View mTouchInterceptor;
-        final View mReducedTouchInterceptor;
-        final View mActionContainerTouchInterceptor;
-
-        ListItemViewHolder(@NonNull View itemView) {
-            super(itemView);
-            mTitle = findViewByRefId(itemView, R.id.title);
-            mBody = findViewByRefId(itemView, R.id.body);
-            mIcon = findViewByRefId(itemView, R.id.icon);
-            mContentIcon = findViewByRefId(itemView, R.id.content_icon);
-            mAvatarIcon = findViewByRefId(itemView, R.id.avatar_icon);
-            mIconContainer = findViewByRefId(itemView, R.id.icon_container);
-            mActionContainer = findViewByRefId(itemView, R.id.action_container);
-            mActionDivider = findViewByRefId(itemView, R.id.action_divider);
-            mSwitch = findViewByRefId(itemView, R.id.switch_widget);
-            mCheckBox = findViewByRefId(itemView, R.id.checkbox_widget);
-            mRadioButton = findViewByRefId(itemView, R.id.radio_button_widget);
-            mSupplementalIcon = findViewByRefId(itemView, R.id.supplemental_icon);
-            mReducedTouchInterceptor = findViewByRefId(itemView, R.id.reduced_touch_interceptor);
-            mTouchInterceptor = findViewByRefId(itemView, R.id.touch_interceptor);
-            mActionContainerTouchInterceptor = findViewByRefId(itemView,
-                    R.id.action_container_touch_interceptor);
-        }
-
-        void bind(@NonNull CarUiContentListItem item) {
-            CharSequence title = item.getTitle();
-            CharSequence body = item.getBody();
-            Drawable icon = item.getIcon();
-
-            if (!TextUtils.isEmpty(title)) {
-                mTitle.setText(title);
-                mTitle.setVisibility(View.VISIBLE);
-            } else {
-                mTitle.setVisibility(View.GONE);
-            }
-
-            if (!TextUtils.isEmpty(body)) {
-                mBody.setText(body);
-                mBody.setVisibility(View.VISIBLE);
-            } else {
-                mBody.setVisibility(View.GONE);
-            }
-
-            mIcon.setVisibility(View.GONE);
-            mContentIcon.setVisibility(View.GONE);
-            mAvatarIcon.setVisibility(View.GONE);
-
-            if (icon != null) {
-                mIconContainer.setVisibility(View.VISIBLE);
-
-                switch (item.getPrimaryIconType()) {
-                    case CONTENT:
-                        mContentIcon.setVisibility(View.VISIBLE);
-                        mContentIcon.setImageDrawable(icon);
-                        break;
-                    case STANDARD:
-                        mIcon.setVisibility(View.VISIBLE);
-                        mIcon.setImageDrawable(icon);
-                        break;
-                    case AVATAR:
-                        mAvatarIcon.setVisibility(View.VISIBLE);
-                        mAvatarIcon.setImageDrawable(icon);
-                        mAvatarIcon.setClipToOutline(true);
-                        break;
-                }
-            } else {
-                mIconContainer.setVisibility(View.GONE);
-            }
-
-            mActionDivider.setVisibility(
-                    item.isActionDividerVisible() ? View.VISIBLE : View.GONE);
-            mSwitch.setVisibility(View.GONE);
-            mCheckBox.setVisibility(View.GONE);
-            mRadioButton.setVisibility(View.GONE);
-            mSupplementalIcon.setVisibility(View.GONE);
-
-            CarUiContentListItem.OnClickListener itemOnClickListener = item.getOnClickListener();
-
-            switch (item.getAction()) {
-                case NONE:
-                    mActionContainer.setVisibility(View.GONE);
-
-                    // Display ripple effects across entire item when clicked by using full-sized
-                    // touch interceptor.
-                    mTouchInterceptor.setVisibility(View.VISIBLE);
-                    mTouchInterceptor.setOnClickListener(v -> {
-                        if (itemOnClickListener != null) {
-                            itemOnClickListener.onClick(item);
-                        }
-                    });
-                    mReducedTouchInterceptor.setVisibility(View.GONE);
-                    mActionContainerTouchInterceptor.setVisibility(View.GONE);
-                    break;
-                case SWITCH:
-                    bindCompoundButton(item, mSwitch, itemOnClickListener);
-                    break;
-                case CHECK_BOX:
-                    bindCompoundButton(item, mCheckBox, itemOnClickListener);
-                    break;
-                case RADIO_BUTTON:
-                    bindCompoundButton(item, mRadioButton, itemOnClickListener);
-                    break;
-                case ICON:
-                    mSupplementalIcon.setVisibility(View.VISIBLE);
-                    mSupplementalIcon.setImageDrawable(item.getSupplementalIcon());
-                    mActionContainer.setVisibility(View.VISIBLE);
-                    mActionContainerTouchInterceptor.setOnClickListener(
-                            (container) -> {
-                                if (item.getSupplementalIconOnClickListener() != null) {
-                                    item.getSupplementalIconOnClickListener().onClick(mIcon);
-                                }
-                                if (itemOnClickListener != null) {
-                                    itemOnClickListener.onClick(item);
-                                }
-                            });
-
-                    // If the icon has a click listener, use a reduced touch interceptor to create
-                    // two distinct touch area; the action container and the remainder of the list
-                    // item. Each touch area will have its own ripple effect. If the icon has no
-                    // click listener, it shouldn't be clickable.
-                    if (item.getSupplementalIconOnClickListener() == null) {
-                        mTouchInterceptor.setVisibility(View.VISIBLE);
-                        mTouchInterceptor.setOnClickListener(v -> {
-                            if (itemOnClickListener != null) {
-                                itemOnClickListener.onClick(item);
-                            }
-                        });
-                        mReducedTouchInterceptor.setVisibility(View.GONE);
-                        mActionContainerTouchInterceptor.setVisibility(View.GONE);
-                    } else {
-                        mReducedTouchInterceptor.setVisibility(View.VISIBLE);
-                        mReducedTouchInterceptor.setOnClickListener(v -> {
-                            if (itemOnClickListener != null) {
-                                itemOnClickListener.onClick(item);
-                            }
-                        });
-                        mActionContainerTouchInterceptor.setVisibility(View.VISIBLE);
-                        mTouchInterceptor.setVisibility(View.GONE);
-                    }
-                    break;
-                default:
-                    throw new IllegalStateException("Unknown secondary action type.");
-            }
-
-            itemView.setActivated(item.isActivated());
-            setEnabled(itemView, item.isEnabled());
-        }
-
-        void setEnabled(View view, boolean enabled) {
-            view.setEnabled(enabled);
-            if (view instanceof ViewGroup) {
-                ViewGroup group = (ViewGroup) view;
-
-                for (int i = 0; i < group.getChildCount(); i++) {
-                    setEnabled(group.getChildAt(i), enabled);
-                }
-            }
-        }
-
-        void bindCompoundButton(@NonNull CarUiContentListItem item,
-                @NonNull CompoundButton compoundButton,
-                @Nullable CarUiContentListItem.OnClickListener itemOnClickListener) {
-            compoundButton.setVisibility(View.VISIBLE);
-            compoundButton.setOnCheckedChangeListener(null);
-            compoundButton.setChecked(item.isChecked());
-            compoundButton.setOnCheckedChangeListener(
-                    (buttonView, isChecked) -> item.setChecked(isChecked));
-
-            // Clicks anywhere on the item should toggle the checkbox state. Use full touch
-            // interceptor.
-            mTouchInterceptor.setVisibility(View.VISIBLE);
-            mTouchInterceptor.setOnClickListener(v -> {
-                compoundButton.toggle();
-                if (itemOnClickListener != null) {
-                    itemOnClickListener.onClick(item);
-                }
-            });
-            mReducedTouchInterceptor.setVisibility(View.GONE);
-            mActionContainerTouchInterceptor.setVisibility(View.GONE);
-
-            mActionContainer.setVisibility(View.VISIBLE);
-            mActionContainer.setClickable(false);
-        }
-    }
-
-    /**
-     * Holds views of {@link CarUiHeaderListItem}.
-     */
-    static class HeaderViewHolder extends RecyclerView.ViewHolder {
-
-        private final TextView mTitle;
-        private final TextView mBody;
-
-        HeaderViewHolder(@NonNull View itemView) {
-            super(itemView);
-            mTitle = findViewByRefId(itemView, R.id.title);
-            mBody = findViewByRefId(itemView, R.id.body);
-        }
-
-        private void bind(@NonNull CarUiHeaderListItem item) {
-            mTitle.setText(item.getTitle());
-
-            CharSequence body = item.getBody();
-            if (!TextUtils.isEmpty(body)) {
-                mBody.setText(body);
-            } else {
-                mBody.setVisibility(View.GONE);
-            }
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java
deleted file mode 100644
index ed248c1..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRadioButtonListItemAdapter.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2020 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.car.ui.recyclerview;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-
-import java.util.List;
-
-/**
- * Adapter for {@link CarUiRecyclerView} to display {@link CarUiRadioButtonListItem}. This adapter
- * allows for at most one item to be selected at a time.
- *
- * <ul>
- * <li> Implements {@link CarUiRecyclerView.ItemCap} - defaults to unlimited item count.
- * </ul>
- */
-public class CarUiRadioButtonListItemAdapter extends CarUiListItemAdapter {
-
-    private int mSelectedIndex = -1;
-
-    public CarUiRadioButtonListItemAdapter(List<CarUiRadioButtonListItem> items) {
-        super(items);
-        for (int i = 0; i < items.size(); i++) {
-            CarUiRadioButtonListItem item = items.get(i);
-            if (item.isChecked() && mSelectedIndex >= 0) {
-                throw new IllegalStateException(
-                        "At most one item in a CarUiRadioButtonListItemAdapter can be checked");
-            }
-
-            if (item.isChecked()) {
-                mSelectedIndex = i;
-            }
-        }
-    }
-
-    @NonNull
-    @Override
-    public RecyclerView.ViewHolder onCreateViewHolder(
-            @NonNull ViewGroup parent, int viewType) {
-        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
-
-        if (viewType == VIEW_TYPE_LIST_ITEM) {
-            return new RadioButtonListItemViewHolder(
-                    inflater.inflate(R.layout.car_ui_list_item, parent, false));
-        }
-        return super.onCreateViewHolder(parent, viewType);
-    }
-
-    @Override
-    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
-        if (holder.getItemViewType() == VIEW_TYPE_LIST_ITEM) {
-            if (!(holder instanceof RadioButtonListItemViewHolder)) {
-                throw new IllegalStateException("Incorrect view holder type for list item.");
-            }
-
-            CarUiListItem item = getItems().get(position);
-            if (!(item instanceof CarUiRadioButtonListItem)) {
-                throw new IllegalStateException(
-                        "Expected item to be bound to viewholder to be instance of "
-                                + "CarUiRadioButtonListItem.");
-            }
-
-            RadioButtonListItemViewHolder actualHolder = ((RadioButtonListItemViewHolder) holder);
-            actualHolder.bind((CarUiRadioButtonListItem) item);
-            actualHolder.setOnCheckedChangeListener(isChecked -> {
-                if (isChecked && mSelectedIndex >= 0) {
-                    CarUiRadioButtonListItem previousSelectedItem =
-                            (CarUiRadioButtonListItem) getItems().get(mSelectedIndex);
-                    previousSelectedItem.setChecked(false);
-                    notifyItemChanged(mSelectedIndex);
-                }
-
-                if (isChecked) {
-                    mSelectedIndex = position;
-                    CarUiRadioButtonListItem currentSelectedItem =
-                            (CarUiRadioButtonListItem) getItems().get(mSelectedIndex);
-                    currentSelectedItem.setChecked(true);
-                    notifyItemChanged(mSelectedIndex);
-                }
-            });
-
-        } else {
-            super.onBindViewHolder(holder, position);
-        }
-    }
-
-    static class RadioButtonListItemViewHolder extends ListItemViewHolder {
-        /**
-         * Callback to be invoked when the checked state of a {@link RadioButtonListItemViewHolder}
-         * changed.
-         */
-        public interface OnCheckedChangeListener {
-            /**
-             * Called when the checked state of a {@link RadioButtonListItemViewHolder} has changed.
-             *
-             * @param isChecked new checked state of list item.
-             */
-            void onCheckedChanged(boolean isChecked);
-        }
-
-        @Nullable
-        private OnCheckedChangeListener mListener;
-
-        RadioButtonListItemViewHolder(@NonNull View itemView) {
-            super(itemView);
-        }
-
-        void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) {
-            mListener = listener;
-        }
-
-        @Override
-        void bind(@NonNull CarUiContentListItem item) {
-            super.bind(item);
-            mRadioButton.setOnCheckedChangeListener(
-                    (buttonView, isChecked) -> {
-                        item.setChecked(isChecked);
-                        if (mListener != null) {
-                            mListener.onCheckedChanged(isChecked);
-                        }
-                    });
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerView.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerView.java
deleted file mode 100644
index 36ed154..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerView.java
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview;
-
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-import com.android.car.ui.recyclerview.decorations.grid.GridDividerItemDecoration;
-import com.android.car.ui.recyclerview.decorations.grid.GridOffsetItemDecoration;
-import com.android.car.ui.recyclerview.decorations.linear.LinearDividerItemDecoration;
-import com.android.car.ui.recyclerview.decorations.linear.LinearOffsetItemDecoration;
-import com.android.car.ui.recyclerview.decorations.linear.LinearOffsetItemDecoration.OffsetPosition;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.utils.CarUxRestrictionsUtil;
-
-import java.lang.annotation.Retention;
-import java.util.Objects;
-
-/**
- * View that extends a {@link RecyclerView} and wraps itself into a {@link LinearLayout} which could
- * potentially include a scrollbar that has page up and down arrows. Interaction with this view is
- * similar to a {@code RecyclerView} as it takes the same adapter and the layout manager.
- */
-public final class CarUiRecyclerView extends RecyclerView implements
-        Toolbar.OnHeightChangedListener {
-
-    private static final String TAG = "CarUiRecyclerView";
-
-    private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener mListener =
-            new UxRestrictionChangedListener();
-
-    private CarUxRestrictionsUtil mCarUxRestrictionsUtil;
-    private boolean mScrollBarEnabled;
-    private String mScrollBarClass;
-    private boolean mFullyInitialized;
-    private int mScrollBarPaddingTop;
-    private int mScrollBarPaddingBottom;
-    private boolean mHasScrolledToTop = false;
-
-    private ScrollBar mScrollBar;
-    private int mInitialTopPadding;
-
-    @CarUiRecyclerViewLayout
-    private int mCarUiRecyclerViewLayout;
-
-    @Nullable
-    private GridOffsetItemDecoration mTopOffsetItemDecorationGrid;
-    @Nullable
-    private GridOffsetItemDecoration mBottomOffsetItemDecorationGrid;
-    @Nullable
-    private RecyclerView.ItemDecoration mTopOffsetItemDecorationLinear;
-    @Nullable
-    private RecyclerView.ItemDecoration mBottomOffsetItemDecorationLinear;
-    @Nullable
-    private GridDividerItemDecoration mDividerItemDecorationGrid;
-    @Nullable
-    private RecyclerView.ItemDecoration mDividerItemDecorationLinear;
-    private int mNumOfColumns;
-    private boolean mInstallingExtScrollBar = false;
-    private int mContainerVisibility = View.VISIBLE;
-    private Rect mContainerPadding;
-    private Rect mContainerPaddingRelative;
-    private LinearLayout mContainer;
-
-    // Set to true when when styled attributes are read and initialized.
-    private boolean mIsInitialized;
-    private boolean mEnableDividers;
-    private int mTopOffset;
-    private int mBottomOffset;
-
-    private ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener = () -> {
-        if (mInitialTopPadding == 0) {
-            mInitialTopPadding = getPaddingTop();
-        }
-        mFullyInitialized = true;
-    };
-
-    /**
-     * The possible values for setScrollBarPosition. The default value is actually {@link
-     * CarUiRecyclerViewLayout#LINEAR}.
-     */
-    @IntDef({
-            CarUiRecyclerViewLayout.LINEAR,
-            CarUiRecyclerViewLayout.GRID,
-    })
-    @Retention(SOURCE)
-    public @interface CarUiRecyclerViewLayout {
-        /**
-         * Arranges items either horizontally in a single row or vertically in a single column. This
-         * is default.
-         */
-        int LINEAR = 0;
-
-        /**
-         * Arranges items in a Grid.
-         */
-        int GRID = 1;
-    }
-
-    /**
-     * Interface for a {@link RecyclerView.Adapter} to cap the number of items.
-     *
-     * <p>NOTE: it is still up to the adapter to use maxItems in {@link
-     * RecyclerView.Adapter#getItemCount()}.
-     *
-     * <p>the recommended way would be with:
-     *
-     * <pre>{@code
-     * {@literal@}Override
-     * public int getItemCount() {
-     *   return Math.min(super.getItemCount(), mMaxItems);
-     * }
-     * }</pre>
-     */
-    public interface ItemCap {
-
-        /**
-         * A value to pass to {@link #setMaxItems(int)} that indicates there should be no limit.
-         */
-        int UNLIMITED = -1;
-
-        /**
-         * Sets the maximum number of items available in the adapter. A value less than '0' means
-         * the list should not be capped.
-         */
-        void setMaxItems(int maxItems);
-    }
-
-    public CarUiRecyclerView(@NonNull Context context) {
-        this(context, null);
-    }
-
-    public CarUiRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, R.attr.carUiRecyclerViewStyle);
-    }
-
-    public CarUiRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyle) {
-        super(context, attrs, defStyle);
-        init(context, attrs, defStyle);
-    }
-
-    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
-        mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
-        TypedArray a = context.obtainStyledAttributes(
-                attrs,
-                R.styleable.CarUiRecyclerView,
-                defStyleAttr,
-                R.style.Widget_CarUi_CarUiRecyclerView);
-
-        mScrollBarEnabled = context.getResources().getBoolean(R.bool.car_ui_scrollbar_enable);
-        mFullyInitialized = false;
-
-        mScrollBarPaddingTop = context.getResources()
-                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_padding_top);
-        mScrollBarPaddingBottom = context.getResources()
-                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_padding_bottom);
-
-        mCarUiRecyclerViewLayout =
-                a.getInt(R.styleable.CarUiRecyclerView_layoutStyle, CarUiRecyclerViewLayout.LINEAR);
-        mNumOfColumns = a.getInt(R.styleable.CarUiRecyclerView_numOfColumns, /* defValue= */ 2);
-        mEnableDividers =
-                a.getBoolean(R.styleable.CarUiRecyclerView_enableDivider, /* defValue= */ false);
-
-        mDividerItemDecorationLinear = new LinearDividerItemDecoration(
-                context.getDrawable(R.drawable.car_ui_recyclerview_divider));
-
-        mDividerItemDecorationGrid =
-                new GridDividerItemDecoration(
-                        context.getDrawable(R.drawable.car_ui_divider),
-                        context.getDrawable(R.drawable.car_ui_divider),
-                        mNumOfColumns);
-
-        mTopOffset = a.getInteger(R.styleable.CarUiRecyclerView_topOffset, /* defValue= */0);
-        mBottomOffset = a.getInteger(
-                R.styleable.CarUiRecyclerView_bottomOffset, /* defValue= */0);
-
-        mTopOffsetItemDecorationLinear =
-                new LinearOffsetItemDecoration(mTopOffset, OffsetPosition.START);
-        mBottomOffsetItemDecorationLinear =
-                new LinearOffsetItemDecoration(mBottomOffset, OffsetPosition.END);
-        mTopOffsetItemDecorationGrid =
-                new GridOffsetItemDecoration(mTopOffset, mNumOfColumns,
-                        OffsetPosition.START);
-        mBottomOffsetItemDecorationGrid =
-                new GridOffsetItemDecoration(mBottomOffset, mNumOfColumns,
-                        OffsetPosition.END);
-
-        mIsInitialized = true;
-
-        // Check if a layout manager has already been set via XML
-        boolean isLayoutMangerSet = getLayoutManager() != null;
-        if (!isLayoutMangerSet && mCarUiRecyclerViewLayout == CarUiRecyclerViewLayout.LINEAR) {
-            setLayoutManager(new LinearLayoutManager(getContext()));
-        } else if (!isLayoutMangerSet && mCarUiRecyclerViewLayout == CarUiRecyclerViewLayout.GRID) {
-            setLayoutManager(new GridLayoutManager(getContext(), mNumOfColumns));
-        }
-
-        a.recycle();
-
-        if (!mScrollBarEnabled) {
-            mFullyInitialized = true;
-            return;
-        }
-
-        mContainer = new LinearLayout(getContext());
-
-        setVerticalScrollBarEnabled(false);
-        setHorizontalScrollBarEnabled(false);
-
-        mScrollBarClass = context.getResources().getString(R.string.car_ui_scrollbar_component);
-    }
-
-    @Override
-    public void setLayoutManager(@Nullable LayoutManager layoutManager) {
-        // Cannot setup item decorations before stylized attributes have been read.
-        if (mIsInitialized) {
-            addItemDecorations(layoutManager);
-        }
-        super.setLayoutManager(layoutManager);
-    }
-
-    // This method should not be invoked before item decorations are initialized by the #init()
-    // method.
-    private void addItemDecorations(LayoutManager layoutManager) {
-        // remove existing Item decorations.
-        removeItemDecoration(Objects.requireNonNull(mDividerItemDecorationGrid));
-        removeItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationGrid));
-        removeItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationGrid));
-        removeItemDecoration(Objects.requireNonNull(mDividerItemDecorationLinear));
-        removeItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationLinear));
-        removeItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationLinear));
-
-        if (layoutManager instanceof GridLayoutManager) {
-            if (mEnableDividers) {
-                addItemDecoration(Objects.requireNonNull(mDividerItemDecorationGrid));
-            }
-            addItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationGrid));
-            addItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationGrid));
-            setNumOfColumns(((GridLayoutManager) layoutManager).getSpanCount());
-        } else {
-            if (mEnableDividers) {
-                addItemDecoration(Objects.requireNonNull(mDividerItemDecorationLinear));
-            }
-            addItemDecoration(Objects.requireNonNull(mTopOffsetItemDecorationLinear));
-            addItemDecoration(Objects.requireNonNull(mBottomOffsetItemDecorationLinear));
-        }
-    }
-
-    @Override
-    public void onHeightChanged(int height) {
-        setPaddingRelative(getPaddingStart(), mInitialTopPadding + height,
-                getPaddingEnd(), getPaddingBottom());
-    }
-
-    /**
-     * Returns {@code true} if the {@link CarUiRecyclerView} is fully drawn. Using a global layout
-     * mListener may not necessarily signify that this view is fully drawn (i.e. when the scrollbar
-     * is enabled).
-     */
-    public boolean fullyInitialized() {
-        return mFullyInitialized;
-    }
-
-    /**
-     * Sets the number of columns in which grid needs to be divided.
-     */
-    public void setNumOfColumns(int numberOfColumns) {
-        mNumOfColumns = numberOfColumns;
-        if (mTopOffsetItemDecorationGrid != null) {
-            mTopOffsetItemDecorationGrid.setNumOfColumns(mNumOfColumns);
-        }
-        if (mDividerItemDecorationGrid != null) {
-            mDividerItemDecorationGrid.setNumOfColumns(mNumOfColumns);
-        }
-    }
-
-    @Override
-    public void setVisibility(int visibility) {
-        super.setVisibility(visibility);
-        mContainerVisibility = visibility;
-        if (mContainer != null) {
-            mContainer.setVisibility(visibility);
-        }
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mCarUxRestrictionsUtil.register(mListener);
-
-        this.getViewTreeObserver()
-                .addOnGlobalLayoutListener(mOnGlobalLayoutListener);
-
-        if (mInstallingExtScrollBar || !mScrollBarEnabled) {
-            return;
-        }
-        // When CarUiRV is detached from the current parent and attached to the container with
-        // the scrollBar, onAttachedToWindow() will get called immediately when attaching the
-        // CarUiRV to the container. This flag will help us keep track of this state and avoid
-        // recursion. We also want to reset the state of this flag as soon as the container is
-        // successfully attached to the CarUiRV's original parent.
-        mInstallingExtScrollBar = true;
-        installExternalScrollBar();
-        mInstallingExtScrollBar = false;
-    }
-
-    /**
-     * This method will detach the current recycler view from its parent and attach it to the
-     * container which is a LinearLayout. Later the entire container is attached to the parent where
-     * the recycler view was set with the same layout params.
-     */
-    private void installExternalScrollBar() {
-        LayoutInflater inflater = LayoutInflater.from(getContext());
-        inflater.inflate(R.layout.car_ui_recycler_view, mContainer, true);
-        mContainer.setVisibility(mContainerVisibility);
-        if (mContainerPadding != null) {
-            mContainer.setPadding(mContainerPadding.left, mContainerPadding.top,
-                    mContainerPadding.right, mContainerPadding.bottom);
-        } else if (mContainerPaddingRelative != null) {
-            mContainer.setPaddingRelative(mContainerPaddingRelative.left,
-                    mContainerPaddingRelative.top, mContainerPaddingRelative.right,
-                    mContainerPaddingRelative.bottom);
-        } else {
-            mContainer.setPadding(getPaddingLeft(), /* Top = */ 0,
-                    getPaddingRight(), /* Bottom = */ 0);
-            setPadding(/* Left = */ 0, getPaddingTop(),
-                    /* Right = */ 0, getPaddingBottom());
-        }
-
-        mContainer.setLayoutParams(getLayoutParams());
-        ViewGroup parent = (ViewGroup) getParent();
-        int index = parent.indexOfChild(this);
-
-        parent.removeViewInLayout(this);
-
-        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
-        ((CarUiRecyclerViewContainer) requireViewByRefId(mContainer, R.id.car_ui_recycler_view))
-                .addRecyclerView(this, params);
-        parent.addView(mContainer, index);
-
-        createScrollBarFromConfig(requireViewByRefId(mContainer, R.id.car_ui_scroll_bar));
-    }
-
-    private void createScrollBarFromConfig(View scrollView) {
-        Class<?> cls;
-        try {
-            cls = !TextUtils.isEmpty(mScrollBarClass)
-                    ? getContext().getClassLoader().loadClass(mScrollBarClass)
-                    : DefaultScrollBar.class;
-        } catch (Throwable t) {
-            throw andLog("Error loading scroll bar component: " + mScrollBarClass, t);
-        }
-        try {
-            mScrollBar = (ScrollBar) cls.getDeclaredConstructor().newInstance();
-        } catch (Throwable t) {
-            throw andLog("Error creating scroll bar component: " + mScrollBarClass, t);
-        }
-
-        mScrollBar.initialize(this, scrollView);
-
-        setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mCarUxRestrictionsUtil.unregister(mListener);
-        this.getViewTreeObserver().removeOnGlobalLayoutListener(mOnGlobalLayoutListener);
-    }
-
-    @Override
-    public void setAlpha(float value) {
-        if (mScrollBarEnabled) {
-            mContainer.setAlpha(value);
-        } else {
-            super.setAlpha(value);
-        }
-    }
-
-    @Override
-    public ViewPropertyAnimator animate() {
-        return mScrollBarEnabled ? mContainer.animate() : super.animate();
-    }
-
-    @Override
-    public void setPadding(int left, int top, int right, int bottom) {
-        super.setPadding(0, top, 0, bottom);
-        mContainerPaddingRelative = null;
-        mContainerPadding = new Rect(left, 0, right, 0);
-        if (mContainer != null) {
-            mContainer.setPadding(left, 0, right, 0);
-        }
-        setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
-    }
-
-    @Override
-    public void setPaddingRelative(int start, int top, int end, int bottom) {
-        super.setPaddingRelative(0, top, 0, bottom);
-        mContainerPadding = null;
-        mContainerPaddingRelative = new Rect(start, 0, end, 0);
-        if (mContainer != null) {
-            mContainer.setPaddingRelative(start, 0, end, 0);
-        }
-        setScrollBarPadding(mScrollBarPaddingTop, mScrollBarPaddingBottom);
-    }
-
-    /**
-     * Sets the scrollbar's padding top and bottom. This padding is applied in addition to the
-     * padding of the RecyclerView.
-     */
-    public void setScrollBarPadding(int paddingTop, int paddingBottom) {
-        if (mScrollBarEnabled) {
-            mScrollBarPaddingTop = paddingTop;
-            mScrollBarPaddingBottom = paddingBottom;
-
-            if (mScrollBar != null) {
-                mScrollBar.setPadding(paddingTop + getPaddingTop(),
-                        paddingBottom + getPaddingBottom());
-            }
-        }
-    }
-
-    /**
-     * @deprecated use {#getLayoutManager()}
-     */
-    @Nullable
-    @Deprecated
-    public LayoutManager getEffectiveLayoutManager() {
-        return super.getLayoutManager();
-    }
-
-    /**
-     * Sets divider item decoration for linear layout.
-     */
-    public void setLinearDividerItemDecoration(boolean enableDividers) {
-        if (enableDividers) {
-            addItemDecoration(mDividerItemDecorationLinear);
-            return;
-        }
-        removeItemDecoration(mDividerItemDecorationLinear);
-    }
-
-    /**
-     * Sets divider item decoration for grid layout.
-     */
-    public void setGridDividerItemDecoration(boolean enableDividers) {
-        if (enableDividers) {
-            addItemDecoration(mDividerItemDecorationGrid);
-            return;
-        }
-        removeItemDecoration(mDividerItemDecorationGrid);
-    }
-
-    private static RuntimeException andLog(String msg, Throwable t) {
-        Log.e(TAG, msg, t);
-        throw new RuntimeException(msg, t);
-    }
-
-    private class UxRestrictionChangedListener implements
-            CarUxRestrictionsUtil.OnUxRestrictionsChangedListener {
-
-        @Override
-        public void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions) {
-            Adapter<?> adapter = getAdapter();
-            // If the adapter does not implement ItemCap, then the max items on it cannot be
-            // updated.
-            if (!(adapter instanceof ItemCap)) {
-                return;
-            }
-
-            int maxItems = ItemCap.UNLIMITED;
-            if ((carUxRestrictions.getActiveRestrictions()
-                    & CarUxRestrictions.UX_RESTRICTIONS_LIMIT_CONTENT)
-                    != 0) {
-                maxItems = carUxRestrictions.getMaxCumulativeContentItems();
-            }
-
-            int originalCount = adapter.getItemCount();
-            ((ItemCap) adapter).setMaxItems(maxItems);
-            int newCount = adapter.getItemCount();
-
-            if (newCount == originalCount) {
-                return;
-            }
-
-            if (newCount < originalCount) {
-                adapter.notifyItemRangeRemoved(newCount, originalCount - newCount);
-            } else {
-                adapter.notifyItemRangeInserted(originalCount, newCount - originalCount);
-            }
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java
deleted file mode 100644
index 5b74b44..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapter.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview;
-
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-
-/** The adapter for the parent recyclerview in {@link CarUiRecyclerView} widget. */
-final class CarUiRecyclerViewAdapter
-        extends RecyclerView.Adapter<CarUiRecyclerViewAdapter.NestedRowViewHolder> {
-
-    @Override
-    public CarUiRecyclerViewAdapter.NestedRowViewHolder onCreateViewHolder(
-            ViewGroup parent, int viewType) {
-        View v =
-                LayoutInflater.from(parent.getContext())
-                        .inflate(R.layout.car_ui_recycler_view_item, parent, false);
-        return new NestedRowViewHolder(v);
-    }
-
-    // Replace the contents of a view (invoked by the layout manager). Intentionally left empty
-    // since this adapter is an empty shell for the nested recyclerview.
-    @Override
-    public void onBindViewHolder(NestedRowViewHolder holder, int position) {
-    }
-
-    // Return the size of your dataset (invoked by the layout manager)
-    @Override
-    public int getItemCount() {
-        return 1;
-    }
-
-    /** The viewholder class for the parent recyclerview. */
-    static class NestedRowViewHolder extends RecyclerView.ViewHolder {
-        public FrameLayout frameLayout;
-
-        NestedRowViewHolder(View view) {
-            super(view);
-            frameLayout = requireViewByRefId(view, R.id.nested_recycler_view_layout);
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java
deleted file mode 100644
index 3a0519f..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiRecyclerViewContainer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.recyclerview;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-/**
- * Container that contains the scrollbar and RecyclerView when scrollbar is enabled.
- *
- * This container is required to expose addViewInLayout such that the scrollbar can be added without
- * triggering multiple invalidate and relayout calls.
- */
-public class CarUiRecyclerViewContainer extends FrameLayout {
-
-    public CarUiRecyclerViewContainer(Context context) {
-        super(context);
-    }
-
-    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    public CarUiRecyclerViewContainer(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    /**
-     * Adds the recyclerview using addViewInLayout so that invalidate and relayout calls are not
-     * triggered.
-     */
-    void addRecyclerView(View view, LayoutParams layoutParams) {
-        addViewInLayout(view, 0, layoutParams);
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSnapHelper.java b/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSnapHelper.java
deleted file mode 100644
index a7fff75..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/CarUiSnapHelper.java
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview;
-
-import android.content.Context;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.LinearSnapHelper;
-import androidx.recyclerview.widget.OrientationHelper;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.LayoutManager;
-
-import java.util.Objects;
-
-/**
- * Inspired by {@link androidx.car.widget.PagedSnapHelper}
- *
- * <p>Extension of a {@link LinearSnapHelper} that will snap to the start of the target child view
- * to the start of the attached {@link RecyclerView}. The start of the view is defined as the top if
- * the RecyclerView is scrolling vertically; it is defined as the left (or right if RTL) if the
- * RecyclerView is scrolling horizontally.
- */
-public class CarUiSnapHelper extends LinearSnapHelper {
-    /**
-     * The percentage of a View that needs to be completely visible for it to be a viable snap
-     * target.
-     */
-    private static final float VIEW_VISIBLE_THRESHOLD = 0.5f;
-
-    /**
-     * When a View is longer than containing RecyclerView, the percentage of the end of this View
-     * that needs to be completely visible to prevent the rest of views to be a viable snap target.
-     *
-     * <p>In other words, if a longer-than-screen View takes more than threshold screen space on its
-     * end, do not snap to any View.
-     */
-    private static final float LONG_ITEM_END_VISIBLE_THRESHOLD = 0.3f;
-
-    private final Context mContext;
-    private RecyclerView mRecyclerView;
-
-    public CarUiSnapHelper(Context context) {
-        mContext = context;
-    }
-
-    // Orientation helpers are lazily created per LayoutManager.
-    @Nullable
-    private OrientationHelper mVerticalHelper;
-    @Nullable
-    private OrientationHelper mHorizontalHelper;
-
-    @Override
-    public int[] calculateDistanceToFinalSnap(
-            @NonNull LayoutManager layoutManager, @NonNull View targetView) {
-        int[] out = new int[2];
-
-        // Don't snap when not in touch mode, i.e. when using rotary.
-        if (!mRecyclerView.isInTouchMode()) {
-            return out;
-        }
-
-        if (layoutManager.canScrollHorizontally()) {
-            out[0] = distanceToTopMargin(targetView, getHorizontalHelper(layoutManager));
-        }
-
-        if (layoutManager.canScrollVertically()) {
-            out[1] = distanceToTopMargin(targetView, getVerticalHelper(layoutManager));
-        }
-
-        return out;
-    }
-
-    /**
-     * Finds the view to snap to. The view to snap to is the child of the LayoutManager that is
-     * closest to the start of the RecyclerView. The "start" depends on if the LayoutManager
-     * is scrolling horizontally or vertically. If it is horizontally scrolling, then the
-     * start is the view on the left (right if RTL). Otherwise, it is the top-most view.
-     *
-     * @param layoutManager The current {@link LayoutManager} for the attached RecyclerView.
-     * @return The View closest to the start of the RecyclerView. Returns {@code null}when:
-     * <ul>
-     *     <li>there is no item; or
-     *     <li>no visible item can fully fit in the containing RecyclerView; or
-     *     <li>an item longer than containing RecyclerView is about to scroll out.
-     * </ul>
-     */
-    @Override
-    @Nullable
-    public View findSnapView(LayoutManager layoutManager) {
-        int childCount = layoutManager.getChildCount();
-        if (childCount == 0) {
-            return null;
-        }
-
-        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
-
-        // If there's only one child, then that will be the snap target.
-        if (childCount == 1) {
-            View firstChild = layoutManager.getChildAt(0);
-            return isValidSnapView(firstChild, orientationHelper) ? firstChild : null;
-        }
-
-        if (mRecyclerView == null) {
-            return null;
-        }
-
-        // If the top child view is longer than the RecyclerView (long item), and it's not yet
-        // scrolled out - meaning the screen it takes up is more than threshold,
-        // do not snap to any view.
-        // This way avoids next View snapping to top "pushes" out the end of a long item.
-        View firstChild = mRecyclerView.getChildAt(0);
-        if (firstChild.getHeight() > mRecyclerView.getHeight()
-                // Long item start is scrolled past screen;
-                && orientationHelper.getDecoratedStart(firstChild) < 0
-                // and it takes up more than threshold screen size.
-                && orientationHelper.getDecoratedEnd(firstChild) > (
-                mRecyclerView.getHeight() * LONG_ITEM_END_VISIBLE_THRESHOLD)) {
-            return null;
-        }
-
-        @NonNull View lastVisibleChild = Objects.requireNonNull(
-                layoutManager.getChildAt(childCount - 1));
-
-        // Check if the last child visible is the last item in the list.
-        boolean lastItemVisible =
-                layoutManager.getPosition(lastVisibleChild) == layoutManager.getItemCount() - 1;
-
-        // If it is, then check how much of that view is visible.
-        float lastItemPercentageVisible = lastItemVisible
-                ? getPercentageVisible(lastVisibleChild, orientationHelper) : 0;
-
-        View closestChild = null;
-        int closestDistanceToStart = Integer.MAX_VALUE;
-        float closestPercentageVisible = 0.f;
-
-        // Iterate to find the child closest to the top and more than half way visible.
-        for (int i = 0; i < childCount; i++) {
-            View child = layoutManager.getChildAt(i);
-            int startOffset = orientationHelper.getDecoratedStart(child);
-
-            if (Math.abs(startOffset) < closestDistanceToStart) {
-                float percentageVisible = getPercentageVisible(child, orientationHelper);
-
-                if (percentageVisible > VIEW_VISIBLE_THRESHOLD
-                        && percentageVisible > closestPercentageVisible) {
-                    closestDistanceToStart = startOffset;
-                    closestChild = child;
-                    closestPercentageVisible = percentageVisible;
-                }
-            }
-        }
-
-        View childToReturn = closestChild;
-
-        // If closestChild is null, then that means we were unable to find a closest child that
-        // is over the VIEW_VISIBLE_THRESHOLD. This could happen if the views are larger than
-        // the given area. In this case, consider returning the lastVisibleChild so that the screen
-        // scrolls. Also, check if the last item should be displayed anyway if it is mostly visible.
-        if ((childToReturn == null
-                || (lastItemVisible && lastItemPercentageVisible > closestPercentageVisible))) {
-            childToReturn = lastVisibleChild;
-        }
-
-        // Return null if the childToReturn is not valid. This allows the user to scroll freely
-        // with no snapping. This can allow them to see the entire view.
-        return isValidSnapView(childToReturn, orientationHelper) ? childToReturn : null;
-    }
-
-    private static int distanceToTopMargin(@NonNull View targetView, OrientationHelper helper) {
-        final int childTop = helper.getDecoratedStart(targetView);
-        final int containerTop = helper.getStartAfterPadding();
-        return childTop - containerTop;
-    }
-
-    /**
-     * Finds the view to snap to. The view to snap to is the child of the LayoutManager that is
-     * closest to the start of the RecyclerView. The "start" depends on if the LayoutManager is
-     * scrolling horizontally or vertically. If it is horizontally scrolling, then the start is the
-     * view on the left (right if RTL). Otherwise, it is the top-most view.
-     *
-     * @param layoutManager The current {@link RecyclerView.LayoutManager} for the attached
-     *                      RecyclerView.
-     * @return The View closest to the start of the RecyclerView.
-     */
-    private static View findTopView(LayoutManager layoutManager, OrientationHelper helper) {
-        int childCount = layoutManager.getChildCount();
-        if (childCount == 0) {
-            return null;
-        }
-
-        View closestChild = null;
-        int absClosest = Integer.MAX_VALUE;
-
-        for (int i = 0; i < childCount; i++) {
-            View child = layoutManager.getChildAt(i);
-            if (child == null) {
-                continue;
-            }
-            int absDistance = Math.abs(distanceToTopMargin(child, helper));
-
-            /* if child top is closer than previous closest, set it as closest */
-            if (absDistance < absClosest) {
-                absClosest = absDistance;
-                closestChild = child;
-            }
-        }
-        return closestChild;
-    }
-
-    /**
-     * Returns whether or not the given View is a valid snapping view. A view is considered valid
-     * for snapping if it can fit entirely within the height of the RecyclerView it is contained
-     * within.
-     *
-     * <p>If the view is larger than the RecyclerView, then it might not want to be snapped to
-     * to allow the user to scroll and see the rest of the View.
-     *
-     * @param view   The view to determine the snapping potential.
-     * @param helper The {@link OrientationHelper} associated with the current RecyclerView.
-     * @return {@code true} if the given view is a valid snapping view; {@code false} otherwise.
-     */
-    private static boolean isValidSnapView(View view, OrientationHelper helper) {
-        return helper.getDecoratedMeasurement(view) <= helper.getTotalSpace();
-    }
-
-    /**
-     * Returns the percentage of the given view that is visible, relative to its containing
-     * RecyclerView.
-     *
-     * @param view   The View to get the percentage visible of.
-     * @param helper An {@link OrientationHelper} to aid with calculation.
-     * @return A float indicating the percentage of the given view that is visible.
-     */
-    static float getPercentageVisible(View view, OrientationHelper helper) {
-        int start = helper.getStartAfterPadding();
-        int end = helper.getEndAfterPadding();
-
-        int viewStart = helper.getDecoratedStart(view);
-        int viewEnd = helper.getDecoratedEnd(view);
-
-        if (viewStart >= start && viewEnd <= end) {
-            // The view is within the bounds of the RecyclerView, so it's fully visible.
-            return 1.f;
-        } else if (viewEnd <= start) {
-            // The view is above the visible area of the RecyclerView.
-            return 0;
-        } else if (viewStart >= end) {
-            // The view is below the visible area of the RecyclerView.
-            return 0;
-        } else if (viewStart <= start && viewEnd >= end) {
-            // The view is larger than the height of the RecyclerView.
-            return ((float) end - start) / helper.getDecoratedMeasurement(view);
-        } else if (viewStart < start) {
-            // The view is above the start of the RecyclerView.
-            return ((float) viewEnd - start) / helper.getDecoratedMeasurement(view);
-        } else {
-            // The view is below the end of the RecyclerView.
-            return ((float) end - viewStart) / helper.getDecoratedMeasurement(view);
-        }
-    }
-
-    @Override
-    public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
-        super.attachToRecyclerView(recyclerView);
-        mRecyclerView = recyclerView;
-    }
-
-    /**
-     * Returns a scroller specific to this {@code PagedSnapHelper}. This scroller is used for all
-     * smooth scrolling operations, including flings.
-     *
-     * @param layoutManager The {@link LayoutManager} associated with the attached
-     *                      {@link RecyclerView}.
-     * @return a {@link RecyclerView.SmoothScroller} which will handle the scrolling.
-     */
-    @Override
-    protected RecyclerView.SmoothScroller createScroller(@NonNull LayoutManager layoutManager) {
-        return new CarUiSmoothScroller(mContext);
-    }
-
-    /**
-     * Calculate the estimated scroll distance in each direction given velocities on both axes.
-     * This method will clamp the maximum scroll distance so that a single fling will never scroll
-     * more than one page.
-     *
-     * @param velocityX Fling velocity on the horizontal axis.
-     * @param velocityY Fling velocity on the vertical axis.
-     * @return An array holding the calculated distances in x and y directions respectively.
-     */
-    @Override
-    public int[] calculateScrollDistance(int velocityX, int velocityY) {
-        int[] outDist = super.calculateScrollDistance(velocityX, velocityY);
-
-        if (mRecyclerView == null) {
-            return outDist;
-        }
-
-        LayoutManager layoutManager = mRecyclerView.getLayoutManager();
-        if (layoutManager == null || layoutManager.getChildCount() == 0) {
-            return outDist;
-        }
-
-        int lastChildPosition = isAtEnd(layoutManager) ? 0 : layoutManager.getChildCount() - 1;
-
-        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
-        @NonNull View lastChild = Objects.requireNonNull(
-                layoutManager.getChildAt(lastChildPosition));
-        float percentageVisible = getPercentageVisible(lastChild, orientationHelper);
-
-        int maxDistance = layoutManager.getHeight();
-        if (percentageVisible > 0.f) {
-            // The max and min distance is the total height of the RecyclerView minus the height of
-            // the last child. This ensures that each scroll will never scroll more than a single
-            // page on the RecyclerView. That is, the max scroll will make the last child the
-            // first child and vice versa when scrolling the opposite way.
-            maxDistance -= layoutManager.getDecoratedMeasuredHeight(lastChild);
-        }
-
-        int minDistance = -maxDistance;
-
-        outDist[0] = clamp(outDist[0], minDistance, maxDistance);
-        outDist[1] = clamp(outDist[1], minDistance, maxDistance);
-
-        return outDist;
-    }
-
-    /**
-     * Estimates a position to which CarUiSnapHelper will try to snap to for a requested scroll
-     * distance.
-     *
-     * @param helper         The {@link OrientationHelper} that is created from the LayoutManager.
-     * @param scrollDistance The intended scroll distance.
-     *
-     * @return The diff between the target snap position and the current position.
-     */
-    public int estimateNextPositionDiffForScrollDistance(OrientationHelper helper,
-            int scrollDistance) {
-        float distancePerChild = computeDistancePerChild(helper.getLayoutManager(), helper);
-        if (distancePerChild <= 0) {
-            return 0;
-        }
-        return (int) Math.round(scrollDistance / distancePerChild);
-    }
-
-    /**
-     * This method is taken verbatim from the [androidx] {@link LinearSnapHelper} private method
-     * implementation.
-     *
-     * Computes an average pixel value to pass a single child.
-     * <p>
-     * Returns a negative value if it cannot be calculated.
-     *
-     * @param layoutManager The {@link RecyclerView.LayoutManager} associated with the attached
-     *                      {@link RecyclerView}.
-     * @param helper        The relevant {@link OrientationHelper} for the attached
-     *                      {@link RecyclerView.LayoutManager}.
-     *
-     * @return A float value that is the average number of pixels needed to scroll by one view in
-     * the relevant direction.
-     */
-    private float computeDistancePerChild(RecyclerView.LayoutManager layoutManager,
-            OrientationHelper helper) {
-        View minPosView = null;
-        View maxPosView = null;
-        int minPos = Integer.MAX_VALUE;
-        int maxPos = Integer.MIN_VALUE;
-        int childCount = layoutManager.getChildCount();
-        if (childCount == 0) {
-            return 1;
-        }
-
-        for (int i = 0; i < childCount; i++) {
-            View child = layoutManager.getChildAt(i);
-            final int pos = layoutManager.getPosition(child);
-            if (pos == RecyclerView.NO_POSITION) {
-                continue;
-            }
-            if (pos < minPos) {
-                minPos = pos;
-                minPosView = child;
-            }
-            if (pos > maxPos) {
-                maxPos = pos;
-                maxPosView = child;
-            }
-        }
-        if (minPosView == null || maxPosView == null) {
-            return 1;
-        }
-        int start = Math.min(helper.getDecoratedStart(minPosView),
-                helper.getDecoratedStart(maxPosView));
-        int end = Math.max(helper.getDecoratedEnd(minPosView),
-                helper.getDecoratedEnd(maxPosView));
-        int distance = end - start;
-        if (distance == 0) {
-            return 0;
-        }
-        return 1f * distance / ((maxPos - minPos) + 1);
-    }
-
-    /**
-     * Returns {@code true} if the RecyclerView is completely displaying the first item.
-     */
-    public boolean isAtStart(@Nullable LayoutManager layoutManager) {
-        if (layoutManager == null || layoutManager.getChildCount() == 0) {
-            return true;
-        }
-
-        @NonNull View firstChild = Objects.requireNonNull(layoutManager.getChildAt(0));
-        OrientationHelper orientationHelper =
-                layoutManager.canScrollVertically() ? getVerticalHelper(layoutManager)
-                        : getHorizontalHelper(layoutManager);
-
-        // Check that the first child is completely visible and is the first item in the list.
-        return orientationHelper.getDecoratedStart(firstChild)
-                >= orientationHelper.getStartAfterPadding() && layoutManager.getPosition(firstChild)
-                == 0;
-    }
-
-    /**
-     * Returns {@code true} if the RecyclerView is completely displaying the last item.
-     */
-    public boolean isAtEnd(@Nullable LayoutManager layoutManager) {
-        if (layoutManager == null || layoutManager.getChildCount() == 0) {
-            return true;
-        }
-
-        int childCount = layoutManager.getChildCount();
-        OrientationHelper orientationHelper =
-                layoutManager.canScrollVertically() ? getVerticalHelper(layoutManager)
-                        : getHorizontalHelper(layoutManager);
-
-        @NonNull View lastVisibleChild = Objects.requireNonNull(
-                layoutManager.getChildAt(childCount - 1));
-
-        // The list has reached the bottom if the last child that is visible is the last item
-        // in the list and it's fully shown.
-        return layoutManager.getPosition(lastVisibleChild) == (layoutManager.getItemCount() - 1)
-                && layoutManager.getDecoratedBottom(lastVisibleChild)
-                <= orientationHelper.getEndAfterPadding();
-    }
-
-    /**
-     * Returns an {@link OrientationHelper} that corresponds to the current scroll direction of the
-     * given {@link LayoutManager}.
-     */
-    @NonNull
-    private OrientationHelper getOrientationHelper(@NonNull LayoutManager layoutManager) {
-        return layoutManager.canScrollVertically()
-                ? getVerticalHelper(layoutManager)
-                : getHorizontalHelper(layoutManager);
-    }
-
-    @NonNull
-    private OrientationHelper getVerticalHelper(@NonNull LayoutManager layoutManager) {
-        if (mVerticalHelper == null || mVerticalHelper.getLayoutManager() != layoutManager) {
-            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
-        }
-        return mVerticalHelper;
-    }
-
-    @NonNull
-    private OrientationHelper getHorizontalHelper(@NonNull LayoutManager layoutManager) {
-        if (mHorizontalHelper == null || mHorizontalHelper.getLayoutManager() != layoutManager) {
-            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
-        }
-        return mHorizontalHelper;
-    }
-
-    /**
-     * Ensures that the given value falls between the range given by the min and max values. This
-     * method does not check that the min value is greater than or equal to the max value. If the
-     * parameters are not well-formed, this method's behavior is undefined.
-     *
-     * @param value The value to clamp.
-     * @param min   The minimum value the given value can be.
-     * @param max   The maximum value the given value can be.
-     * @return A number that falls between {@code min} or {@code max} or one of those values if the
-     * given value is less than or greater than {@code min} and {@code max} respectively.
-     */
-    private static int clamp(int value, int min, int max) {
-        return Math.max(min, Math.min(max, value));
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/DefaultScrollBar.java b/car-ui-lib/src/com/android/car/ui/recyclerview/DefaultScrollBar.java
deleted file mode 100644
index 912dda3..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/DefaultScrollBar.java
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview;
-
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
-
-import android.content.res.Resources;
-import android.os.Handler;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import androidx.annotation.IntRange;
-import androidx.recyclerview.widget.OrientationHelper;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-import com.android.car.ui.utils.CarUiUtils;
-
-/**
- * The default scroll bar widget for the {@link CarUiRecyclerView}.
- *
- * <p>Inspired by {@link androidx.car.widget.PagedListView}. Most pagination and scrolling logic
- * has been ported from the PLV with minor updates.
- */
-class DefaultScrollBar implements ScrollBar {
-
-    private float mButtonDisabledAlpha;
-    private CarUiSnapHelper mSnapHelper;
-
-    private View mScrollView;
-    private View mScrollTrack;
-    private View mScrollThumb;
-    private View mUpButton;
-    private View mDownButton;
-    private int mScrollbarThumbMinHeight;
-
-    private RecyclerView mRecyclerView;
-
-    private final Interpolator mPaginationInterpolator = new AccelerateDecelerateInterpolator();
-
-    private final int mRowsPerPage = -1;
-    private final Handler mHandler = new Handler();
-
-    private OrientationHelper mOrientationHelper;
-
-    private OnContinuousScrollListener mPageUpOnContinuousScrollListener;
-    private OnContinuousScrollListener mPageDownOnContinuousScrollListener;
-
-    @Override
-    public void initialize(RecyclerView rv, View scrollView) {
-        mRecyclerView = rv;
-
-        mScrollView = scrollView;
-
-        Resources res = rv.getContext().getResources();
-
-        mButtonDisabledAlpha = CarUiUtils.getFloat(res, R.dimen.car_ui_button_disabled_alpha);
-        mScrollbarThumbMinHeight = rv.getContext().getResources()
-                .getDimensionPixelSize(R.dimen.car_ui_scrollbar_min_thumb_height);
-
-        getRecyclerView().addOnScrollListener(mRecyclerViewOnScrollListener);
-        getRecyclerView().getRecycledViewPool().setMaxRecycledViews(0, 12);
-
-        mUpButton = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_page_up);
-        PaginateButtonClickListener paginateUpButtonClickListener =
-                new PaginateButtonClickListener(PaginationListener.PAGE_UP);
-        mUpButton.setOnClickListener(paginateUpButtonClickListener);
-        mPageUpOnContinuousScrollListener = new OnContinuousScrollListener(rv.getContext(),
-                paginateUpButtonClickListener);
-        mUpButton.setOnTouchListener(mPageUpOnContinuousScrollListener);
-
-        mDownButton = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_page_down);
-        PaginateButtonClickListener paginateDownButtonClickListener =
-                new PaginateButtonClickListener(PaginationListener.PAGE_DOWN);
-        mDownButton.setOnClickListener(paginateDownButtonClickListener);
-        mPageDownOnContinuousScrollListener = new OnContinuousScrollListener(rv.getContext(),
-                paginateDownButtonClickListener);
-        mDownButton.setOnTouchListener(mPageDownOnContinuousScrollListener);
-
-        mScrollTrack = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_track);
-        mScrollThumb = requireViewByRefId(mScrollView, R.id.car_ui_scrollbar_thumb);
-
-        mSnapHelper = new CarUiSnapHelper(rv.getContext());
-        getRecyclerView().setOnFlingListener(null);
-        mSnapHelper.attachToRecyclerView(getRecyclerView());
-
-        // enables fast scrolling.
-        FastScroller fastScroller = new FastScroller(mRecyclerView, mScrollTrack, mScrollView);
-        fastScroller.enable();
-
-        mScrollView.addOnLayoutChangeListener(
-                (View v,
-                        int left,
-                        int top,
-                        int right,
-                        int bottom,
-                        int oldLeft,
-                        int oldTop,
-                        int oldRight,
-                        int oldBottom) -> {
-                    mHandler.post(() -> updatePaginationButtons(/* animate= */ false));
-                });
-    }
-
-    public RecyclerView getRecyclerView() {
-        return mRecyclerView;
-    }
-
-    @Override
-    public void requestLayout() {
-        mScrollView.requestLayout();
-    }
-
-    @Override
-    public void setPadding(int paddingStart, int paddingEnd) {
-        mScrollView.setPadding(mScrollView.getPaddingLeft(), paddingStart,
-                mScrollView.getPaddingRight(), paddingEnd);
-    }
-
-    /**
-     * Sets whether or not the up button on the scroll bar is clickable.
-     *
-     * @param enabled {@code true} if the up button is enabled.
-     */
-    private void setUpEnabled(boolean enabled) {
-        // If the button is held down the button is disabled, the MotionEvent.ACTION_UP event on
-        // button release will not be sent to cancel pending scrolls. Manually cancel any pending
-        // scroll.
-        if (!enabled) {
-            mPageUpOnContinuousScrollListener.cancelPendingScroll();
-        }
-
-        mUpButton.setEnabled(enabled);
-        mUpButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
-    }
-
-    /**
-     * Sets whether or not the down button on the scroll bar is clickable.
-     *
-     * @param enabled {@code true} if the down button is enabled.
-     */
-    private void setDownEnabled(boolean enabled) {
-        // If the button is held down the button is disabled, the MotionEvent.ACTION_UP event on
-        // button release will not be sent to cancel pending scrolls. Manually cancel any pending
-        // scroll.
-        if (!enabled) {
-            mPageDownOnContinuousScrollListener.cancelPendingScroll();
-        }
-
-        mDownButton.setEnabled(enabled);
-        mDownButton.setAlpha(enabled ? 1f : mButtonDisabledAlpha);
-    }
-
-    /**
-     * Returns whether or not the down button on the scroll bar is clickable.
-     *
-     * @return {@code true} if the down button is enabled. {@code false} otherwise.
-     */
-    private boolean isDownEnabled() {
-        return mDownButton.isEnabled();
-    }
-
-    /**
-     * Listener for when the list should paginate.
-     */
-    interface PaginationListener {
-        int PAGE_UP = 0;
-        int PAGE_DOWN = 1;
-
-        /**
-         * Called when the linked view should be paged in the given direction
-         */
-        void onPaginate(int direction);
-    }
-
-    /**
-     * Sets the range, offset and extent of the scroll bar. The range represents the size of a
-     * container for the scrollbar thumb; offset is the distance from the start of the container to
-     * where the thumb should be; and finally, extent is the size of the thumb.
-     *
-     * <p>These values can be expressed in arbitrary units, so long as they share the same units.
-     * The values should also be positive.
-     *
-     * @param range   The range of the scrollbar's thumb
-     * @param offset  The offset of the scrollbar's thumb
-     * @param extent  The extent of the scrollbar's thumb
-     * @param animate Whether or not the thumb should animate from its current position to the
-     *                position specified by the given range, offset and extent.
-     */
-    private void setParameters(
-            @IntRange(from = 0) int range,
-            @IntRange(from = 0) int offset,
-            @IntRange(from = 0) int extent,
-            boolean animate) {
-        // Not laid out yet, so values cannot be calculated.
-        if (!mScrollView.isLaidOut()) {
-            return;
-        }
-
-        // If the scroll bars aren't visible, then no need to update.
-        if (mScrollView.getVisibility() == View.GONE || range == 0) {
-            return;
-        }
-
-        int thumbLength = calculateScrollThumbLength(range, extent);
-        int thumbOffset = calculateScrollThumbOffset(range, offset, thumbLength);
-
-        // Sets the size of the thumb and request a redraw if needed.
-        ViewGroup.LayoutParams lp = mScrollThumb.getLayoutParams();
-
-        if (lp.height != thumbLength) {
-            lp.height = thumbLength;
-            mScrollThumb.requestLayout();
-        }
-
-        moveY(mScrollThumb, thumbOffset, animate);
-    }
-
-    /**
-     * Calculates and returns how big the scroll bar thumb should be based on the given range and
-     * extent.
-     *
-     * @param range  The total amount of space the scroll bar is allowed to roam over.
-     * @param extent The amount of space that the scroll bar takes up relative to the range.
-     * @return The height of the scroll bar thumb in pixels.
-     */
-    private int calculateScrollThumbLength(int range, int extent) {
-        // Scale the length by the available space that the thumb can fill.
-        return Math.max(Math.round(((float) extent / range) * mScrollTrack.getHeight()),
-                mScrollbarThumbMinHeight);
-    }
-
-    /**
-     * Calculates and returns how much the scroll thumb should be offset from the top of where it
-     * has been laid out.
-     *
-     * @param range       The total amount of space the scroll bar is allowed to roam over.
-     * @param offset      The amount the scroll bar should be offset, expressed in the same units as
-     *                    the given range.
-     * @param thumbLength The current length of the thumb in pixels.
-     * @return The amount the thumb should be offset in pixels.
-     */
-    private int calculateScrollThumbOffset(int range, int offset, int thumbLength) {
-        // Ensure that if the user has reached the bottom of the list, then the scroll bar is
-        // aligned to the bottom as well. Otherwise, scale the offset appropriately.
-        // This offset will be a value relative to the parent of this scrollbar, so start by where
-        // the top of scrollbar track is.
-        return mScrollTrack.getTop()
-                + (isDownEnabled()
-                ? Math.round(((float) offset / range) * (mScrollTrack.getHeight() - thumbLength))
-                : mScrollTrack.getHeight() - thumbLength);
-    }
-
-    /**
-     * Moves the given view to the specified 'y' position.
-     */
-    private void moveY(final View view, float newPosition, boolean animate) {
-        final int duration = animate ? 200 : 0;
-        view.animate()
-                .y(newPosition)
-                .setDuration(duration)
-                .setInterpolator(mPaginationInterpolator)
-                .start();
-    }
-
-    private class PaginateButtonClickListener implements View.OnClickListener {
-        private final int mPaginateDirection;
-        private PaginationListener mPaginationListener;
-
-        PaginateButtonClickListener(int paginateDirection) {
-            this.mPaginateDirection = paginateDirection;
-        }
-
-        @Override
-        public void onClick(View v) {
-            if (mPaginationListener != null) {
-                mPaginationListener.onPaginate(mPaginateDirection);
-            }
-            if (mPaginateDirection == PaginationListener.PAGE_DOWN) {
-                pageDown();
-            } else if (mPaginateDirection == PaginationListener.PAGE_UP) {
-                pageUp();
-            }
-        }
-    }
-
-    private final RecyclerView.OnScrollListener mRecyclerViewOnScrollListener =
-            new RecyclerView.OnScrollListener() {
-                @Override
-                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-                    updatePaginationButtons(false);
-                }
-            };
-
-    /**
-     * Returns the page the given position is on, starting with page 0.
-     */
-    int getPage(int position) {
-        if (mRowsPerPage == -1) {
-            return -1;
-        }
-        if (mRowsPerPage == 0) {
-            return 0;
-        }
-        return position / mRowsPerPage;
-    }
-
-    private OrientationHelper getOrientationHelper(RecyclerView.LayoutManager layoutManager) {
-        if (mOrientationHelper == null || mOrientationHelper.getLayoutManager() != layoutManager) {
-            // CarUiRecyclerView is assumed to be a list that always vertically scrolls.
-            mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
-        }
-        return mOrientationHelper;
-    }
-
-    /**
-     * Scrolls the contents of the RecyclerView up a page. A page is defined as the height of the
-     * {@code CarUiRecyclerView}.
-     *
-     * <p>The resulting first item in the list will be snapped to so that it is completely visible.
-     * If this is not possible due to the first item being taller than the containing {@code
-     * CarUiRecyclerView}, then the snapping will not occur.
-     */
-    void pageUp() {
-        int currentOffset = getRecyclerView().computeVerticalScrollOffset();
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-        if (layoutManager == null || layoutManager.getChildCount() == 0 || currentOffset == 0) {
-            return;
-        }
-
-        // Use OrientationHelper to calculate scroll distance in order to match snapping behavior.
-        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
-        int screenSize = orientationHelper.getTotalSpace();
-        int scrollDistance = screenSize;
-        boolean isPageUpOverLongItem;
-        // The iteration order matters. In case where there are 2 items longer than screen size, we
-        // want to focus on upcoming view.
-        for (int i = 0; i < layoutManager.getChildCount(); i++) {
-            /*
-             * We treat child View longer than screen size differently:
-             * 1) When it enters screen, next pageUp will align its bottom with parent bottom;
-             * 2) When it leaves screen, next pageUp will align its top with parent top.
-             */
-            View child = layoutManager.getChildAt(i);
-            if (child.getHeight() > screenSize) {
-                if (orientationHelper.getDecoratedEnd(child) < screenSize) {
-                    // Child view bottom is entering screen. Align its bottom with parent bottom.
-                    scrollDistance = screenSize - orientationHelper.getDecoratedEnd(child);
-                } else if (-screenSize < orientationHelper.getDecoratedStart(child)
-                        && orientationHelper.getDecoratedStart(child) < 0) {
-                    // Child view top is about to enter screen - its distance to parent top
-                    // is less than a full scroll. Align child top with parent top.
-                    scrollDistance = Math.abs(orientationHelper.getDecoratedStart(child));
-                }
-
-                // There can be two items that are longer than the screen. We stop at the first one.
-                // This is affected by the iteration order.
-                // Distance should always be positive. Negate its value to scroll up.
-                mRecyclerView.smoothScrollBy(0, -scrollDistance);
-                return;
-            }
-        }
-
-        int nextPos = mSnapHelper.estimateNextPositionDiffForScrollDistance(orientationHelper,
-                -scrollDistance);
-        View currentPosView = getFirstFullyVisibleChild(orientationHelper);
-        int currentPos = currentPosView != null ? mRecyclerView.getLayoutManager().getPosition(
-                currentPosView) : 0;
-        mRecyclerView.smoothScrollToPosition(Math.max(0, currentPos + nextPos));
-    }
-
-    private View getFirstFullyVisibleChild(OrientationHelper helper) {
-        for (int i = 0; i < getRecyclerView().getChildCount(); i++) {
-            View child = getRecyclerView().getChildAt(i);
-            if (CarUiSnapHelper.getPercentageVisible(child, helper) == 1f) {
-                return getRecyclerView().getChildAt(i);
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Scrolls the contents of the RecyclerView down a page. A page is defined as the height of the
-     * {@code CarUiRecyclerView}.
-     *
-     * <p>This method will attempt to bring the last item in the list as the first item. If the
-     * current first item in the list is taller than the {@code CarUiRecyclerView}, then it will be
-     * scrolled the length of a page, but not snapped to.
-     */
-    void pageDown() {
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-        if (layoutManager == null || layoutManager.getChildCount() == 0) {
-            return;
-        }
-
-        OrientationHelper orientationHelper = getOrientationHelper(layoutManager);
-        int screenSize = orientationHelper.getTotalSpace();
-        int scrollDistance = screenSize;
-
-        // If the last item is partially visible, page down should bring it to the top.
-        View lastChild = layoutManager.getChildAt(layoutManager.getChildCount() - 1);
-        if (layoutManager.isViewPartiallyVisible(lastChild,
-                /* completelyVisible= */ false, /* acceptEndPointInclusion= */ false)) {
-            scrollDistance = orientationHelper.getDecoratedStart(lastChild)
-                    - orientationHelper.getStartAfterPadding();
-            if (scrollDistance <= 0) {
-                // - Scroll value is zero if the top of last item is aligned with top of the screen;
-                // - Scroll value can be negative if the child is longer than the screen size and
-                //   the visible area of the screen does not show the start of the child.
-                // Scroll to the next screen in both cases.
-                scrollDistance = screenSize;
-            }
-        }
-
-        // The iteration order matters. In case where there are 2 items longer than screen size, we
-        // want to focus on upcoming view (the one at the bottom of screen).
-        for (int i = layoutManager.getChildCount() - 1; i >= 0; i--) {
-            /* We treat child View longer than screen size differently:
-             * 1) When it enters screen, next pageDown will align its top with parent top;
-             * 2) When it leaves screen, next pageDown will align its bottom with parent bottom.
-             */
-            View child = layoutManager.getChildAt(i);
-            if (child.getHeight() > screenSize) {
-                if (orientationHelper.getDecoratedStart(child)
-                        - orientationHelper.getStartAfterPadding() > 0) {
-                    // Child view top is entering screen. Align its top with parent top.
-                    scrollDistance = orientationHelper.getDecoratedStart(lastChild)
-                            - orientationHelper.getStartAfterPadding();
-                } else if (screenSize < orientationHelper.getDecoratedEnd(child)
-                        && orientationHelper.getDecoratedEnd(child) < 2 * screenSize) {
-                    // Child view bottom is about to enter screen - its distance to parent bottom
-                    // is less than a full scroll. Align child bottom with parent bottom.
-                    scrollDistance = orientationHelper.getDecoratedEnd(child) - screenSize;
-                }
-                // There can be two items that are longer than the screen. We stop at the first one.
-                // This is affected by the iteration order.
-                break;
-            }
-        }
-
-        mRecyclerView.smoothScrollBy(0, scrollDistance);
-    }
-
-    /**
-     * Determines if scrollbar should be visible or not and shows/hides it accordingly. If this is
-     * being called as a result of adapter changes, it should be called after the new layout has
-     * been calculated because the method of determining scrollbar visibility uses the current
-     * layout. If this is called after an adapter change but before the new layout, the visibility
-     * determination may not be correct.
-     *
-     * @param animate {@code true} if the scrollbar should animate to its new position. {@code
-     *                false} if no animation is used
-     */
-    private void updatePaginationButtons(boolean animate) {
-
-        boolean isAtStart = isAtStart();
-        boolean isAtEnd = isAtEnd();
-        RecyclerView.LayoutManager layoutManager = getRecyclerView().getLayoutManager();
-
-        if ((isAtStart && isAtEnd) || layoutManager == null || layoutManager.getItemCount() == 0) {
-            mScrollView.setVisibility(View.INVISIBLE);
-        } else {
-            mScrollView.setVisibility(View.VISIBLE);
-        }
-        setUpEnabled(!isAtStart);
-        setDownEnabled(!isAtEnd);
-
-        if (layoutManager == null) {
-            return;
-        }
-
-        if (layoutManager.canScrollVertically()) {
-            setParameters(
-                    getRecyclerView().computeVerticalScrollRange(),
-                    getRecyclerView().computeVerticalScrollOffset(),
-                    getRecyclerView().computeVerticalScrollExtent(),
-                    animate);
-        } else {
-            setParameters(
-                    getRecyclerView().computeHorizontalScrollRange(),
-                    getRecyclerView().computeHorizontalScrollOffset(),
-                    getRecyclerView().computeHorizontalScrollExtent(),
-                    animate);
-        }
-
-        mScrollView.invalidate();
-    }
-
-    /**
-     * Returns {@code true} if the RecyclerView is completely displaying the first item.
-     */
-    boolean isAtStart() {
-        return mSnapHelper.isAtStart(getRecyclerView().getLayoutManager());
-    }
-
-    /**
-     * Returns {@code true} if the RecyclerView is completely displaying the last item.
-     */
-    boolean isAtEnd() {
-        return mSnapHelper.isAtEnd(getRecyclerView().getLayoutManager());
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/OnContinuousScrollListener.java b/car-ui-lib/src/com/android/car/ui/recyclerview/OnContinuousScrollListener.java
deleted file mode 100644
index c7f66bd..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/OnContinuousScrollListener.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.recyclerview;
-
-import android.content.Context;
-import android.os.Handler;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnTouchListener;
-
-import androidx.annotation.NonNull;
-
-import com.android.car.ui.R;
-
-/**
- * A class, that can be used as a TouchListener on any view (e.g. a Button). It periodically calls
- * the provided clickListener. The first callback is fired after the initial Delay, and subsequent
- * ones after the defined interval.
- */
-public class OnContinuousScrollListener implements OnTouchListener {
-
-    private final Handler mHandler = new Handler();
-
-    private final int mInitialDelay;
-    private final int mRepeatInterval;
-    private final OnClickListener mOnClickListener;
-    private View mTouchedView;
-    private boolean mIsLongPressed;
-
-    /**
-     * Notifies listener and self schedules to be re-run at next callback interval.
-     */
-    private final Runnable mPeriodicRunnable = new Runnable() {
-        @Override
-        public void run() {
-            if (mTouchedView.isEnabled()) {
-                mHandler.postDelayed(this, mRepeatInterval);
-                mOnClickListener.onClick(mTouchedView);
-                mIsLongPressed = true;
-            } else {
-                mIsLongPressed = false;
-            }
-        }
-    };
-
-    /**
-     * @param clickListener The OnClickListener, that will be called periodically
-     */
-    public OnContinuousScrollListener(@NonNull Context context,
-            @NonNull OnClickListener clickListener) {
-        this.mInitialDelay = context.getResources().getInteger(
-                R.integer.car_ui_scrollbar_longpress_initial_delay);
-
-        this.mRepeatInterval = context.getResources().getInteger(
-                R.integer.car_ui_scrollbar_longpress_repeat_interval);
-
-        if (mInitialDelay < 0 || mRepeatInterval < 0) {
-            throw new IllegalArgumentException("negative intervals are not allowed");
-        }
-        this.mOnClickListener = clickListener;
-    }
-
-    /**
-     * Cancel pending scroll operations. Any scroll operations that were scheduled to possibly be
-     * performed, as part of a continuous scroll, will be cancelled.
-     */
-    public void cancelPendingScroll() {
-        mHandler.removeCallbacks(mPeriodicRunnable);
-        mIsLongPressed = false;
-    }
-
-    @Override
-    public boolean onTouch(View view, MotionEvent motionEvent) {
-        mTouchedView = view;
-        switch (motionEvent.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                mHandler.removeCallbacks(mPeriodicRunnable);
-                mHandler.postDelayed(mPeriodicRunnable, mInitialDelay);
-                mTouchedView.setPressed(true);
-                return true;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                if (!mIsLongPressed) {
-                    mOnClickListener.onClick(view);
-                }
-                mHandler.removeCallbacks(mPeriodicRunnable);
-                mTouchedView.setPressed(false);
-                mIsLongPressed = false;
-                return true;
-        }
-        return false;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollBar.java b/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollBar.java
deleted file mode 100644
index ce58897..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/ScrollBar.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview;
-
-import android.view.View;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-/**
- * An abstract class that defines required contract for a custom scroll bar for the {@link
- * CarUiRecyclerView}. All custom scroll bar must inherit from this class.
- */
-public interface ScrollBar {
-    /**
-     * The concrete class should implement this method to initialize configuration of a scrollbar
-     * view.
-     */
-    void initialize(RecyclerView recyclerView, View scrollView);
-
-    /**
-     * Requests layout of the scrollbar. Should be called when there's been a change that will
-     * affect
-     * the size of the scrollbar view.
-     */
-    void requestLayout();
-
-    /** Sets the padding of the scrollbar, relative to the padding of the RecyclerView. */
-    void setPadding(int padddingStart, int paddingEnd);
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java
deleted file mode 100644
index d36346e..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridDividerItemDecoration.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview.decorations.grid;
-
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-
-import java.util.Objects;
-
-/** Adds interior dividers to a RecyclerView with a GridLayoutManager. */
-public class GridDividerItemDecoration extends RecyclerView.ItemDecoration {
-
-    private final Drawable mHorizontalDivider;
-    private final Drawable mVerticalDivider;
-    private int mNumColumns;
-
-    /**
-     * Sole constructor. Takes in {@link Drawable} objects to be used as horizontal and vertical
-     * dividers.
-     *
-     * @param horizontalDivider A divider {@code Drawable} to be drawn on the rows of the grid of
-     * the
-     * RecyclerView
-     * @param verticalDivider A divider {@code Drawable} to be drawn on the columns of the grid of
-     * the
-     * RecyclerView
-     * @param numColumns The number of columns in the grid of the RecyclerView
-     */
-    public GridDividerItemDecoration(
-            Drawable horizontalDivider, Drawable verticalDivider, int numColumns) {
-        this.mHorizontalDivider = horizontalDivider;
-        this.mVerticalDivider = verticalDivider;
-        this.mNumColumns = numColumns;
-    }
-
-    /**
-     * Draws horizontal and/or vertical dividers onto the parent RecyclerView.
-     *
-     * @param canvas The {@link Canvas} onto which dividers will be drawn
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
-     */
-    @Override
-    public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
-        drawVerticalDividers(canvas, parent);
-        drawHorizontalDividers(canvas, parent);
-    }
-
-    /**
-     * Determines the size and location of offsets between items in the parent RecyclerView.
-     *
-     * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
-     */
-    @Override
-    public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
-        outRect.set(
-                0, 0, mHorizontalDivider.getIntrinsicWidth(),
-                mHorizontalDivider.getIntrinsicHeight());
-    }
-
-    /**
-     * Adds horizontal dividers to a RecyclerView with a GridLayoutManager or its subclass.
-     *
-     * @param canvas The {@link Canvas} onto which dividers will be drawn
-     * @param parent The RecyclerView onto which dividers are being added
-     */
-    private void drawHorizontalDividers(Canvas canvas, RecyclerView parent) {
-        RecyclerView.LayoutManager layoutManager = Objects.requireNonNull(
-                parent.getLayoutManager());
-        int childCount = layoutManager.getChildCount();
-        int rowCount = childCount / mNumColumns;
-        int lastRowChildCount = childCount % mNumColumns;
-        int lastColumn = Math.min(childCount, mNumColumns);
-
-        for (int i = 1; i < lastColumn; i++) {
-            int lastRowChildIndex;
-            if (i < lastRowChildCount) {
-                lastRowChildIndex = i + (rowCount * mNumColumns);
-            } else {
-                lastRowChildIndex = i + ((rowCount - 1) * mNumColumns);
-            }
-
-
-            View firstRowChild = layoutManager.getChildAt(i);
-            View lastRowChild = layoutManager.getChildAt(lastRowChildIndex);
-
-            int dividerTop =
-                    firstRowChild.getTop() + (int) parent.getContext().getResources().getDimension(
-                            R.dimen.car_ui_recyclerview_divider_top_margin);
-            int dividerRight = firstRowChild.getLeft();
-            int dividerLeft = dividerRight - mHorizontalDivider.getIntrinsicWidth();
-            int dividerBottom = lastRowChild.getBottom()
-                    - (int) parent.getContext().getResources().getDimension(
-                    R.dimen.car_ui_recyclerview_divider_bottom_margin);
-
-            mHorizontalDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
-            mHorizontalDivider.draw(canvas);
-        }
-    }
-
-    public void setNumOfColumns(int numberOfColumns) {
-        mNumColumns = numberOfColumns;
-    }
-
-    /**
-     * Adds vertical dividers to a RecyclerView with a GridLayoutManager or its subclass.
-     *
-     * @param canvas The {@link Canvas} onto which dividers will be drawn
-     * @param parent The RecyclerView onto which dividers are being added
-     */
-    private void drawVerticalDividers(Canvas canvas, RecyclerView parent) {
-        RecyclerView.LayoutManager layoutManager = Objects.requireNonNull(
-                parent.getLayoutManager());
-        double childCount = layoutManager.getChildCount();
-        double rowCount = Math.ceil(childCount / mNumColumns);
-        int rightmostChildIndex;
-        for (int i = 1; i <= rowCount; i++) {
-            // we dont want the divider on top of first row.
-            if (i == 1) {
-                continue;
-            }
-            if (i == rowCount) {
-                rightmostChildIndex = ((i - 1) * mNumColumns) - 1;
-            } else {
-                rightmostChildIndex = (i * mNumColumns) - 1;
-            }
-
-            View leftmostChild = layoutManager.getChildAt(mNumColumns * (i - 1));
-            View rightmostChild = layoutManager.getChildAt(rightmostChildIndex);
-
-            // draws on top of each row.
-            int dividerLeft =
-                    leftmostChild.getLeft() + (int) parent.getContext().getResources().getDimension(
-                            R.dimen.car_ui_recyclerview_divider_start_margin);
-            int dividerBottom = leftmostChild.getTop();
-            int dividerTop = dividerBottom - mVerticalDivider.getIntrinsicHeight();
-            int dividerRight = rightmostChild.getRight()
-                    - (int) parent.getContext().getResources().getDimension(
-                    R.dimen.car_ui_recyclerview_divider_end_margin);
-
-            mVerticalDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
-            mVerticalDivider.draw(canvas);
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java
deleted file mode 100644
index 3dd6c19..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/grid/GridOffsetItemDecoration.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview.decorations.grid;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import androidx.annotation.IntDef;
-import androidx.recyclerview.widget.RecyclerView;
-
-import java.lang.annotation.Retention;
-
-/** Adds an offset to the top of a RecyclerView with a GridLayoutManager or its subclass. */
-public class GridOffsetItemDecoration extends RecyclerView.ItemDecoration {
-
-    private int mOffsetPx;
-    private Drawable mOffsetDrawable;
-    private int mNumColumns;
-    @OffsetPosition
-    private final int mOffsetPosition;
-
-    /** The possible values for setScrollbarPosition. */
-    @IntDef({
-            OffsetPosition.START,
-            OffsetPosition.END,
-    })
-    @Retention(SOURCE)
-    public @interface OffsetPosition {
-        /** Position the offset to the start of the screen. */
-        int START = 0;
-
-        /** Position offset to the end of the screen. */
-        int END = 1;
-    }
-
-    /**
-     * Constructor that takes in the size of the offset to be added to the top of the RecyclerView.
-     *
-     * @param offsetPx The size of the offset to be added to the top of the RecyclerView in pixels
-     * @param numColumns The number of columns in the grid of the RecyclerView
-     * @param offsetPosition Position where offset needs to be applied.
-     */
-    public GridOffsetItemDecoration(int offsetPx, int numColumns, int offsetPosition) {
-        this.mOffsetPx = offsetPx;
-        this.mNumColumns = numColumns;
-        this.mOffsetPosition = offsetPosition;
-    }
-
-    /**
-     * Constructor that takes in a {@link Drawable} to be drawn at the top of the RecyclerView.
-     *
-     * @param offsetDrawable The {@code Drawable} to be added to the top of the RecyclerView
-     * @param numColumns The number of columns in the grid of the RecyclerView
-     */
-    public GridOffsetItemDecoration(Drawable offsetDrawable, int numColumns, int offsetPosition) {
-        this.mOffsetDrawable = offsetDrawable;
-        this.mNumColumns = numColumns;
-        this.mOffsetPosition = offsetPosition;
-    }
-
-    public void setNumOfColumns(int numberOfColumns) {
-        mNumColumns = numberOfColumns;
-    }
-
-    /**
-     * Determines the size and the location of the offset to be added to the top of the
-     * RecyclerView.
-     *
-     * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
-     */
-    @Override
-    public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
-        super.getItemOffsets(outRect, view, parent, state);
-
-        if (mOffsetPosition == OffsetPosition.START) {
-            boolean childIsInTopRow = parent.getChildAdapterPosition(view) < mNumColumns;
-            if (childIsInTopRow) {
-                if (mOffsetPx > 0) {
-                    outRect.top = mOffsetPx;
-                } else if (mOffsetDrawable != null) {
-                    outRect.top = mOffsetDrawable.getIntrinsicHeight();
-                }
-            }
-            return;
-        }
-
-        int childCount = state.getItemCount();
-        int lastRowChildCount = getLastRowChildCount(childCount);
-
-        boolean childIsInBottomRow =
-                parent.getChildAdapterPosition(view) >= childCount - lastRowChildCount;
-        if (childIsInBottomRow) {
-            if (mOffsetPx > 0) {
-                outRect.bottom = mOffsetPx;
-            } else if (mOffsetDrawable != null) {
-                outRect.bottom = mOffsetDrawable.getIntrinsicHeight();
-            }
-        }
-    }
-
-    @Override
-    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
-        super.onDraw(c, parent, state);
-        if (mOffsetDrawable == null) {
-            return;
-        }
-
-        int parentLeft = parent.getPaddingLeft();
-        int parentRight = parent.getWidth() - parent.getPaddingRight();
-
-        if (mOffsetPosition == OffsetPosition.START) {
-
-            int parentTop = parent.getPaddingTop();
-            int offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
-
-            mOffsetDrawable.setBounds(parentLeft, parentTop, parentRight, offsetDrawableBottom);
-            mOffsetDrawable.draw(c);
-            return;
-        }
-
-        int childCount = state.getItemCount();
-        int lastRowChildCount = getLastRowChildCount(childCount);
-
-        int offsetDrawableTop = 0;
-        int offsetDrawableBottom = 0;
-
-        for (int i = childCount - lastRowChildCount; i < childCount; i++) {
-            View child = parent.getChildAt(i);
-            offsetDrawableTop = child.getBottom();
-            offsetDrawableBottom = offsetDrawableTop + mOffsetDrawable.getIntrinsicHeight();
-        }
-
-        mOffsetDrawable.setBounds(parentLeft, offsetDrawableTop, parentRight, offsetDrawableBottom);
-        mOffsetDrawable.draw(c);
-    }
-
-    private int getLastRowChildCount(int itemCount) {
-        int lastRowChildCount = itemCount % mNumColumns;
-        if (lastRowChildCount == 0) {
-            lastRowChildCount = mNumColumns;
-        }
-
-        return lastRowChildCount;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java
deleted file mode 100644
index e79468f..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearDividerItemDecoration.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview.decorations.linear;
-
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-
-/** Adds interior dividers to a RecyclerView with a LinearLayoutManager or its subclass. */
-public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration {
-
-    private final Drawable mDivider;
-    private int mOrientation;
-
-    /**
-     * Sole constructor. Takes in a {@link Drawable} to be used as the interior
-     * car_ui_recyclerview_divider.
-     *
-     * @param divider A car_ui_recyclerview_divider {@code Drawable} to be drawn on the
-     * RecyclerView
-     */
-    public LinearDividerItemDecoration(Drawable divider) {
-        this.mDivider = divider;
-    }
-
-    /**
-     * Draws horizontal or vertical dividers onto the parent RecyclerView.
-     *
-     * @param canvas The {@link Canvas} onto which dividers will be drawn
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
-     */
-    @Override
-    public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
-        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
-            drawHorizontalDividers(canvas, parent);
-        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
-            drawVerticalDividers(canvas, parent);
-        }
-    }
-
-    /**
-     * Determines the size and location of offsets between items in the parent RecyclerView.
-     *
-     * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
-     */
-    @Override
-    public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
-        super.getItemOffsets(outRect, view, parent, state);
-
-        if (parent.getChildAdapterPosition(view) == 0) {
-            return;
-        }
-
-        mOrientation = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
-        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
-            outRect.left = mDivider.getIntrinsicWidth();
-        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
-            outRect.top = mDivider.getIntrinsicHeight();
-        }
-    }
-
-    /**
-     * Adds dividers to a RecyclerView with a LinearLayoutManager or its subclass oriented
-     * horizontally.
-     *
-     * @param canvas The {@link Canvas} onto which horizontal dividers will be drawn
-     * @param parent The RecyclerView onto which horizontal dividers are being added
-     */
-    private void drawHorizontalDividers(Canvas canvas, RecyclerView parent) {
-        int parentTop =
-                parent.getPaddingTop() + (int) parent.getContext().getResources().getDimension(
-                        R.dimen.car_ui_recyclerview_divider_top_margin);
-        int parentBottom = parent.getHeight() - parent.getPaddingBottom()
-                - (int) parent.getContext().getResources().getDimension(
-                R.dimen.car_ui_recyclerview_divider_bottom_margin);
-
-        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
-        int childCount = layoutManager.getChildCount();
-        for (int i = 0; i < childCount - 1; i++) {
-            View child = layoutManager.getChildAt(i);
-
-            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
-
-            int parentLeft = child.getRight() + params.rightMargin;
-            int parentRight = parentLeft + mDivider.getIntrinsicWidth();
-
-            mDivider.setBounds(parentLeft, parentTop, parentRight, parentBottom);
-            mDivider.draw(canvas);
-        }
-    }
-
-    /**
-     * Adds dividers to a RecyclerView with a LinearLayoutManager or its subclass oriented
-     * vertically.
-     *
-     * @param canvas The {@link Canvas} onto which vertical dividers will be drawn
-     * @param parent The RecyclerView onto which vertical dividers are being added
-     */
-    private void drawVerticalDividers(Canvas canvas, RecyclerView parent) {
-        int parentLeft =
-                parent.getPaddingLeft() + (int) parent.getContext().getResources().getDimension(
-                        R.dimen.car_ui_recyclerview_divider_start_margin);
-        int parentRight = parent.getWidth() - parent.getPaddingRight()
-                - (int) parent.getContext().getResources().getDimension(
-                R.dimen.car_ui_recyclerview_divider_end_margin);
-
-        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
-        int childCount = layoutManager.getChildCount();
-        for (int i = 0; i < childCount - 1; i++) {
-            View child = layoutManager.getChildAt(i);
-
-            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
-
-            int parentTop = child.getBottom() + params.bottomMargin;
-            int parentBottom = parentTop + mDivider.getIntrinsicHeight();
-
-            mDivider.setBounds(parentLeft, parentTop, parentRight, parentBottom);
-            mDivider.draw(canvas);
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java b/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java
deleted file mode 100644
index 37ed388..0000000
--- a/car-ui-lib/src/com/android/car/ui/recyclerview/decorations/linear/LinearOffsetItemDecoration.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.recyclerview.decorations.linear;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import androidx.annotation.IntDef;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import java.lang.annotation.Retention;
-
-/**
- * Adds an offset to the start of a RecyclerView using a LinearLayoutManager or its subclass.
- *
- * <p>If the RecyclerView.LayoutManager is oriented vertically, the offset will be added to the top
- * of the RecyclerView. If the LayoutManager is oriented horizontally, the offset will be added to
- * the left of the RecyclerView.
- */
-public class LinearOffsetItemDecoration extends RecyclerView.ItemDecoration {
-
-    private int mOffsetPx;
-    private Drawable mOffsetDrawable;
-    private int mOrientation;
-    @OffsetPosition
-    private int mOffsetPosition;
-
-    /** The possible values for setScrollbarPosition. */
-    @IntDef({
-            OffsetPosition.START,
-            OffsetPosition.END,
-    })
-    @Retention(SOURCE)
-    public @interface OffsetPosition {
-        /** Position the offset to the start of the screen. */
-        int START = 0;
-
-        /** Position offset to the end of the screen. */
-        int END = 1;
-    }
-
-    /**
-     * Constructor that takes in the size of the offset to be added to the start of the
-     * RecyclerView.
-     *
-     * @param offsetPx The size of the offset to be added to the start of the RecyclerView in pixels
-     * @param offsetPosition Position where offset needs to be applied.
-     */
-    public LinearOffsetItemDecoration(int offsetPx, int offsetPosition) {
-        this.mOffsetPx = offsetPx;
-        this.mOffsetPosition = offsetPosition;
-    }
-
-    /**
-     * Constructor that takes in a {@link Drawable} to be drawn at the start of the RecyclerView.
-     *
-     * @param offsetDrawable The {@code Drawable} to be added to the start of the RecyclerView
-     */
-    public LinearOffsetItemDecoration(Drawable offsetDrawable) {
-        this.mOffsetDrawable = offsetDrawable;
-    }
-
-    /**
-     * Determines the size and location of the offset to be added to the start of the RecyclerView.
-     *
-     * @param outRect The {@link Rect} of offsets to be added around the child view
-     * @param view The child view to be decorated with an offset
-     * @param parent The RecyclerView onto which dividers are being added
-     * @param state The current RecyclerView.State of the RecyclerView
-     */
-    @Override
-    public void getItemOffsets(
-            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
-        super.getItemOffsets(outRect, view, parent, state);
-
-        if (mOffsetPosition == OffsetPosition.START && parent.getChildAdapterPosition(view) > 0) {
-            return;
-        }
-
-        int itemCount = state.getItemCount();
-        if (mOffsetPosition == OffsetPosition.END
-                && parent.getChildAdapterPosition(view) != itemCount - 1) {
-            return;
-        }
-
-        mOrientation = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
-        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
-            if (mOffsetPx > 0) {
-                if (mOffsetPosition == OffsetPosition.START) {
-                    outRect.left = mOffsetPx;
-                } else {
-                    outRect.right = mOffsetPx;
-                }
-            } else if (mOffsetDrawable != null) {
-                if (mOffsetPosition == OffsetPosition.START) {
-                    outRect.left = mOffsetDrawable.getIntrinsicWidth();
-                } else {
-                    outRect.right = mOffsetDrawable.getIntrinsicWidth();
-                }
-            }
-        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
-            if (mOffsetPx > 0) {
-                if (mOffsetPosition == OffsetPosition.START) {
-                    outRect.top = mOffsetPx;
-                } else {
-                    outRect.bottom = mOffsetPx;
-                }
-            } else if (mOffsetDrawable != null) {
-                if (mOffsetPosition == OffsetPosition.START) {
-                    outRect.top = mOffsetDrawable.getIntrinsicHeight();
-                } else {
-                    outRect.bottom = mOffsetDrawable.getIntrinsicHeight();
-                }
-            }
-        }
-    }
-
-    /**
-     * Draws horizontal or vertical offset onto the start of the parent RecyclerView.
-     *
-     * @param c The {@link Canvas} onto which an offset will be drawn
-     * @param parent The RecyclerView onto which an offset is being added
-     * @param state The current RecyclerView.State of the RecyclerView
-     */
-    @Override
-    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
-        super.onDraw(c, parent, state);
-        if (mOffsetDrawable == null) {
-            return;
-        }
-
-        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
-            drawOffsetHorizontal(c, parent);
-        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
-            drawOffsetVertical(c, parent);
-        }
-    }
-
-    private void drawOffsetHorizontal(Canvas canvas, RecyclerView parent) {
-        int parentTop = parent.getPaddingTop();
-        int parentBottom = parent.getHeight() - parent.getPaddingBottom();
-        int parentLeft = 0;
-        int offsetDrawableRight = 0;
-
-        if (mOffsetPosition == OffsetPosition.START) {
-            parentLeft = parent.getPaddingLeft();
-            offsetDrawableRight = parentLeft + mOffsetDrawable.getIntrinsicWidth();
-        } else {
-            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
-            View lastChild = layoutManager.getChildAt(layoutManager.getChildCount() - 1);
-            RecyclerView.LayoutParams lastChildLayoutParams =
-                    (RecyclerView.LayoutParams) lastChild.getLayoutParams();
-            parentLeft = lastChild.getRight() + lastChildLayoutParams.rightMargin;
-            offsetDrawableRight = parentLeft + mOffsetDrawable.getIntrinsicWidth();
-        }
-
-        mOffsetDrawable.setBounds(parentLeft, parentTop, offsetDrawableRight, parentBottom);
-        mOffsetDrawable.draw(canvas);
-    }
-
-    private void drawOffsetVertical(Canvas canvas, RecyclerView parent) {
-        int parentLeft = parent.getPaddingLeft();
-        int parentRight = parent.getWidth() - parent.getPaddingRight();
-
-        int parentTop = 0;
-        int offsetDrawableBottom = 0;
-
-        if (mOffsetPosition == OffsetPosition.START) {
-            parentTop = parent.getPaddingTop();
-            offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
-        } else {
-            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
-            View lastChild = layoutManager.getChildAt(layoutManager.getChildCount() - 1);
-            RecyclerView.LayoutParams lastChildLayoutParams =
-                    (RecyclerView.LayoutParams) lastChild.getLayoutParams();
-            parentTop = lastChild.getBottom() + lastChildLayoutParams.bottomMargin;
-            offsetDrawableBottom = parentTop + mOffsetDrawable.getIntrinsicHeight();
-        }
-
-        mOffsetDrawable.setBounds(parentLeft, parentTop, parentRight, offsetDrawableBottom);
-        mOffsetDrawable.draw(canvas);
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItem.java b/car-ui-lib/src/com/android/car/ui/toolbar/MenuItem.java
deleted file mode 100644
index 20d6847..0000000
--- a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItem.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.toolbar;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-import android.widget.Toast;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.ui.R;
-import com.android.car.ui.utils.CarUxRestrictionsUtil;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Represents a button to display in the {@link Toolbar}.
- *
- * <p>There are currently 3 types of buttons: icon, text, and switch. Using
- * {@link Builder#setCheckable()} will ensure that you get a switch, after that
- * {@link Builder#setIcon(int)} will ensure an icon, and anything left just requires
- * {@link Builder#setTitle(int)}.
- *
- * <p>Each MenuItem has a {@link DisplayBehavior} that controls if it appears on the {@link Toolbar}
- * itself, or it's overflow menu.
- *
- * <p>If you require a search or settings button, you should use
- * {@link Builder#setToSearch()} or
- * {@link Builder#setToSettings()}.
- *
- * <p>Some properties can be changed after the creating a MenuItem, but others require being set
- * with a {@link Builder}.
- */
-public class MenuItem {
-
-    private final Context mContext;
-    private final boolean mIsCheckable;
-    private final boolean mIsActivatable;
-    private final boolean mIsSearch;
-    private final boolean mShowIconAndTitle;
-    private final boolean mIsTinted;
-    @CarUxRestrictions.CarUxRestrictionsInfo
-
-    private int mId;
-    private CarUxRestrictions mCurrentRestrictions;
-    // This is a WeakReference to allow the Toolbar (and by extension, the whole screen
-    // the toolbar is on) to be garbage-collected if the MenuItem is held past the
-    // lifecycle of the toolbar.
-    private WeakReference<Listener> mListener = new WeakReference<>(null);
-    private CharSequence mTitle;
-    private Drawable mIcon;
-    private OnClickListener mOnClickListener;
-    private DisplayBehavior mDisplayBehavior;
-    private int mUxRestrictions;
-    private boolean mIsEnabled;
-    private boolean mIsChecked;
-    private boolean mIsVisible;
-    private boolean mIsActivated;
-
-    private MenuItem(Builder builder) {
-        mContext = builder.mContext;
-        mId = builder.mId;
-        mIsCheckable = builder.mIsCheckable;
-        mIsActivatable = builder.mIsActivatable;
-        mTitle = builder.mTitle;
-        mIcon = builder.mIcon;
-        mOnClickListener = builder.mOnClickListener;
-        mDisplayBehavior = builder.mDisplayBehavior;
-        mIsEnabled = builder.mIsEnabled;
-        mIsChecked = builder.mIsChecked;
-        mIsVisible = builder.mIsVisible;
-        mIsActivated = builder.mIsActivated;
-        mIsSearch = builder.mIsSearch;
-        mShowIconAndTitle = builder.mShowIconAndTitle;
-        mIsTinted = builder.mIsTinted;
-        mUxRestrictions = builder.mUxRestrictions;
-
-        mCurrentRestrictions = CarUxRestrictionsUtil.getInstance(mContext).getCurrentRestrictions();
-    }
-
-    private void update() {
-        Listener listener = mListener.get();
-        if (listener != null) {
-            listener.onMenuItemChanged();
-        }
-    }
-
-    /** Sets the id, which is purely for the client to distinguish MenuItems with.  */
-    public void setId(int id) {
-        mId = id;
-        update();
-    }
-
-    /** Gets the id, which is purely for the client to distinguish MenuItems with. */
-    public int getId() {
-        return mId;
-    }
-
-    /** Returns whether the MenuItem is enabled */
-    public boolean isEnabled() {
-        return mIsEnabled;
-    }
-
-    /** Sets whether the MenuItem is enabled */
-    public void setEnabled(boolean enabled) {
-        mIsEnabled = enabled;
-
-        update();
-    }
-
-    /** Returns whether the MenuItem is checkable. If it is, it will be displayed as a switch. */
-    public boolean isCheckable() {
-        return mIsCheckable;
-    }
-
-    /**
-     * Returns whether the MenuItem is currently checked. Only valid if {@link #isCheckable()}
-     * is true.
-     */
-    public boolean isChecked() {
-        return mIsChecked;
-    }
-
-    /**
-     * Sets whether or not the MenuItem is checked.
-     * @throws IllegalStateException When {@link #isCheckable()} is false.
-     */
-    public void setChecked(boolean checked) {
-        if (!isCheckable()) {
-            throw new IllegalStateException("Cannot call setChecked() on a non-checkable MenuItem");
-        }
-
-        mIsChecked = checked;
-
-        update();
-    }
-
-    public boolean isTinted() {
-        return mIsTinted;
-    }
-
-    /** Returns whether or not the MenuItem is visible */
-    public boolean isVisible() {
-        return mIsVisible;
-    }
-
-    /** Sets whether or not the MenuItem is visible */
-    public void setVisible(boolean visible) {
-        mIsVisible = visible;
-
-        update();
-    }
-
-    /**
-     * Returns whether the MenuItem is activatable. If it is, it's every click will toggle
-     * the MenuItem's View to appear activated or not.
-     */
-    public boolean isActivatable() {
-        return mIsActivatable;
-    }
-
-    /** Returns whether or not this view is selected. Toggles after every click */
-    public boolean isActivated() {
-        return mIsActivated;
-    }
-
-    /** Sets the MenuItem as activated and updates it's View to the activated state */
-    public void setActivated(boolean activated) {
-        if (!isActivatable()) {
-            throw new IllegalStateException(
-                    "Cannot call setActivated() on a non-activatable MenuItem");
-        }
-
-        mIsActivated = activated;
-
-        update();
-    }
-
-    /** Gets the title of this MenuItem. */
-    public CharSequence getTitle() {
-        return mTitle;
-    }
-
-    /** Sets the title of this MenuItem. */
-    public void setTitle(CharSequence title) {
-        mTitle = title;
-
-        update();
-    }
-
-    /** Sets the title of this MenuItem to a string resource. */
-    public void setTitle(int resId) {
-        setTitle(mContext.getString(resId));
-    }
-
-    /** Sets the UxRestrictions of this MenuItem. */
-    public void setUxRestrictions(@CarUxRestrictions.CarUxRestrictionsInfo int uxRestrictions) {
-        if (mUxRestrictions != uxRestrictions) {
-            mUxRestrictions = uxRestrictions;
-            update();
-        }
-    }
-
-    @CarUxRestrictions.CarUxRestrictionsInfo
-    public int getUxRestrictions() {
-        return mUxRestrictions;
-    }
-
-    /** Gets the current {@link OnClickListener} */
-    public OnClickListener getOnClickListener() {
-        return mOnClickListener;
-    }
-
-    public boolean isShowingIconAndTitle() {
-        return mShowIconAndTitle;
-    }
-
-    /** Sets the {@link OnClickListener} */
-    public void setOnClickListener(OnClickListener listener) {
-        mOnClickListener = listener;
-
-        update();
-    }
-
-    /* package */ void setCarUxRestrictions(CarUxRestrictions restrictions) {
-        boolean wasRestricted = isRestricted();
-        mCurrentRestrictions = restrictions;
-
-        if (isRestricted() != wasRestricted) {
-            update();
-        }
-    }
-
-    /* package */ boolean isRestricted() {
-        return CarUxRestrictionsUtil.isRestricted(mUxRestrictions, mCurrentRestrictions);
-    }
-
-    /** Calls the {@link OnClickListener}. */
-    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
-    public void performClick() {
-        if (!isEnabled() || !isVisible()) {
-            return;
-        }
-
-        if (isRestricted()) {
-            Toast.makeText(mContext,
-                    R.string.car_ui_restricted_while_driving, Toast.LENGTH_LONG).show();
-            return;
-        }
-
-        if (isActivatable()) {
-            setActivated(!isActivated());
-        }
-
-        if (isCheckable()) {
-            setChecked(!isChecked());
-        }
-
-        if (mOnClickListener != null) {
-            mOnClickListener.onClick(this);
-        }
-    }
-
-    /** Gets the current {@link DisplayBehavior} */
-    public DisplayBehavior getDisplayBehavior() {
-        return mDisplayBehavior;
-    }
-
-    /** Gets the current Icon */
-    public Drawable getIcon() {
-        return mIcon;
-    }
-
-    /** Sets the Icon of this MenuItem. */
-    public void setIcon(Drawable icon) {
-        mIcon = icon;
-
-        update();
-    }
-
-    /** Sets the Icon of this MenuItem to a drawable resource. */
-    public void setIcon(int resId) {
-        setIcon(resId == 0
-                ? null
-                : mContext.getDrawable(resId));
-    }
-
-    /** Returns if this is the search MenuItem, which has special behavior when searching */
-    boolean isSearch() {
-        return mIsSearch;
-    }
-
-    /** Builder class */
-    public static final class Builder {
-        private final Context mContext;
-
-        private String mSearchTitle;
-        private String mSettingsTitle;
-        private Drawable mSearchIcon;
-        private Drawable mSettingsIcon;
-
-        private int mId = View.NO_ID;
-        private CharSequence mTitle;
-        private Drawable mIcon;
-        private OnClickListener mOnClickListener;
-        private DisplayBehavior mDisplayBehavior = DisplayBehavior.ALWAYS;
-        private boolean mIsTinted = true;
-        private boolean mShowIconAndTitle = false;
-        private boolean mIsEnabled = true;
-        private boolean mIsCheckable = false;
-        private boolean mIsChecked = false;
-        private boolean mIsVisible = true;
-        private boolean mIsActivatable = false;
-        private boolean mIsActivated = false;
-        private boolean mIsSearch = false;
-        private boolean mIsSettings = false;
-        @CarUxRestrictions.CarUxRestrictionsInfo
-        private int mUxRestrictions = CarUxRestrictions.UX_RESTRICTIONS_BASELINE;
-
-        public Builder(Context c) {
-            // Must use getApplicationContext to avoid leaking activities when the MenuItem
-            // is held onto for longer than the Activity's lifecycle
-            mContext = c.getApplicationContext();
-        }
-
-        /** Builds a {@link MenuItem} from the current state of the Builder */
-        public MenuItem build() {
-            if (mIsActivatable && (mShowIconAndTitle || mIcon == null)) {
-                throw new IllegalStateException("Only simple icons can be activatable");
-            }
-            if (mIsCheckable
-                    && (mDisplayBehavior == DisplayBehavior.NEVER
-                    || mShowIconAndTitle
-                    || mIsActivatable)) {
-                throw new IllegalStateException("Unsupported options for a checkable MenuItem");
-            }
-            if (mIsSearch && mIsSettings) {
-                throw new IllegalStateException("Can't have both a search and settings MenuItem");
-            }
-
-            if (mIsSearch && (!mSearchTitle.contentEquals(mTitle)
-                    || !mSearchIcon.equals(mIcon)
-                    || mIsCheckable
-                    || mIsActivatable
-                    || !mIsTinted
-                    || mShowIconAndTitle
-                    || mDisplayBehavior != DisplayBehavior.ALWAYS)) {
-                throw new IllegalStateException("Invalid search MenuItem");
-            }
-
-            if (mIsSettings && (!mSettingsTitle.contentEquals(mTitle)
-                    || !mSettingsIcon.equals(mIcon)
-                    || mIsCheckable
-                    || mIsActivatable
-                    || !mIsTinted
-                    || mShowIconAndTitle
-                    || mDisplayBehavior != DisplayBehavior.ALWAYS)) {
-                throw new IllegalStateException("Invalid settings MenuItem");
-            }
-
-            return new MenuItem(this);
-        }
-
-        /** Sets the id, which is purely for the client to distinguish MenuItems with. */
-        public Builder setId(int id) {
-            mId = id;
-            return this;
-        }
-
-        /** Sets the title to a string resource id */
-        public Builder setTitle(int resId) {
-            setTitle(mContext.getString(resId));
-            return this;
-        }
-
-        /** Sets the title */
-        public Builder setTitle(CharSequence title) {
-            mTitle = title;
-            return this;
-        }
-
-        /**
-         * Sets the icon to a drawable resource id.
-         *
-         * <p>The icon's color and size will be changed to match the other MenuItems.
-         */
-        public Builder setIcon(int resId) {
-            mIcon = resId == 0
-                    ? null
-                    : mContext.getDrawable(resId);
-            return this;
-        }
-
-        /**
-         * Sets the icon to a drawable.
-         *
-         * <p>The icon's color and size will be changed to match the other MenuItems.
-         */
-        public Builder setIcon(Drawable icon) {
-            mIcon = icon;
-            return this;
-        }
-
-        /**
-         * Sets whether to tint the icon, true by default.
-         *
-         * <p>Try not to use this, it should only be used if the MenuItem is displaying some
-         * kind of logo or avatar and should be colored.
-         */
-        public Builder setTinted(boolean tinted) {
-            mIsTinted = tinted;
-            return this;
-        }
-
-        /** Sets whether the MenuItem is visible or not. Default true. */
-        public Builder setVisible(boolean visible) {
-            mIsVisible = visible;
-            return this;
-        }
-
-        /**
-         * Makes the MenuItem activatable, which means it will toggle it's visual state after
-         * every click.
-         */
-        public Builder setActivatable() {
-            mIsActivatable = true;
-            return this;
-        }
-
-        /**
-         * Sets whether or not the MenuItem is selected. If it is,
-         * {@link View#setSelected(boolean)} will be called on its View.
-         */
-        public Builder setActivated(boolean activated) {
-            setActivatable();
-            mIsActivated = activated;
-            return this;
-        }
-
-        /** Sets the {@link OnClickListener} */
-        public Builder setOnClickListener(OnClickListener listener) {
-            mOnClickListener = listener;
-            return this;
-        }
-
-        /**
-         * Used to show both the icon and title when displayed on the toolbar. If this
-         * is false, only the icon while be displayed when the MenuItem is in the toolbar
-         * and only the title will be displayed when the MenuItem is in the overflow menu.
-         *
-         * <p>Defaults to false.
-         */
-        public Builder setShowIconAndTitle(boolean showIconAndTitle) {
-            mShowIconAndTitle = showIconAndTitle;
-            return this;
-        }
-
-        /**
-         * Sets the {@link DisplayBehavior}.
-         *
-         * <p>If the DisplayBehavior is {@link DisplayBehavior#NEVER}, the MenuItem must not be
-         * {@link #setCheckable() checkable}.
-         */
-        public Builder setDisplayBehavior(DisplayBehavior behavior) {
-            mDisplayBehavior = behavior;
-            return this;
-        }
-
-        /** Sets whether the MenuItem is enabled or not. Default true. */
-        public Builder setEnabled(boolean enabled) {
-            mIsEnabled = enabled;
-            return this;
-        }
-
-        /**
-         * Makes the MenuItem checkable, meaning it will be displayed as a
-         * switch. Currently a checkable MenuItem cannot have a {@link DisplayBehavior} of NEVER.
-         *
-         * <p>The MenuItem is not checkable by default.
-         */
-        public Builder setCheckable() {
-            mIsCheckable = true;
-            return this;
-        }
-
-        /**
-         * Sets whether the MenuItem is checked or not. This will imply {@link #setCheckable()}.
-         */
-        public Builder setChecked(boolean checked) {
-            setCheckable();
-            mIsChecked = checked;
-            return this;
-        }
-
-        /**
-         * Sets under what {@link android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo}
-         * the MenuItem should be restricted.
-         */
-        public Builder setUxRestrictions(
-                @CarUxRestrictions.CarUxRestrictionsInfo int restrictions) {
-            mUxRestrictions = restrictions;
-            return this;
-        }
-
-        /**
-         * Creates a search MenuItem.
-         *
-         * <p>The advantage of using this over creating your own is getting an OEM-styled search
-         * icon, and this button will always disappear while searching, even when the
-         * {@link Toolbar Toolbar's} showMenuItemsWhileSearching is true.
-         *
-         * <p>If using this, you should only change the id, visibility, or onClickListener.
-         */
-        public Builder setToSearch() {
-            mSearchTitle = mContext.getString(R.string.car_ui_toolbar_menu_item_search_title);
-            mSearchIcon = mContext.getDrawable(R.drawable.car_ui_icon_search);
-            mIsSearch = true;
-            setTitle(mSearchTitle);
-            setIcon(mSearchIcon);
-            return this;
-        }
-
-        /**
-         * Creates a settings MenuItem.
-         *
-         * <p>The advantage of this over creating your own is getting an OEM-styled settings icon,
-         * and that the MenuItem will be restricted based on
-         * {@link CarUxRestrictions#UX_RESTRICTIONS_NO_SETUP}
-         *
-         * <p>If using this, you should only change the id, visibility, or onClickListener.
-         */
-        public Builder setToSettings() {
-            mSettingsTitle = mContext.getString(R.string.car_ui_toolbar_menu_item_settings_title);
-            mSettingsIcon = mContext.getDrawable(R.drawable.car_ui_icon_settings);
-            mIsSettings = true;
-            setTitle(mSettingsTitle);
-            setIcon(mSettingsIcon);
-            setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP);
-            return this;
-        }
-
-        /** @deprecated Use {@link #setToSearch()} instead. */
-        @Deprecated
-        public static MenuItem createSearch(Context c, OnClickListener listener) {
-            return MenuItem.builder(c)
-                    .setToSearch()
-                    .setOnClickListener(listener)
-                    .build();
-        }
-
-        /** @deprecated Use {@link #setToSettings()} instead. */
-        @Deprecated
-        public static MenuItem createSettings(Context c, OnClickListener listener) {
-            return MenuItem.builder(c)
-                    .setToSettings()
-                    .setOnClickListener(listener)
-                    .build();
-        }
-    }
-
-    /** Get a new {@link Builder}. */
-    public static Builder builder(Context context) {
-        return new Builder(context);
-    }
-
-    /**
-     * OnClickListener for a MenuItem.
-     */
-    public interface OnClickListener {
-        /** Called when the MenuItem is clicked */
-        void onClick(MenuItem item);
-    }
-
-    /**
-     * DisplayBehavior controls how the MenuItem is presented in the Toolbar
-     */
-    public enum DisplayBehavior {
-        /** Always show the MenuItem on the toolbar instead of the overflow menu */
-        ALWAYS,
-        /** Never show the MenuItem in the toolbar, always put it in the overflow menu */
-        NEVER
-    }
-
-    /** Listener for {@link Toolbar} to update when this MenuItem changes */
-    interface Listener {
-        /** Called when the MenuItem is changed. For use only by {@link Toolbar} */
-        void onMenuItemChanged();
-    }
-
-    /**
-     * Sets a listener for changes to this MenuItem. Note that the MenuItem will only hold
-     * weak references to the Listener, so that the listener is not held if the MenuItem
-     * outlives the toolbar.
-     */
-    void setListener(Listener listener) {
-        mListener = new WeakReference<>(listener);
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItemRenderer.java b/car-ui-lib/src/com/android/car/ui/toolbar/MenuItemRenderer.java
deleted file mode 100644
index 77b9f53..0000000
--- a/car-ui-lib/src/com/android/car/ui/toolbar/MenuItemRenderer.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.toolbar;
-
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
-
-import android.app.Activity;
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Xml;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import androidx.annotation.XmlRes;
-import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
-import androidx.core.util.Consumer;
-
-import com.android.car.ui.R;
-import com.android.car.ui.utils.CarUiUtils;
-import com.android.car.ui.uxr.DrawableStateView;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-class MenuItemRenderer implements MenuItem.Listener {
-
-    private static final int[] RESTRICTED_STATE = new int[] {R.attr.state_ux_restricted};
-
-    private final int mMenuItemIconSize;
-
-    private Toolbar.State mToolbarState;
-
-    private final MenuItem mMenuItem;
-    private final ViewGroup mParentView;
-    private View mView;
-    private View mIconContainer;
-    private ImageView mIconView;
-    private Switch mSwitch;
-    private TextView mTextView;
-    private TextView mTextWithIconView;
-
-    MenuItemRenderer(MenuItem item, ViewGroup parentView) {
-        mMenuItem = item;
-        mParentView = parentView;
-        mMenuItem.setListener(this);
-
-        mMenuItemIconSize = parentView.getContext().getResources()
-                .getDimensionPixelSize(R.dimen.car_ui_toolbar_menu_item_icon_size);
-    }
-
-    void setToolbarState(Toolbar.State state) {
-        mToolbarState = state;
-
-        if (mMenuItem.isSearch()) {
-            updateView();
-        }
-    }
-
-    void setCarUxRestrictions(CarUxRestrictions restrictions) {
-        mMenuItem.setCarUxRestrictions(restrictions);
-    }
-
-    @Override
-    public void onMenuItemChanged() {
-        updateView();
-    }
-
-    void createView(Consumer<View> callback) {
-        AsyncLayoutInflater inflater = new AsyncLayoutInflater(mParentView.getContext());
-        inflater.inflate(R.layout.car_ui_toolbar_menu_item, mParentView, (View view, int resid,
-                ViewGroup parent) -> {
-            mView = view;
-
-            mIconContainer =
-                    requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_icon_container);
-            mIconView = requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_icon);
-            mSwitch = requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_switch);
-            mTextView = requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_text);
-            mTextWithIconView =
-                    requireViewByRefId(mView, R.id.car_ui_toolbar_menu_item_text_with_icon);
-            updateView();
-            callback.accept(mView);
-        });
-    }
-
-    private void updateView() {
-        if (mView == null) {
-            return;
-        }
-
-        mView.setId(mMenuItem.getId());
-
-        boolean hasIcon = mMenuItem.getIcon() != null;
-        boolean hasText = !TextUtils.isEmpty(mMenuItem.getTitle());
-        boolean textAndIcon = mMenuItem.isShowingIconAndTitle();
-        boolean checkable = mMenuItem.isCheckable();
-
-        if (!mMenuItem.isVisible()
-                || (mMenuItem.isSearch() && mToolbarState == Toolbar.State.SEARCH)
-                || (!checkable && !hasIcon && !hasText)) {
-            mView.setVisibility(View.GONE);
-            return;
-        }
-        mView.setVisibility(View.VISIBLE);
-        mView.setContentDescription(mMenuItem.getTitle());
-
-        mIconContainer.setVisibility(View.GONE);
-        mTextView.setVisibility(View.GONE);
-        mTextWithIconView.setVisibility(View.GONE);
-        mSwitch.setVisibility(View.GONE);
-        if (checkable) {
-            mSwitch.setChecked(mMenuItem.isChecked());
-            mSwitch.setVisibility(View.VISIBLE);
-        } else if (hasText && hasIcon && textAndIcon) {
-            mMenuItem.getIcon().setBounds(0, 0, mMenuItemIconSize, mMenuItemIconSize);
-            mTextWithIconView.setCompoundDrawables(mMenuItem.getIcon(), null, null, null);
-            mTextWithIconView.setText(mMenuItem.getTitle());
-            mTextWithIconView.setVisibility(View.VISIBLE);
-        } else if (hasIcon) {
-            mIconView.setImageDrawable(mMenuItem.getIcon());
-            mIconContainer.setVisibility(View.VISIBLE);
-        } else { // hasText will be true
-            mTextView.setText(mMenuItem.getTitle());
-            mTextView.setVisibility(View.VISIBLE);
-        }
-
-        if (!mMenuItem.isTinted() && hasIcon) {
-            mMenuItem.getIcon().setTintList(null);
-        }
-
-        recursiveSetEnabledAndDrawableState(mView);
-        mView.setActivated(mMenuItem.isActivated());
-
-        if (mMenuItem.getOnClickListener() != null
-                || mMenuItem.isCheckable()
-                || mMenuItem.isActivatable()) {
-            mView.setOnClickListener(v -> mMenuItem.performClick());
-        } else {
-            mView.setOnClickListener(null);
-            mView.setClickable(false);
-        }
-    }
-
-    private void recursiveSetEnabledAndDrawableState(View view) {
-        view.setEnabled(mMenuItem.isEnabled());
-
-        int[] drawableState = mMenuItem.isRestricted() ? RESTRICTED_STATE : null;
-        if (view instanceof ImageView) {
-            ((ImageView) view).setImageState(drawableState, true);
-        } else if (view instanceof DrawableStateView) {
-            ((DrawableStateView) view).setDrawableState(drawableState);
-        }
-
-        if (view instanceof ViewGroup) {
-            ViewGroup viewGroup = ((ViewGroup) view);
-            for (int i = 0; i < viewGroup.getChildCount(); i++) {
-                recursiveSetEnabledAndDrawableState(viewGroup.getChildAt(i));
-            }
-        }
-    }
-
-    static List<MenuItem> readMenuItemList(Context c, @XmlRes int resId) {
-        if (resId == 0) {
-            return new ArrayList<>();
-        }
-
-        try (XmlResourceParser parser = c.getResources().getXml(resId)) {
-            AttributeSet attrs = Xml.asAttributeSet(parser);
-            List<MenuItem> menuItems = new ArrayList<>();
-
-            parser.next();
-            parser.next();
-            parser.require(XmlPullParser.START_TAG, null, "MenuItems");
-            while (parser.next() != XmlPullParser.END_TAG) {
-                menuItems.add(readMenuItem(c, parser, attrs));
-            }
-
-            return menuItems;
-        } catch (XmlPullParserException | IOException e) {
-            throw new RuntimeException("Unable to parse Menu Items", e);
-        }
-    }
-
-    private static MenuItem readMenuItem(Context c, XmlResourceParser parser, AttributeSet attrs)
-            throws XmlPullParserException, IOException {
-
-        parser.require(XmlPullParser.START_TAG, null, "MenuItem");
-
-        TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.CarUiToolbarMenuItem);
-        try {
-            int id = a.getResourceId(R.styleable.CarUiToolbarMenuItem_id, View.NO_ID);
-            String title = a.getString(R.styleable.CarUiToolbarMenuItem_title);
-            Drawable icon = a.getDrawable(R.styleable.CarUiToolbarMenuItem_icon);
-            boolean isSearch = a.getBoolean(R.styleable.CarUiToolbarMenuItem_search, false);
-            boolean isSettings = a.getBoolean(R.styleable.CarUiToolbarMenuItem_settings, false);
-            boolean tinted = a.getBoolean(R.styleable.CarUiToolbarMenuItem_tinted, true);
-            boolean visible = a.getBoolean(R.styleable.CarUiToolbarMenuItem_visible, true);
-            boolean showIconAndTitle = a.getBoolean(
-                    R.styleable.CarUiToolbarMenuItem_showIconAndTitle, false);
-            boolean checkable = a.getBoolean(R.styleable.CarUiToolbarMenuItem_checkable, false);
-            boolean checked = a.getBoolean(R.styleable.CarUiToolbarMenuItem_checked, false);
-            boolean checkedExists = a.hasValue(R.styleable.CarUiToolbarMenuItem_checked);
-            boolean activatable = a.getBoolean(R.styleable.CarUiToolbarMenuItem_activatable, false);
-            boolean activated = a.getBoolean(R.styleable.CarUiToolbarMenuItem_activated, false);
-            boolean activatedExists = a.hasValue(R.styleable.CarUiToolbarMenuItem_activated);
-            int displayBehaviorInt = a.getInt(R.styleable.CarUiToolbarMenuItem_displayBehavior, 0);
-            int uxRestrictions = a.getInt(R.styleable.CarUiToolbarMenuItem_uxRestrictions, 0);
-            String onClickMethod = a.getString(R.styleable.CarUiToolbarMenuItem_onClick);
-            MenuItem.OnClickListener onClickListener = null;
-
-            if (onClickMethod != null) {
-                Activity activity = CarUiUtils.getActivity(c);
-                if (activity == null) {
-                    throw new RuntimeException("Couldn't find an activity for the MenuItem");
-                }
-
-                try {
-                    Method m = activity.getClass().getMethod(onClickMethod, MenuItem.class);
-                    onClickListener = i -> {
-                        try {
-                            m.invoke(activity, i);
-                        } catch (InvocationTargetException | IllegalAccessException e) {
-                            throw new RuntimeException("Couldn't call the MenuItem's listener", e);
-                        }
-                    };
-                } catch (NoSuchMethodException e) {
-                    throw new RuntimeException("OnClick method "
-                            + onClickMethod + "(MenuItem) not found in your activity", e);
-                }
-            }
-
-            MenuItem.DisplayBehavior displayBehavior = displayBehaviorInt == 0
-                    ? MenuItem.DisplayBehavior.ALWAYS
-                    : MenuItem.DisplayBehavior.NEVER;
-
-            parser.next();
-            parser.require(XmlPullParser.END_TAG, null, "MenuItem");
-
-            MenuItem.Builder builder = MenuItem.builder(c)
-                    .setId(id)
-                    .setTitle(title)
-                    .setIcon(icon)
-                    .setOnClickListener(onClickListener)
-                    .setUxRestrictions(uxRestrictions)
-                    .setTinted(tinted)
-                    .setVisible(visible)
-                    .setShowIconAndTitle(showIconAndTitle)
-                    .setDisplayBehavior(displayBehavior);
-
-            if (isSearch) {
-                builder.setToSearch();
-            }
-
-            if (isSettings) {
-                builder.setToSettings();
-            }
-
-            if (checkable || checkedExists) {
-                builder.setChecked(checked);
-            }
-
-            if (activatable || activatedExists) {
-                builder.setActivated(activated);
-            }
-
-            return builder.build();
-        } finally {
-            a.recycle();
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarControllerImpl.java b/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarControllerImpl.java
deleted file mode 100644
index d22dc11..0000000
--- a/car-ui-lib/src/com/android/car/ui/toolbar/ProgressBarControllerImpl.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.toolbar;
-
-import android.view.View;
-import android.widget.ProgressBar;
-
-import androidx.annotation.NonNull;
-
-/**
- * Implementation of {@link ProgressBarController}.
- *
- * <p>This class accepts a {@link ProgressBar} in it's constructor and forwards the methods
- * of {@link ProgressBarController} to it.
- */
-class ProgressBarControllerImpl implements ProgressBarController {
-
-    @NonNull
-    private ProgressBar mProgressBar;
-
-    ProgressBarControllerImpl(@NonNull ProgressBar progressBar) {
-        mProgressBar = progressBar;
-    }
-
-    @Override
-    public void setVisible(boolean visible) {
-        mProgressBar.setVisibility(visible ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public boolean isVisible() {
-        return mProgressBar.getVisibility() == View.VISIBLE;
-    }
-
-    @Override
-    public void setIndeterminate(boolean indeterminate) {
-        mProgressBar.setIndeterminate(indeterminate);
-    }
-
-    @Override
-    public boolean isIndeterminate() {
-        return mProgressBar.isIndeterminate();
-    }
-
-    @Override
-    public void setMax(int max) {
-        mProgressBar.setMax(max);
-    }
-
-    @Override
-    public int getMax() {
-        return mProgressBar.getMax();
-    }
-
-    @Override
-    public void setMin(int min) {
-        mProgressBar.setMin(min);
-    }
-
-    @Override
-    public int getMin() {
-        return mProgressBar.getMin();
-    }
-
-    @Override
-    public void setProgress(int progress) {
-        mProgressBar.setProgress(progress);
-    }
-
-    @Override
-    public int getProgress() {
-        return mProgressBar.getProgress();
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/SearchView.java b/car-ui-lib/src/com/android/car/ui/toolbar/SearchView.java
deleted file mode 100644
index 7f7eb80..0000000
--- a/car-ui-lib/src/com/android/car/ui/toolbar/SearchView.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.toolbar;
-
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.ImageView;
-
-import androidx.annotation.NonNull;
-import androidx.constraintlayout.widget.ConstraintLayout;
-
-import com.android.car.ui.R;
-
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * A search view used by {@link Toolbar}.
- */
-public class SearchView extends ConstraintLayout {
-    private final InputMethodManager mInputMethodManager;
-    private final ImageView mIcon;
-    private final EditText mSearchText;
-    private final View mCloseIcon;
-    private final int mStartPaddingWithoutIcon;
-    private final int mStartPadding;
-    private final int mEndPadding;
-    private Set<Toolbar.OnSearchListener> mSearchListeners = Collections.emptySet();
-    private Set<Toolbar.OnSearchCompletedListener> mSearchCompletedListeners =
-            Collections.emptySet();
-    private final TextWatcher mTextWatcher = new TextWatcher() {
-        @Override
-        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
-        }
-
-        @Override
-        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
-        }
-
-        @Override
-        public void afterTextChanged(Editable editable) {
-            onSearch(editable.toString());
-        }
-    };
-
-    private boolean mIsPlainText = false;
-
-    public SearchView(Context context) {
-        this(context, null);
-    }
-
-    public SearchView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public SearchView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-
-        mInputMethodManager = (InputMethodManager)
-            getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-
-        LayoutInflater inflater = LayoutInflater.from(context);
-        inflater.inflate(R.layout.car_ui_toolbar_search_view, this, true);
-
-        mSearchText = requireViewByRefId(this, R.id.car_ui_toolbar_search_bar);
-        mIcon = requireViewByRefId(this, R.id.car_ui_toolbar_search_icon);
-        mCloseIcon = requireViewByRefId(this, R.id.car_ui_toolbar_search_close);
-
-        mCloseIcon.setOnClickListener(view -> mSearchText.getText().clear());
-        mCloseIcon.setVisibility(View.GONE);
-
-        mStartPaddingWithoutIcon = mSearchText.getPaddingStart();
-        mStartPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.car_ui_toolbar_search_search_icon_container_width);
-        mEndPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.car_ui_toolbar_search_close_icon_container_width);
-
-        mSearchText.setSaveEnabled(false);
-        mSearchText.setPaddingRelative(mStartPadding, 0, mEndPadding, 0);
-
-        mSearchText.setOnFocusChangeListener(
-                (view, hasFocus) -> {
-                    if (hasFocus) {
-                        mInputMethodManager.showSoftInput(view, 0);
-                    } else {
-                        mInputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
-                    }
-                });
-
-        mSearchText.addTextChangedListener(mTextWatcher);
-
-        mSearchText.setOnEditorActionListener((v, actionId, event) -> {
-            if (actionId == EditorInfo.IME_ACTION_DONE
-                    || actionId == EditorInfo.IME_ACTION_SEARCH) {
-                mSearchText.clearFocus();
-                for (Toolbar.OnSearchCompletedListener listener : mSearchCompletedListeners) {
-                    listener.onSearchCompleted();
-                }
-            }
-            return false;
-        });
-    }
-
-    private boolean mWasShown = false;
-
-    @Override
-    public void onVisibilityChanged(@NonNull View changedView, int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-
-        boolean isShown = isShown();
-        if (isShown && !mWasShown) {
-            boolean hasQuery = mSearchText.getText().length() > 0;
-            mCloseIcon.setVisibility(hasQuery ? View.VISIBLE : View.GONE);
-            mSearchText.requestFocus();
-        }
-        mWasShown = isShown;
-    }
-
-    /**
-     * Adds a listener for the search text changing.
-     * See also {@link #unregisterOnSearchListener(Toolbar.OnSearchListener)}
-     */
-    public void setSearchListeners(Set<Toolbar.OnSearchListener> listeners) {
-        mSearchListeners = listeners;
-    }
-
-    /**
-     * Removes a search listener.
-     * See also {@link #registerOnSearchListener(Toolbar.OnSearchListener)}
-     */
-    public void setSearchCompletedListeners(Set<Toolbar.OnSearchCompletedListener> listeners) {
-        mSearchCompletedListeners = listeners;
-    }
-
-    /**
-     * Sets the search hint.
-     *
-     * @param resId A string resource id of the search hint.
-     */
-    public void setHint(int resId) {
-        mSearchText.setHint(resId);
-    }
-
-    /**
-     * Sets the search hint
-     *
-     * @param hint A CharSequence of the search hint.
-     */
-    public void setHint(CharSequence hint) {
-        mSearchText.setHint(hint);
-    }
-
-    /** Gets the search hint */
-    public CharSequence getHint() {
-        return mSearchText.getHint();
-    }
-
-    /**
-     * Sets a custom icon to display in the search box.
-     */
-    public void setIcon(Drawable d) {
-        if (d == null) {
-            mIcon.setImageResource(R.drawable.car_ui_icon_search);
-        } else {
-            mIcon.setImageDrawable(d);
-        }
-    }
-
-    /**
-     * Sets a custom icon to display in the search box.
-     */
-    public void setIcon(int resId) {
-        if (resId == 0) {
-            mIcon.setImageResource(R.drawable.car_ui_icon_search);
-        } else {
-            mIcon.setImageResource(resId);
-        }
-    }
-
-    /**
-     * Sets whether or not the search bar should look like a regular text box
-     * instead of a search box.
-     */
-    public void setPlainText(boolean plainText) {
-        if (plainText != mIsPlainText) {
-            if (plainText) {
-                mSearchText.setPaddingRelative(mStartPaddingWithoutIcon, 0, mEndPadding, 0);
-                mSearchText.setImeOptions(EditorInfo.IME_ACTION_DONE);
-                mIcon.setVisibility(View.GONE);
-            } else {
-                mSearchText.setPaddingRelative(mStartPadding, 0, mEndPadding, 0);
-                mSearchText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
-                mIcon.setVisibility(View.VISIBLE);
-            }
-            mIsPlainText = plainText;
-
-            // Needed to detect changes to imeOptions
-            mInputMethodManager.restartInput(mSearchText);
-        }
-    }
-
-    private void onSearch(String query) {
-        mCloseIcon.setVisibility(TextUtils.isEmpty(query) ? View.GONE : View.VISIBLE);
-
-        for (Toolbar.OnSearchListener listener : mSearchListeners) {
-            listener.onSearch(query);
-        }
-    }
-
-    /**
-     * Sets the text being searched.
-     */
-    public void setSearchQuery(String query) {
-        mSearchText.setText(query);
-        mSearchText.setSelection(mSearchText.getText().length());
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java b/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
deleted file mode 100644
index 524e3c2..0000000
--- a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.toolbar;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
-import androidx.annotation.XmlRes;
-
-import com.android.car.ui.R;
-
-import java.util.List;
-
-/**
- * A toolbar for Android Automotive OS apps.
- *
- * <p>This isn't a toolbar in the android framework sense, it's merely a custom view that can be
- * added to a layout. (You can't call
- * {@link android.app.Activity#setActionBar(android.widget.Toolbar)} with it)
- *
- * <p>The toolbar supports a navigation button, title, tabs, search, and {@link MenuItem MenuItems}
- */
-public class Toolbar extends FrameLayout implements ToolbarController {
-
-    /** Callback that will be issued whenever the height of toolbar is changed. */
-    public interface OnHeightChangedListener {
-        /**
-         * Will be called when the height of the toolbar is changed.
-         *
-         * @param height new height of the toolbar
-         */
-        void onHeightChanged(int height);
-    }
-
-    /** Back button listener */
-    public interface OnBackListener {
-        /**
-         * Invoked when the user clicks on the back button. By default, the toolbar will call
-         * the Activity's {@link android.app.Activity#onBackPressed()}. Returning true from
-         * this method will absorb the back press and prevent that behavior.
-         */
-        boolean onBack();
-    }
-
-    /** Tab selection listener */
-    public interface OnTabSelectedListener {
-        /** Called when a {@link TabLayout.Tab} is selected */
-        void onTabSelected(TabLayout.Tab tab);
-    }
-
-    /** Search listener */
-    public interface OnSearchListener {
-        /**
-         * Invoked when the user edits a search query.
-         *
-         * <p>This is called for every letter the user types, and also empty strings if the user
-         * erases everything.
-         */
-        void onSearch(String query);
-    }
-
-    /** Search completed listener */
-    public interface OnSearchCompletedListener {
-        /**
-         * Invoked when the user submits a search query by clicking the keyboard's search / done
-         * button.
-         */
-        void onSearchCompleted();
-    }
-
-    private static final String TAG = "CarUiToolbar";
-
-    /** Enum of states the toolbar can be in. Controls what elements of the toolbar are displayed */
-    public enum State {
-        /**
-         * In the HOME state, the logo will be displayed if there is one, and no navigation icon
-         * will be displayed. The tab bar will be visible. The title will be displayed if there
-         * is space. MenuItems will be displayed.
-         */
-        HOME,
-        /**
-         * In the SUBPAGE state, the logo will be replaced with a back button, the tab bar won't
-         * be visible. The title and MenuItems will be displayed.
-         */
-        SUBPAGE,
-        /**
-         * In the SEARCH state, only the back button and the search bar will be visible.
-         */
-        SEARCH,
-        /**
-         * In the EDIT state, the search bar will look like a regular text box, but will be
-         * functionally identical to the SEARCH state.
-         */
-        EDIT,
-    }
-
-    private ToolbarControllerImpl mController;
-    private boolean mEatingTouch = false;
-    private boolean mEatingHover = false;
-
-    public Toolbar(Context context) {
-        this(context, null);
-    }
-
-    public Toolbar(Context context, AttributeSet attrs) {
-        this(context, attrs, R.attr.CarUiToolbarStyle);
-    }
-
-    public Toolbar(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public Toolbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-
-        LayoutInflater inflater = (LayoutInflater) context
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        inflater.inflate(getToolbarLayout(), this, true);
-
-        mController = new ToolbarControllerImpl(this);
-
-        TypedArray a = context.obtainStyledAttributes(
-                attrs, R.styleable.CarUiToolbar, defStyleAttr, defStyleRes);
-
-        try {
-            setShowTabsInSubpage(a.getBoolean(R.styleable.CarUiToolbar_showTabsInSubpage, false));
-            setTitle(a.getString(R.styleable.CarUiToolbar_title));
-            setLogo(a.getResourceId(R.styleable.CarUiToolbar_logo, 0));
-            setBackgroundShown(a.getBoolean(R.styleable.CarUiToolbar_showBackground, true));
-            setMenuItems(a.getResourceId(R.styleable.CarUiToolbar_menuItems, 0));
-            String searchHint = a.getString(R.styleable.CarUiToolbar_searchHint);
-            if (searchHint != null) {
-                setSearchHint(searchHint);
-            }
-
-            switch (a.getInt(R.styleable.CarUiToolbar_state, 0)) {
-                case 0:
-                    setState(State.HOME);
-                    break;
-                case 1:
-                    setState(State.SUBPAGE);
-                    break;
-                case 2:
-                    setState(State.SEARCH);
-                    break;
-                default:
-                    if (Log.isLoggable(TAG, Log.WARN)) {
-                        Log.w(TAG, "Unknown initial state");
-                    }
-                    break;
-            }
-
-            switch (a.getInt(R.styleable.CarUiToolbar_navButtonMode, 0)) {
-                case 0:
-                    setNavButtonMode(NavButtonMode.BACK);
-                    break;
-                case 1:
-                    setNavButtonMode(NavButtonMode.CLOSE);
-                    break;
-                case 2:
-                    setNavButtonMode(NavButtonMode.DOWN);
-                    break;
-                default:
-                    if (Log.isLoggable(TAG, Log.WARN)) {
-                        Log.w(TAG, "Unknown navigation button style");
-                    }
-                    break;
-            }
-        } finally {
-            a.recycle();
-        }
-    }
-
-    /**
-     * Override this in a subclass to allow for different toolbar layouts within a single app.
-     *
-     * <p>Non-system apps should not use this, as customising the layout isn't possible with RROs
-     */
-    protected int getToolbarLayout() {
-        if (getContext().getResources().getBoolean(
-                R.bool.car_ui_toolbar_tabs_on_second_row)) {
-            return R.layout.car_ui_toolbar_two_row;
-        }
-
-        return R.layout.car_ui_toolbar;
-    }
-
-    /**
-     * Returns {@code true} if a two row layout in enabled for the toolbar.
-     */
-    public boolean isTabsInSecondRow() {
-        return mController.isTabsInSecondRow();
-    }
-
-    /**
-     * Sets the title of the toolbar to a string resource.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    public void setTitle(@StringRes int title) {
-        mController.setTitle(title);
-    }
-
-    /**
-     * Sets the title of the toolbar to a CharSequence.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    public void setTitle(CharSequence title) {
-        mController.setTitle(title);
-    }
-
-    public CharSequence getTitle() {
-        return mController.getTitle();
-    }
-
-    /**
-     * Sets the subtitle of the toolbar to a string resource.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    @Override
-    public void setSubtitle(@StringRes int title) {
-        mController.setSubtitle(title);
-    }
-
-    /**
-     * Sets the subtitle of the toolbar to a CharSequence.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    @Override
-    public void setSubtitle(CharSequence title) {
-        mController.setSubtitle(title);
-    }
-
-    @Override
-    public CharSequence getSubtitle() {
-        return mController.getSubtitle();
-    }
-
-    /**
-     * Gets the {@link TabLayout} for this toolbar.
-     */
-    public TabLayout getTabLayout() {
-        return mController.getTabLayout();
-    }
-
-    /**
-     * Adds a tab to this toolbar. You can listen for when it is selected via
-     * {@link #registerOnTabSelectedListener(OnTabSelectedListener)}.
-     */
-    public void addTab(TabLayout.Tab tab) {
-        mController.addTab(tab);
-    }
-
-    /** Removes all the tabs. */
-    public void clearAllTabs() {
-        mController.clearAllTabs();
-    }
-
-    /**
-     * Gets a tab added to this toolbar. See
-     * {@link #addTab(TabLayout.Tab)}.
-     */
-    public TabLayout.Tab getTab(int position) {
-        return mController.getTab(position);
-    }
-
-    /**
-     * Selects a tab added to this toolbar. See
-     * {@link #addTab(TabLayout.Tab)}.
-     */
-    public void selectTab(int position) {
-        mController.selectTab(position);
-    }
-
-    /**
-     * Sets whether or not tabs should also be shown in the SUBPAGE {@link State}.
-     */
-    public void setShowTabsInSubpage(boolean showTabs) {
-        mController.setShowTabsInSubpage(showTabs);
-    }
-
-    /**
-     * Gets whether or not tabs should also be shown in the SUBPAGE {@link State}.
-     */
-    public boolean getShowTabsInSubpage() {
-        return mController.getShowTabsInSubpage();
-    }
-
-    /**
-     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
-     * will be displayed next to the title.
-     */
-    public void setLogo(@DrawableRes int resId) {
-        mController.setLogo(resId);
-    }
-
-    /**
-     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
-     * will be displayed next to the title.
-     */
-    public void setLogo(Drawable drawable) {
-        mController.setLogo(drawable);
-    }
-
-    /** Sets the hint for the search bar. */
-    public void setSearchHint(@StringRes int resId) {
-        mController.setSearchHint(resId);
-    }
-
-    /** Sets the hint for the search bar. */
-    public void setSearchHint(CharSequence hint) {
-        mController.setSearchHint(hint);
-    }
-
-    /** Gets the search hint */
-    public CharSequence getSearchHint() {
-        return mController.getSearchHint();
-    }
-
-    /**
-     * Sets the icon to display in the search box.
-     *
-     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
-     * a similar place.
-     */
-    public void setSearchIcon(@DrawableRes int resId) {
-        mController.setSearchIcon(resId);
-    }
-
-    /**
-     * Sets the icon to display in the search box.
-     *
-     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
-     * a similar place.
-     */
-    public void setSearchIcon(Drawable d) {
-        mController.setSearchIcon(d);
-    }
-
-    /**
-     * An enum of possible styles the nav button could be in. All styles will still call
-     * {@link OnBackListener#onBack()}.
-     */
-    public enum NavButtonMode {
-        /** A back button */
-        BACK,
-        /** A close button */
-        CLOSE,
-        /** A down button, used to indicate that the page will animate down when navigating away */
-        DOWN
-    }
-
-    /** Sets the {@link NavButtonMode} */
-    public void setNavButtonMode(NavButtonMode style) {
-        mController.setNavButtonMode(style);
-    }
-
-    /** Gets the {@link NavButtonMode} */
-    public NavButtonMode getNavButtonMode() {
-        return mController.getNavButtonMode();
-    }
-
-    /**
-     * setBackground is disallowed, to prevent apps from deviating from the intended style too much.
-     */
-    @Override
-    public void setBackground(Drawable d) {
-        throw new UnsupportedOperationException(
-                "You can not change the background of a CarUi toolbar, use "
-                        + "setBackgroundShown(boolean) or an RRO instead.");
-    }
-
-    /** Show/hide the background. When hidden, the toolbar is completely transparent. */
-    public void setBackgroundShown(boolean shown) {
-        mController.setBackgroundShown(shown);
-    }
-
-    /** Returns true is the toolbar background is shown */
-    public boolean getBackgroundShown() {
-        return mController.getBackgroundShown();
-    }
-
-    /**
-     * Sets the {@link MenuItem Menuitems} to display.
-     */
-    public void setMenuItems(@Nullable List<MenuItem> items) {
-        mController.setMenuItems(items);
-    }
-
-    /**
-     * Sets the {@link MenuItem Menuitems} to display to a list defined in XML.
-     *
-     * <p>If this method is called twice with the same argument (and {@link #setMenuItems(List)}
-     * wasn't called), nothing will happen the second time, even if the MenuItems were changed.
-     *
-     * <p>The XML file must have one <MenuItems> tag, with a variable number of <MenuItem>
-     * child tags. See CarUiToolbarMenuItem in CarUi's attrs.xml for a list of available attributes.
-     *
-     * Example:
-     * <pre>
-     * <MenuItems>
-     *     <MenuItem
-     *         app:title="Foo"/>
-     *     <MenuItem
-     *         app:title="Bar"
-     *         app:icon="@drawable/ic_tracklist"
-     *         app:onClick="xmlMenuItemClicked"/>
-     *     <MenuItem
-     *         app:title="Bar"
-     *         app:checkable="true"
-     *         app:uxRestrictions="FULLY_RESTRICTED"
-     *         app:onClick="xmlMenuItemClicked"/>
-     * </MenuItems>
-     * </pre>
-     *
-     * @return The MenuItems that were loaded from XML.
-     * @see #setMenuItems(List)
-     */
-    public List<MenuItem> setMenuItems(@XmlRes int resId) {
-        return mController.setMenuItems(resId);
-    }
-
-    /** Gets the {@link MenuItem MenuItems} currently displayed */
-    @NonNull
-    public List<MenuItem> getMenuItems() {
-        return mController.getMenuItems();
-    }
-
-    /** Gets a {@link MenuItem} by id. */
-    @Nullable
-    public MenuItem findMenuItemById(int id) {
-        return mController.findMenuItemById(id);
-    }
-
-    /** Gets a {@link MenuItem} by id. Will throw an exception if not found. */
-    @NonNull
-    public MenuItem requireMenuItemById(int id) {
-        return mController.requireMenuItemById(id);
-    }
-
-    /**
-     * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
-     * Even if this is set to true, the {@link MenuItem} created by
-     * {@link MenuItem.Builder#setToSearch()} will still be hidden.
-     */
-    public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
-        mController.setShowMenuItemsWhileSearching(showMenuItems);
-    }
-
-    /** Returns if {@link MenuItem MenuItems} are shown while searching */
-    public boolean getShowMenuItemsWhileSearching() {
-        return mController.getShowMenuItemsWhileSearching();
-    }
-
-    /**
-     * Sets the search query.
-     */
-    public void setSearchQuery(String query) {
-        mController.setSearchQuery(query);
-    }
-
-    /**
-     * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
-     * for the desired state.
-     */
-    public void setState(State state) {
-        mController.setState(state);
-    }
-
-    /** Gets the current {@link State} of the toolbar. */
-    public State getState() {
-        return mController.getState();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        // Copied from androidx.appcompat.widget.Toolbar
-
-        // Toolbars always eat touch events, but should still respect the touch event dispatch
-        // contract. If the normal View implementation doesn't want the events, we'll just silently
-        // eat the rest of the gesture without reporting the events to the default implementation
-        // since that's what it expects.
-
-        final int action = ev.getActionMasked();
-        if (action == MotionEvent.ACTION_DOWN) {
-            mEatingTouch = false;
-        }
-
-        if (!mEatingTouch) {
-            final boolean handled = super.onTouchEvent(ev);
-            if (action == MotionEvent.ACTION_DOWN && !handled) {
-                mEatingTouch = true;
-            }
-        }
-
-        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
-            mEatingTouch = false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean onHoverEvent(MotionEvent ev) {
-        // Copied from androidx.appcompat.widget.Toolbar
-
-        // Same deal as onTouchEvent() above. Eat all hover events, but still
-        // respect the touch event dispatch contract.
-
-        final int action = ev.getActionMasked();
-        if (action == MotionEvent.ACTION_HOVER_ENTER) {
-            mEatingHover = false;
-        }
-
-        if (!mEatingHover) {
-            final boolean handled = super.onHoverEvent(ev);
-            if (action == MotionEvent.ACTION_HOVER_ENTER && !handled) {
-                mEatingHover = true;
-            }
-        }
-
-        if (action == MotionEvent.ACTION_HOVER_EXIT || action == MotionEvent.ACTION_CANCEL) {
-            mEatingHover = false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Registers a new {@link OnHeightChangedListener} to the list of listeners. Register a
-     * {@link com.android.car.ui.recyclerview.CarUiRecyclerView} only if there is a toolbar at
-     * the top and a {@link com.android.car.ui.recyclerview.CarUiRecyclerView} in the view and
-     * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
-     * automatically adjust its height according to the height of the Toolbar.
-     */
-    public void registerToolbarHeightChangeListener(
-            OnHeightChangedListener listener) {
-        mController.registerToolbarHeightChangeListener(listener);
-    }
-
-    /** Unregisters an existing {@link OnHeightChangedListener} from the list of listeners. */
-    public boolean unregisterToolbarHeightChangeListener(
-            OnHeightChangedListener listener) {
-        return mController.unregisterToolbarHeightChangeListener(listener);
-    }
-
-    /** Registers a new {@link OnTabSelectedListener} to the list of listeners. */
-    public void registerOnTabSelectedListener(OnTabSelectedListener listener) {
-        mController.registerOnTabSelectedListener(listener);
-    }
-
-    /** Unregisters an existing {@link OnTabSelectedListener} from the list of listeners. */
-    public boolean unregisterOnTabSelectedListener(OnTabSelectedListener listener) {
-        return mController.unregisterOnTabSelectedListener(listener);
-    }
-
-    /** Registers a new {@link OnSearchListener} to the list of listeners. */
-    public void registerOnSearchListener(OnSearchListener listener) {
-        mController.registerOnSearchListener(listener);
-    }
-
-    /** Unregisters an existing {@link OnSearchListener} from the list of listeners. */
-    public boolean unregisterOnSearchListener(OnSearchListener listener) {
-        return mController.unregisterOnSearchListener(listener);
-    }
-
-    /** Registers a new {@link OnSearchCompletedListener} to the list of listeners. */
-    public void registerOnSearchCompletedListener(OnSearchCompletedListener listener) {
-        mController.registerOnSearchCompletedListener(listener);
-    }
-
-    /** Unregisters an existing {@link OnSearchCompletedListener} from the list of listeners. */
-    public boolean unregisterOnSearchCompletedListener(OnSearchCompletedListener listener) {
-        return mController.unregisterOnSearchCompletedListener(listener);
-    }
-
-    /** Registers a new {@link OnBackListener} to the list of listeners. */
-    public void registerOnBackListener(OnBackListener listener) {
-        mController.registerOnBackListener(listener);
-    }
-
-    /** Unregisters an existing {@link OnBackListener} from the list of listeners. */
-    public boolean unregisterOnBackListener(OnBackListener listener) {
-        return mController.unregisterOnBackListener(listener);
-    }
-
-    /** Returns the progress bar */
-    public ProgressBarController getProgressBar() {
-        return mController.getProgressBar();
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarController.java b/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarController.java
deleted file mode 100644
index 5404fb1..0000000
--- a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarController.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.toolbar;
-
-import android.graphics.drawable.Drawable;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
-import androidx.annotation.XmlRes;
-
-import java.util.List;
-
-/**
- * An interface for accessing a Chassis Toolbar, regardless of how the underlying
- * views are represented.
- */
-public interface ToolbarController {
-
-    /**
-     * Returns {@code true} if a two row layout in enabled for the toolbar.
-     */
-    boolean isTabsInSecondRow();
-
-    /**
-     * Sets the title of the toolbar to a string resource.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    void setTitle(@StringRes int title);
-
-    /**
-     * Sets the title of the toolbar to a CharSequence.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    void setTitle(CharSequence title);
-
-    /**
-     * Gets the current toolbar title.
-     */
-    CharSequence getTitle();
-
-    /**
-     * Sets the subtitle of the toolbar to a string resource.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    void setSubtitle(@StringRes int title);
-
-    /**
-     * Sets the subtitle of the toolbar to a CharSequence.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    void setSubtitle(CharSequence title);
-
-    /**
-     * Gets the current toolbar subtitle.
-     */
-    CharSequence getSubtitle();
-
-    /**
-     * Gets the {@link TabLayout} for this toolbar.
-     */
-    TabLayout getTabLayout();
-
-    /**
-     * Adds a tab to this toolbar. You can listen for when it is selected via
-     * {@link #registerOnTabSelectedListener(Toolbar.OnTabSelectedListener)}.
-     */
-    void addTab(TabLayout.Tab tab);
-
-    /** Removes all the tabs. */
-    void clearAllTabs();
-
-    /**
-     * Gets a tab added to this toolbar. See
-     * {@link #addTab(TabLayout.Tab)}.
-     */
-    TabLayout.Tab getTab(int position);
-
-    /**
-     * Selects a tab added to this toolbar. See
-     * {@link #addTab(TabLayout.Tab)}.
-     */
-    void selectTab(int position);
-
-    /**
-     * Sets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
-     */
-    void setShowTabsInSubpage(boolean showTabs);
-
-    /**
-     * Gets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
-     */
-    boolean getShowTabsInSubpage();
-
-    /**
-     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
-     * will be displayed next to the title.
-     */
-    void setLogo(@DrawableRes int resId);
-
-    /**
-     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
-     * will be displayed next to the title.
-     */
-    void setLogo(Drawable drawable);
-
-    /** Sets the hint for the search bar. */
-    void setSearchHint(@StringRes int resId);
-
-    /** Sets the hint for the search bar. */
-    void setSearchHint(CharSequence hint);
-
-    /** Gets the search hint */
-    CharSequence getSearchHint();
-
-    /**
-     * Sets the icon to display in the search box.
-     *
-     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
-     * a similar place.
-     */
-    void setSearchIcon(@DrawableRes int resId);
-
-    /**
-     * Sets the icon to display in the search box.
-     *
-     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
-     * a similar place.
-     */
-    void setSearchIcon(Drawable d);
-
-
-    /** Sets the {@link Toolbar.NavButtonMode} */
-    void setNavButtonMode(Toolbar.NavButtonMode style);
-
-    /** Gets the {@link Toolbar.NavButtonMode} */
-    Toolbar.NavButtonMode getNavButtonMode();
-
-    /** Show/hide the background. When hidden, the toolbar is completely transparent. */
-    void setBackgroundShown(boolean shown);
-
-    /** Returns true is the toolbar background is shown */
-    boolean getBackgroundShown();
-
-    /**
-     * Sets the {@link MenuItem Menuitems} to display.
-     */
-    void setMenuItems(@Nullable List<MenuItem> items);
-
-    /**
-     * Sets the {@link MenuItem Menuitems} to display to a list defined in XML.
-     *
-     * <p>If this method is called twice with the same argument (and {@link #setMenuItems(List)}
-     * wasn't called), nothing will happen the second time, even if the MenuItems were changed.
-     *
-     * <p>The XML file must have one <MenuItems> tag, with a variable number of <MenuItem>
-     * child tags. See CarUiToolbarMenuItem in CarUi's attrs.xml for a list of available attributes.
-     *
-     * Example:
-     * <pre>
-     * <MenuItems>
-     *     <MenuItem
-     *         app:title="Foo"/>
-     *     <MenuItem
-     *         app:title="Bar"
-     *         app:icon="@drawable/ic_tracklist"
-     *         app:onClick="xmlMenuItemClicked"/>
-     *     <MenuItem
-     *         app:title="Bar"
-     *         app:checkable="true"
-     *         app:uxRestrictions="FULLY_RESTRICTED"
-     *         app:onClick="xmlMenuItemClicked"/>
-     * </MenuItems>
-     * </pre>
-     *
-     * @return The MenuItems that were loaded from XML.
-     * @see #setMenuItems(List)
-     */
-    List<MenuItem> setMenuItems(@XmlRes int resId);
-
-    /** Gets the {@link MenuItem MenuItems} currently displayed */
-    @NonNull
-    List<MenuItem> getMenuItems();
-
-    /** Gets a {@link MenuItem} by id. */
-    @Nullable
-    MenuItem findMenuItemById(int id);
-
-    /** Gets a {@link MenuItem} by id. Will throw an IllegalArgumentException if not found. */
-    @NonNull
-    MenuItem requireMenuItemById(int id);
-
-    /**
-     * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
-     * Even if this is set to true, the {@link MenuItem} created by
-     * {@link MenuItem.Builder#setToSearch()} will still be hidden.
-     */
-    void setShowMenuItemsWhileSearching(boolean showMenuItems);
-
-    /** Returns if {@link MenuItem MenuItems} are shown while searching */
-    boolean getShowMenuItemsWhileSearching();
-
-    /**
-     * Sets the search query.
-     */
-    void setSearchQuery(String query);
-
-    /**
-     * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
-     * for the desired state.
-     */
-    void setState(Toolbar.State state);
-
-    /** Gets the current {@link Toolbar.State} of the toolbar. */
-    Toolbar.State getState();
-
-    /**
-     * Registers a new {@link Toolbar.OnHeightChangedListener} to the list of listeners. Register a
-     * {@link com.android.car.ui.recyclerview.CarUiRecyclerView} only if there is a toolbar at
-     * the top and a {@link com.android.car.ui.recyclerview.CarUiRecyclerView} in the view and
-     * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
-     * automatically adjust its height according to the height of the Toolbar.
-     */
-    void registerToolbarHeightChangeListener(Toolbar.OnHeightChangedListener listener);
-
-    /** Unregisters an existing {@link Toolbar.OnHeightChangedListener} from the list of
-     * listeners. */
-    boolean unregisterToolbarHeightChangeListener(Toolbar.OnHeightChangedListener listener);
-
-    /** Registers a new {@link Toolbar.OnTabSelectedListener} to the list of listeners. */
-    void registerOnTabSelectedListener(Toolbar.OnTabSelectedListener listener);
-
-    /** Unregisters an existing {@link Toolbar.OnTabSelectedListener} from the list of listeners. */
-    boolean unregisterOnTabSelectedListener(Toolbar.OnTabSelectedListener listener);
-
-    /** Registers a new {@link Toolbar.OnSearchListener} to the list of listeners. */
-    void registerOnSearchListener(Toolbar.OnSearchListener listener);
-
-    /** Unregisters an existing {@link Toolbar.OnSearchListener} from the list of listeners. */
-    boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener);
-
-    /** Registers a new {@link Toolbar.OnSearchCompletedListener} to the list of listeners. */
-    void registerOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener);
-
-    /** Unregisters an existing {@link Toolbar.OnSearchCompletedListener} from the list of
-     * listeners. */
-    boolean unregisterOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener);
-
-    /** Registers a new {@link Toolbar.OnBackListener} to the list of listeners. */
-    void registerOnBackListener(Toolbar.OnBackListener listener);
-
-    /** Unregisters an existing {@link Toolbar.OnBackListener} from the list of listeners. */
-    boolean unregisterOnBackListener(Toolbar.OnBackListener listener);
-
-    /** Gets a {@link ProgressBarController} */
-    ProgressBarController getProgressBar();
-
-    /**
-     * Shows the progress bar.
-     *
-     * @deprecated use {@link #getProgressBar()} instead.
-     */
-    @Deprecated
-    default void showProgressBar() {
-        getProgressBar().setVisible(true);
-    }
-
-    /**
-     * Hides the progress bar
-     *
-     * @deprecated use {@link #getProgressBar()} instead.
-     */
-    @Deprecated
-    default void hideProgressBar() {
-        getProgressBar().setVisible(false);
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarControllerImpl.java b/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarControllerImpl.java
deleted file mode 100644
index 1b44d86..0000000
--- a/car-ui-lib/src/com/android/car/ui/toolbar/ToolbarControllerImpl.java
+++ /dev/null
@@ -1,799 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.ui.toolbar;
-
-import static android.view.View.GONE;
-import static android.view.View.INVISIBLE;
-import static android.view.View.VISIBLE;
-
-import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
-import androidx.annotation.XmlRes;
-
-import com.android.car.ui.R;
-import com.android.car.ui.utils.CarUiUtils;
-import com.android.car.ui.utils.CarUxRestrictionsUtil;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * The implementation of {@link ToolbarController}. This class takes a ViewGroup, and looks
- * in the ViewGroup to find all the toolbar-related views to control.
- */
-public class ToolbarControllerImpl implements ToolbarController {
-    private static final String TAG = "CarUiToolbarController";
-
-    private View mBackground;
-    private ImageView mNavIcon;
-    private ImageView mLogoInNavIconSpace;
-    private ViewGroup mNavIconContainer;
-    private LinearLayout mTitleContainer;
-    private TextView mTitle;
-    private TextView mSubtitle;
-    private ImageView mTitleLogo;
-    private ViewGroup mTitleLogoContainer;
-    private TabLayout mTabLayout;
-    private ViewGroup mMenuItemsContainer;
-    private FrameLayout mSearchViewContainer;
-    private SearchView mSearchView;
-
-
-    // Cached values that we will send to views when they are inflated
-    private CharSequence mSearchHint;
-    private Drawable mSearchIcon;
-    private String mSearchQuery;
-    private final Context mContext;
-    private final Set<Toolbar.OnSearchListener> mOnSearchListeners = new HashSet<>();
-    private final Set<Toolbar.OnSearchCompletedListener> mOnSearchCompletedListeners =
-            new HashSet<>();
-
-    private final Set<Toolbar.OnBackListener> mOnBackListeners = new HashSet<>();
-    private final Set<Toolbar.OnTabSelectedListener> mOnTabSelectedListeners = new HashSet<>();
-    private final Set<Toolbar.OnHeightChangedListener> mOnHeightChangedListeners = new HashSet<>();
-
-    private final MenuItem mOverflowButton;
-    private final boolean mIsTabsInSecondRow;
-    private boolean mShowTabsInSubpage = false;
-    private boolean mHasLogo = false;
-    private boolean mShowMenuItemsWhileSearching;
-    private Toolbar.State mState = Toolbar.State.HOME;
-    private Toolbar.NavButtonMode mNavButtonMode = Toolbar.NavButtonMode.BACK;
-    @NonNull
-    private List<MenuItem> mMenuItems = Collections.emptyList();
-    private List<MenuItem> mOverflowItems = new ArrayList<>();
-    private final List<MenuItemRenderer> mMenuItemRenderers = new ArrayList<>();
-    private View[] mMenuItemViews;
-    private int mMenuItemsXmlId = 0;
-    private AlertDialog mOverflowDialog;
-    private boolean mNavIconSpaceReserved;
-    private boolean mLogoFillsNavIconSpace;
-    private boolean mShowLogo;
-    private ProgressBarController mProgressBar;
-    private MenuItem.Listener mOverflowItemListener = () -> {
-        createOverflowDialog();
-        setState(getState());
-    };
-
-    // Despite the warning, this has to be a field so it's not garbage-collected.
-    // The only other reference to it is a weak reference
-    private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener
-            mOnUxRestrictionsChangedListener = restrictions -> {
-                for (MenuItemRenderer renderer : mMenuItemRenderers) {
-                    renderer.setCarUxRestrictions(restrictions);
-                }
-            };
-
-    public ToolbarControllerImpl(View view) {
-        mContext = view.getContext();
-        mOverflowButton = MenuItem.builder(getContext())
-                .setIcon(R.drawable.car_ui_icon_overflow_menu)
-                .setTitle(R.string.car_ui_toolbar_menu_item_overflow_title)
-                .setOnClickListener(v -> {
-                    if (mOverflowDialog == null) {
-                        if (Log.isLoggable(TAG, Log.ERROR)) {
-                            Log.e(TAG, "Overflow dialog was null when trying to show it!");
-                        }
-                    } else {
-                        mOverflowDialog.show();
-                    }
-                })
-                .build();
-
-        mIsTabsInSecondRow = getContext().getResources().getBoolean(
-                R.bool.car_ui_toolbar_tabs_on_second_row);
-        mNavIconSpaceReserved = getContext().getResources().getBoolean(
-                R.bool.car_ui_toolbar_nav_icon_reserve_space);
-        mLogoFillsNavIconSpace = getContext().getResources().getBoolean(
-                R.bool.car_ui_toolbar_logo_fills_nav_icon_space);
-        mShowLogo = getContext().getResources().getBoolean(
-                R.bool.car_ui_toolbar_show_logo);
-        mSearchHint = getContext().getString(R.string.car_ui_toolbar_default_search_hint);
-
-        mBackground = requireViewByRefId(view, R.id.car_ui_toolbar_background);
-        mTabLayout = requireViewByRefId(view, R.id.car_ui_toolbar_tabs);
-        mNavIcon = requireViewByRefId(view, R.id.car_ui_toolbar_nav_icon);
-        mLogoInNavIconSpace = requireViewByRefId(view, R.id.car_ui_toolbar_logo);
-        mNavIconContainer = requireViewByRefId(view, R.id.car_ui_toolbar_nav_icon_container);
-        mMenuItemsContainer = requireViewByRefId(view, R.id.car_ui_toolbar_menu_items_container);
-        mTitleContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_container);
-        mSubtitle = requireViewByRefId(view, R.id.car_ui_toolbar_subtitle);
-        mTitle = requireViewByRefId(view, R.id.car_ui_toolbar_title);
-        mTitleLogoContainer = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo_container);
-        mTitleLogo = requireViewByRefId(view, R.id.car_ui_toolbar_title_logo);
-        mSearchViewContainer = requireViewByRefId(view, R.id.car_ui_toolbar_search_view_container);
-        mProgressBar = new ProgressBarControllerImpl(
-                requireViewByRefId(view, R.id.car_ui_toolbar_progress_bar));
-
-        mTabLayout.addListener(new TabLayout.Listener() {
-            @Override
-            public void onTabSelected(TabLayout.Tab tab) {
-                for (Toolbar.OnTabSelectedListener listener : mOnTabSelectedListeners) {
-                    listener.onTabSelected(tab);
-                }
-            }
-        });
-
-        mBackground.addOnLayoutChangeListener((v, left, top, right, bottom,
-                oldLeft, oldTop, oldRight, oldBottom) -> {
-            if (oldBottom - oldTop != bottom - top) {
-                for (Toolbar.OnHeightChangedListener listener : mOnHeightChangedListeners) {
-                    listener.onHeightChanged(mBackground.getHeight());
-                }
-            }
-        });
-
-        setBackgroundShown(true);
-
-        // This holds weak references so we don't need to unregister later
-        CarUxRestrictionsUtil.getInstance(getContext())
-                .register(mOnUxRestrictionsChangedListener);
-    }
-
-    private Context getContext() {
-        return mContext;
-    }
-
-    /**
-     * Returns {@code true} if a two row layout in enabled for the toolbar.
-     */
-    public boolean isTabsInSecondRow() {
-        return mIsTabsInSecondRow;
-    }
-
-    /**
-     * Sets the title of the toolbar to a string resource.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    public void setTitle(@StringRes int title) {
-        mTitle.setText(title);
-        setState(getState());
-    }
-
-    /**
-     * Sets the title of the toolbar to a CharSequence.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    public void setTitle(CharSequence title) {
-        mTitle.setText(title);
-        setState(getState());
-    }
-
-    public CharSequence getTitle() {
-        return mTitle.getText();
-    }
-
-    /**
-     * Sets the subtitle of the toolbar to a string resource.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    @Override
-    public void setSubtitle(@StringRes int title) {
-        mSubtitle.setText(title);
-        setState(getState());
-    }
-
-    /**
-     * Sets the subtitle of the toolbar to a CharSequence.
-     *
-     * <p>The title may not always be shown, for example with one row layout with tabs.
-     */
-    @Override
-    public void setSubtitle(CharSequence title) {
-        mSubtitle.setText(title);
-        setState(getState());
-    }
-
-    @Override
-    public CharSequence getSubtitle() {
-        return mSubtitle.getText();
-    }
-
-    /**
-     * Gets the {@link TabLayout} for this toolbar.
-     */
-    public TabLayout getTabLayout() {
-        return mTabLayout;
-    }
-
-    /**
-     * Adds a tab to this toolbar. You can listen for when it is selected via
-     * {@link #registerOnTabSelectedListener(Toolbar.OnTabSelectedListener)}.
-     */
-    public void addTab(TabLayout.Tab tab) {
-        mTabLayout.addTab(tab);
-        setState(getState());
-    }
-
-    /** Removes all the tabs. */
-    public void clearAllTabs() {
-        mTabLayout.clearAllTabs();
-        setState(getState());
-    }
-
-    /**
-     * Gets a tab added to this toolbar. See
-     * {@link #addTab(TabLayout.Tab)}.
-     */
-    public TabLayout.Tab getTab(int position) {
-        return mTabLayout.get(position);
-    }
-
-    /**
-     * Selects a tab added to this toolbar. See
-     * {@link #addTab(TabLayout.Tab)}.
-     */
-    public void selectTab(int position) {
-        mTabLayout.selectTab(position);
-    }
-
-    /**
-     * Sets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
-     */
-    public void setShowTabsInSubpage(boolean showTabs) {
-        if (showTabs != mShowTabsInSubpage) {
-            mShowTabsInSubpage = showTabs;
-            setState(getState());
-        }
-    }
-
-    /**
-     * Gets whether or not tabs should also be shown in the SUBPAGE {@link Toolbar.State}.
-     */
-    public boolean getShowTabsInSubpage() {
-        return mShowTabsInSubpage;
-    }
-
-    /**
-     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
-     * will be displayed next to the title.
-     */
-    public void setLogo(@DrawableRes int resId) {
-        setLogo(resId != 0 ? getContext().getDrawable(resId) : null);
-    }
-
-    /**
-     * Sets the logo to display in this toolbar. If navigation icon is being displayed, this logo
-     * will be displayed next to the title.
-     */
-    public void setLogo(Drawable drawable) {
-        if (!mShowLogo) {
-            // If no logo should be shown then we act as if we never received one.
-            return;
-        }
-        if (drawable != null) {
-            mLogoInNavIconSpace.setImageDrawable(drawable);
-            mTitleLogo.setImageDrawable(drawable);
-            mHasLogo = true;
-        } else {
-            mHasLogo = false;
-        }
-        setState(mState);
-    }
-
-    /** Sets the hint for the search bar. */
-    public void setSearchHint(@StringRes int resId) {
-        setSearchHint(getContext().getString(resId));
-    }
-
-    /** Sets the hint for the search bar. */
-    public void setSearchHint(CharSequence hint) {
-        mSearchHint = hint;
-        if (mSearchView != null) {
-            mSearchView.setHint(mSearchHint);
-        }
-    }
-
-    /** Gets the search hint */
-    public CharSequence getSearchHint() {
-        return mSearchHint;
-    }
-
-    /**
-     * Sets the icon to display in the search box.
-     *
-     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
-     * a similar place.
-     */
-    public void setSearchIcon(@DrawableRes int resId) {
-        setSearchIcon(getContext().getDrawable(resId));
-    }
-
-    /**
-     * Sets the icon to display in the search box.
-     *
-     * <p>The icon will be lost on configuration change, make sure to set it in onCreate() or
-     * a similar place.
-     */
-    public void setSearchIcon(Drawable d) {
-        if (!Objects.equals(d, mSearchIcon)) {
-            mSearchIcon = d;
-            if (mSearchView != null) {
-                mSearchView.setIcon(mSearchIcon);
-            }
-        }
-    }
-
-
-    /** Sets the {@link Toolbar.NavButtonMode} */
-    public void setNavButtonMode(Toolbar.NavButtonMode style) {
-        if (style != mNavButtonMode) {
-            mNavButtonMode = style;
-            setState(mState);
-        }
-    }
-
-    /** Gets the {@link Toolbar.NavButtonMode} */
-    public Toolbar.NavButtonMode getNavButtonMode() {
-        return mNavButtonMode;
-    }
-
-    /** Show/hide the background. When hidden, the toolbar is completely transparent. */
-    public void setBackgroundShown(boolean shown) {
-        if (shown) {
-            mBackground.setBackground(
-                    getContext().getDrawable(R.drawable.car_ui_toolbar_background));
-        } else {
-            mBackground.setBackground(null);
-        }
-    }
-
-    /** Returns true is the toolbar background is shown */
-    public boolean getBackgroundShown() {
-        return mBackground.getBackground() != null;
-    }
-
-    private void setMenuItemsInternal(@Nullable List<MenuItem> items) {
-        if (items == null) {
-            items = Collections.emptyList();
-        }
-
-        List<MenuItem> visibleMenuItems = new ArrayList<>();
-        List<MenuItem> overflowItems = new ArrayList<>();
-        AtomicInteger loadedMenuItems = new AtomicInteger(0);
-
-        synchronized (this) {
-            if (items.equals(mMenuItems)) {
-                return;
-            }
-
-            for (MenuItem item : items) {
-                if (item.getDisplayBehavior() == MenuItem.DisplayBehavior.NEVER) {
-                    overflowItems.add(item);
-                    item.setListener(mOverflowItemListener);
-                } else {
-                    visibleMenuItems.add(item);
-                }
-            }
-
-            // Copy the list so that if the list is modified and setMenuItems is called again,
-            // the equals() check will fail. Note that the MenuItems are not copied here.
-            mMenuItems = new ArrayList<>(items);
-            mOverflowItems = overflowItems;
-            mMenuItemRenderers.clear();
-            mMenuItemsContainer.removeAllViews();
-
-            if (!overflowItems.isEmpty()) {
-                visibleMenuItems.add(mOverflowButton);
-                createOverflowDialog();
-            }
-
-            View[] menuItemViews = new View[visibleMenuItems.size()];
-            mMenuItemViews = menuItemViews;
-
-            for (int i = 0; i < visibleMenuItems.size(); ++i) {
-                int index = i;
-                MenuItem item = visibleMenuItems.get(i);
-                MenuItemRenderer renderer = new MenuItemRenderer(item, mMenuItemsContainer);
-                mMenuItemRenderers.add(renderer);
-                renderer.createView(view -> {
-                    synchronized (ToolbarControllerImpl.this) {
-                        if (menuItemViews != mMenuItemViews) {
-                            return;
-                        }
-
-                        menuItemViews[index] = view;
-                        if (loadedMenuItems.addAndGet(1) == menuItemViews.length) {
-                            for (View v : menuItemViews) {
-                                mMenuItemsContainer.addView(v);
-                            }
-                        }
-                    }
-                });
-            }
-        }
-
-        setState(mState);
-    }
-
-    /**
-     * Sets the {@link MenuItem Menuitems} to display.
-     */
-    public void setMenuItems(@Nullable List<MenuItem> items) {
-        mMenuItemsXmlId = 0;
-        setMenuItemsInternal(items);
-    }
-
-    /**
-     * Sets the {@link MenuItem Menuitems} to display to a list defined in XML.
-     *
-     * <p>If this method is called twice with the same argument (and {@link #setMenuItems(List)}
-     * wasn't called), nothing will happen the second time, even if the MenuItems were changed.
-     *
-     * <p>The XML file must have one <MenuItems> tag, with a variable number of <MenuItem>
-     * child tags. See CarUiToolbarMenuItem in CarUi's attrs.xml for a list of available attributes.
-     *
-     * Example:
-     * <pre>
-     * <MenuItems>
-     *     <MenuItem
-     *         app:title="Foo"/>
-     *     <MenuItem
-     *         app:title="Bar"
-     *         app:icon="@drawable/ic_tracklist"
-     *         app:onClick="xmlMenuItemClicked"/>
-     *     <MenuItem
-     *         app:title="Bar"
-     *         app:checkable="true"
-     *         app:uxRestrictions="FULLY_RESTRICTED"
-     *         app:onClick="xmlMenuItemClicked"/>
-     * </MenuItems>
-     * </pre>
-     *
-     * @return The MenuItems that were loaded from XML.
-     * @see #setMenuItems(List)
-     */
-    public List<MenuItem> setMenuItems(@XmlRes int resId) {
-        if (mMenuItemsXmlId != 0 && mMenuItemsXmlId == resId) {
-            return mMenuItems;
-        }
-
-        mMenuItemsXmlId = resId;
-        List<MenuItem> menuItems = MenuItemRenderer.readMenuItemList(getContext(), resId);
-        setMenuItemsInternal(menuItems);
-        return menuItems;
-    }
-
-    /** Gets the {@link MenuItem MenuItems} currently displayed */
-    @NonNull
-    public List<MenuItem> getMenuItems() {
-        return Collections.unmodifiableList(mMenuItems);
-    }
-
-    /** Gets a {@link MenuItem} by id. */
-    @Nullable
-    public MenuItem findMenuItemById(int id) {
-        for (MenuItem item : mMenuItems) {
-            if (item.getId() == id) {
-                return item;
-            }
-        }
-        return null;
-    }
-
-    /** Gets a {@link MenuItem} by id. Will throw an IllegalArgumentException if not found. */
-    @NonNull
-    public MenuItem requireMenuItemById(int id) {
-        MenuItem result = findMenuItemById(id);
-
-        if (result == null) {
-            throw new IllegalArgumentException("ID does not reference a MenuItem on this Toolbar");
-        }
-
-        return result;
-    }
-
-    private int countVisibleOverflowItems() {
-        int numVisibleItems = 0;
-        for (MenuItem item : mOverflowItems) {
-            if (item.isVisible()) {
-                numVisibleItems++;
-            }
-        }
-        return numVisibleItems;
-    }
-
-    private void createOverflowDialog() {
-        // TODO(b/140564530) Use a carui alert with a (car ui)recyclerview here
-        // TODO(b/140563930) Support enabled/disabled overflow items
-
-        CharSequence[] itemTitles = new CharSequence[countVisibleOverflowItems()];
-        int i = 0;
-        for (MenuItem item : mOverflowItems) {
-            if (item.isVisible()) {
-                itemTitles[i++] = item.getTitle();
-            }
-        }
-
-        mOverflowDialog = new AlertDialog.Builder(getContext())
-                .setItems(itemTitles, (dialog, which) -> {
-                    MenuItem item = mOverflowItems.get(which);
-                    MenuItem.OnClickListener listener = item.getOnClickListener();
-                    if (listener != null) {
-                        listener.onClick(item);
-                    }
-                })
-                .create();
-    }
-
-
-    /**
-     * Set whether or not to show the {@link MenuItem MenuItems} while searching. Default false.
-     * Even if this is set to true, the {@link MenuItem} created by
-     * {@link MenuItem.Builder#setToSearch()} will still be hidden.
-     */
-    public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
-        mShowMenuItemsWhileSearching = showMenuItems;
-        setState(mState);
-    }
-
-    /** Returns if {@link MenuItem MenuItems} are shown while searching */
-    public boolean getShowMenuItemsWhileSearching() {
-        return mShowMenuItemsWhileSearching;
-    }
-
-    /**
-     * Sets the search query.
-     */
-    public void setSearchQuery(String query) {
-        if (mSearchView != null) {
-            mSearchView.setSearchQuery(query);
-        } else {
-            mSearchQuery = query;
-            for (Toolbar.OnSearchListener listener : mOnSearchListeners) {
-                listener.onSearch(query);
-            }
-        }
-    }
-
-    /**
-     * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
-     * for the desired state.
-     */
-    public void setState(Toolbar.State state) {
-        mState = state;
-
-        if (mSearchView == null && (state == Toolbar.State.SEARCH || state == Toolbar.State.EDIT)) {
-            SearchView searchView = new SearchView(getContext());
-            searchView.setHint(mSearchHint);
-            searchView.setIcon(mSearchIcon);
-            searchView.setSearchQuery(mSearchQuery);
-            searchView.setSearchListeners(mOnSearchListeners);
-            searchView.setSearchCompletedListeners(mOnSearchCompletedListeners);
-            searchView.setVisibility(GONE);
-
-            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT);
-            mSearchViewContainer.addView(searchView, layoutParams);
-
-            mSearchView = searchView;
-        }
-
-        for (MenuItemRenderer renderer : mMenuItemRenderers) {
-            renderer.setToolbarState(mState);
-        }
-
-        View.OnClickListener backClickListener = (v) -> {
-            boolean absorbed = false;
-            List<Toolbar.OnBackListener> listenersCopy = new ArrayList<>(mOnBackListeners);
-            for (Toolbar.OnBackListener listener : listenersCopy) {
-                absorbed = absorbed || listener.onBack();
-            }
-
-            if (!absorbed) {
-                Activity activity = CarUiUtils.getActivity(getContext());
-                if (activity != null) {
-                    activity.onBackPressed();
-                }
-            }
-        };
-
-        if (state == Toolbar.State.SEARCH) {
-            mNavIcon.setImageResource(R.drawable.car_ui_icon_search_nav_icon);
-        } else {
-            switch (mNavButtonMode) {
-                case CLOSE:
-                    mNavIcon.setImageResource(R.drawable.car_ui_icon_close);
-                    break;
-                case DOWN:
-                    mNavIcon.setImageResource(R.drawable.car_ui_icon_down);
-                    break;
-                default:
-                    mNavIcon.setImageResource(R.drawable.car_ui_icon_arrow_back);
-                    break;
-            }
-        }
-
-        mNavIcon.setVisibility(state != Toolbar.State.HOME ? VISIBLE : GONE);
-
-        // Show the logo in the nav space if that's enabled, we have a logo,
-        // and we're in the Home state.
-        mLogoInNavIconSpace.setVisibility(mHasLogo
-                && state == Toolbar.State.HOME
-                && mLogoFillsNavIconSpace
-                ? VISIBLE : INVISIBLE);
-
-        // Show logo next to the title if we're in the subpage state or we're configured to not show
-        // the logo in the nav icon space.
-        mTitleLogoContainer.setVisibility(mHasLogo
-                && (state == Toolbar.State.SUBPAGE
-                || (state == Toolbar.State.HOME && !mLogoFillsNavIconSpace))
-                ? VISIBLE : GONE);
-
-        // Show the nav icon container if we're not in the home space or the logo fills the nav icon
-        // container. If car_ui_toolbar_nav_icon_reserve_space is true, hiding it will still reserve
-        // its space
-        mNavIconContainer.setVisibility(
-                state != Toolbar.State.HOME || (mHasLogo && mLogoFillsNavIconSpace)
-                        ? VISIBLE : (mNavIconSpaceReserved ? INVISIBLE : GONE));
-        mNavIconContainer.setOnClickListener(
-                state != Toolbar.State.HOME ? backClickListener : null);
-        mNavIconContainer.setClickable(state != Toolbar.State.HOME);
-        mNavIconContainer.setContentDescription(state != Toolbar.State.HOME
-                ? mContext.getString(R.string.car_ui_toolbar_nav_icon_content_description)
-                : null);
-
-        boolean hasTabs = mTabLayout.getTabCount() > 0
-                && (state == Toolbar.State.HOME
-                || (state == Toolbar.State.SUBPAGE && mShowTabsInSubpage));
-        // Show the title if we're in the subpage state, or in the home state with no tabs or tabs
-        // on the second row
-        int visibility = (state == Toolbar.State.SUBPAGE || state == Toolbar.State.HOME)
-                && (!hasTabs || mIsTabsInSecondRow)
-                ? VISIBLE : GONE;
-        mTitleContainer.setVisibility(visibility);
-        mSubtitle.setVisibility(
-                TextUtils.isEmpty(mSubtitle.getText()) ? GONE : VISIBLE);
-
-        mTabLayout.setVisibility(hasTabs ? VISIBLE : GONE);
-
-        if (mSearchView != null) {
-            if (state == Toolbar.State.SEARCH || state == Toolbar.State.EDIT) {
-                mSearchView.setPlainText(state == Toolbar.State.EDIT);
-                mSearchView.setVisibility(VISIBLE);
-            } else {
-                mSearchView.setVisibility(GONE);
-            }
-        }
-
-        boolean showButtons = (state != Toolbar.State.SEARCH && state != Toolbar.State.EDIT)
-                || mShowMenuItemsWhileSearching;
-        mMenuItemsContainer.setVisibility(showButtons ? VISIBLE : GONE);
-        mOverflowButton.setVisible(showButtons && countVisibleOverflowItems() > 0);
-    }
-
-    /** Gets the current {@link Toolbar.State} of the toolbar. */
-    public Toolbar.State getState() {
-        return mState;
-    }
-
-
-    /**
-     * Registers a new {@link Toolbar.OnHeightChangedListener} to the list of listeners. Register a
-     * {@link com.android.car.ui.recyclerview.CarUiRecyclerView} only if there is a toolbar at
-     * the top and a {@link com.android.car.ui.recyclerview.CarUiRecyclerView} in the view and
-     * nothing else. {@link com.android.car.ui.recyclerview.CarUiRecyclerView} will
-     * automatically adjust its height according to the height of the Toolbar.
-     */
-    public void registerToolbarHeightChangeListener(
-            Toolbar.OnHeightChangedListener listener) {
-        mOnHeightChangedListeners.add(listener);
-    }
-
-    /**
-     * Unregisters an existing {@link Toolbar.OnHeightChangedListener} from the list of
-     * listeners.
-     */
-    public boolean unregisterToolbarHeightChangeListener(
-            Toolbar.OnHeightChangedListener listener) {
-        return mOnHeightChangedListeners.remove(listener);
-    }
-
-    /** Registers a new {@link Toolbar.OnTabSelectedListener} to the list of listeners. */
-    public void registerOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
-        mOnTabSelectedListeners.add(listener);
-    }
-
-    /** Unregisters an existing {@link Toolbar.OnTabSelectedListener} from the list of listeners. */
-    public boolean unregisterOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
-        return mOnTabSelectedListeners.remove(listener);
-    }
-
-    /** Registers a new {@link Toolbar.OnSearchListener} to the list of listeners. */
-    public void registerOnSearchListener(Toolbar.OnSearchListener listener) {
-        mOnSearchListeners.add(listener);
-    }
-
-    /** Unregisters an existing {@link Toolbar.OnSearchListener} from the list of listeners. */
-    public boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener) {
-        return mOnSearchListeners.remove(listener);
-    }
-
-    /** Registers a new {@link Toolbar.OnSearchCompletedListener} to the list of listeners. */
-    public void registerOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
-        mOnSearchCompletedListeners.add(listener);
-    }
-
-    /**
-     * Unregisters an existing {@link Toolbar.OnSearchCompletedListener} from the list of
-     * listeners.
-     */
-    public boolean unregisterOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
-        return mOnSearchCompletedListeners.remove(listener);
-    }
-
-    /** Registers a new {@link Toolbar.OnBackListener} to the list of listeners. */
-    public void registerOnBackListener(Toolbar.OnBackListener listener) {
-        mOnBackListeners.add(listener);
-    }
-
-    /** Unregisters an existing {@link Toolbar.OnBackListener} from the list of listeners. */
-    public boolean unregisterOnBackListener(Toolbar.OnBackListener listener) {
-        return mOnBackListeners.remove(listener);
-    }
-
-    /** Returns the progress bar */
-    public ProgressBarController getProgressBar() {
-        return mProgressBar;
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/utils/CarUiUtils.java b/car-ui-lib/src/com/android/car/ui/utils/CarUiUtils.java
deleted file mode 100644
index 497d028..0000000
--- a/car-ui-lib/src/com/android/car/ui/utils/CarUiUtils.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.utils;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.DimenRes;
-import androidx.annotation.IdRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StyleRes;
-import androidx.annotation.UiThread;
-import androidx.core.view.ViewCompat;
-
-/**
- * Collection of utility methods
- */
-public final class CarUiUtils {
-    /** This is a utility class */
-    private CarUiUtils() {
-    }
-
-    /**
-     * Reads a float value from a dimens resource. This is necessary as {@link Resources#getFloat}
-     * is not currently public.
-     *
-     * @param res {@link Resources} to read values from
-     * @param resId Id of the dimens resource to read
-     */
-    public static float getFloat(Resources res, @DimenRes int resId) {
-        TypedValue outValue = new TypedValue();
-        res.getValue(resId, outValue, true);
-        return outValue.getFloat();
-    }
-
-    /** Returns the identifier of the resolved resource assigned to the given attribute. */
-    public static int getAttrResourceId(Context context, int attr) {
-        return getAttrResourceId(context, /*styleResId=*/ 0, attr);
-    }
-
-    /**
-     * Returns the identifier of the resolved resource assigned to the given attribute defined in
-     * the given style.
-     */
-    public static int getAttrResourceId(Context context, @StyleRes int styleResId, int attr) {
-        TypedArray ta = context.obtainStyledAttributes(styleResId, new int[]{attr});
-        int resId = ta.getResourceId(0, 0);
-        ta.recycle();
-        return resId;
-    }
-
-    /**
-     * Gets the {@link Activity} for a certain {@link Context}.
-     *
-     * <p>It is possible the Context is not associated with an Activity, in which case
-     * this method will return null.
-     */
-    @Nullable
-    public static Activity getActivity(Context context) {
-        while (context instanceof ContextWrapper) {
-            if (context instanceof Activity) {
-                return (Activity) context;
-            }
-            context = ((ContextWrapper) context).getBaseContext();
-        }
-        return null;
-    }
-
-    /**
-     * It behaves similar to @see View#findViewById, except it resolves the ID reference first.
-     *
-     * @param id the ID to search for
-     * @return a view with given ID if found, or {@code null} otherwise
-     * @see View#requireViewById(int)
-     */
-    @Nullable
-    @UiThread
-    public static <T extends View> T findViewByRefId(@NonNull View root, @IdRes int id) {
-        if (id == View.NO_ID) {
-            return null;
-        }
-
-        TypedValue value = new TypedValue();
-        root.getResources().getValue(id, value, true);
-        return root.findViewById(value.resourceId);
-    }
-
-    /**
-     * It behaves similar to @see View#requireViewById, except it resolves the ID reference first.
-     *
-     * @param id the ID to search for
-     * @return a view with given ID
-     * @see View#findViewById(int)
-     */
-    @NonNull
-    @UiThread
-    public static <T extends View> T requireViewByRefId(@NonNull View root, @IdRes int id) {
-        T view = findViewByRefId(root, id);
-        if (view == null) {
-            throw new IllegalArgumentException("ID does not reference a View inside this View");
-        }
-        return view;
-    }
-
-    /**
-     * Updates the preference view enabled state. If the view is disabled we just disable the child
-     * of preference like TextView, ImageView. The preference itself is always enabled to get the
-     * click events. Ripple effect in background is also removed by default. If the ripple is
-     * needed see
-     * {@link IDisabledPreferenceCallback#setShouldShowRippleOnDisabledPreference(boolean)}
-     */
-    public static Drawable setPreferenceViewEnabled(boolean viewEnabled, View itemView,
-            Drawable background, boolean shouldShowRippleOnDisabledPreference) {
-        if (viewEnabled) {
-            if (background != null) {
-                ViewCompat.setBackground(itemView, background);
-            }
-            setChildViewsEnabled(itemView, true, false);
-        } else {
-            itemView.setEnabled(true);
-            if (background == null) {
-                // store the original background.
-                background = itemView.getBackground();
-            }
-            updateRippleStateOnDisabledPreference(false, shouldShowRippleOnDisabledPreference,
-                    background, itemView);
-            setChildViewsEnabled(itemView, false, true);
-        }
-        return background;
-    }
-
-    /**
-     * Sets the enabled state on the views of the preference. If the view is being disabled we want
-     * only child views of preference to be disabled.
-     */
-    private static void setChildViewsEnabled(View view, boolean enabled, boolean isRootView) {
-        if (!isRootView) {
-            view.setEnabled(enabled);
-        }
-        if (view instanceof ViewGroup) {
-            ViewGroup grp = (ViewGroup) view;
-            for (int index = 0; index < grp.getChildCount(); index++) {
-                setChildViewsEnabled(grp.getChildAt(index), enabled, false);
-            }
-        }
-    }
-
-    /**
-     * Updates the ripple state on the given preference.
-     *
-     * @param isEnabled whether the preference is enabled or not
-     * @param shouldShowRippleOnDisabledPreference should ripple be displayed when the preference is
-     * clicked
-     * @param background drawable that represents the ripple
-     * @param preference preference on which drawable will be applied
-     */
-    public static void updateRippleStateOnDisabledPreference(boolean isEnabled,
-            boolean shouldShowRippleOnDisabledPreference, Drawable background, View preference) {
-        if (isEnabled || preference == null) {
-            return;
-        }
-        if (shouldShowRippleOnDisabledPreference && background != null) {
-            ViewCompat.setBackground(preference, background);
-        } else {
-            ViewCompat.setBackground(preference, null);
-        }
-    }
-}
diff --git a/car-ui-lib/src/com/android/car/ui/utils/CarUxRestrictionsUtil.java b/car-ui-lib/src/com/android/car/ui/utils/CarUxRestrictionsUtil.java
deleted file mode 100644
index 31ac24a..0000000
--- a/car-ui-lib/src/com/android/car/ui/utils/CarUxRestrictionsUtil.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.utils;
-
-import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH;
-
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.drivingstate.CarUxRestrictions;
-import android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo;
-import android.car.drivingstate.CarUxRestrictionsManager;
-import android.content.Context;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.ui.R;
-
-import java.util.Collections;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-/**
- * Utility class to access Car Restriction Manager.
- *
- * <p>This class must be a singleton because only one listener can be registered with {@link
- * CarUxRestrictionsManager} at a time, as documented in {@link
- * CarUxRestrictionsManager#registerListener}.
- */
-public class CarUxRestrictionsUtil {
-    private static final String TAG = "CarUxRestrictionsUtil";
-
-    private final Car mCarApi;
-    private CarUxRestrictionsManager mCarUxRestrictionsManager;
-    @NonNull
-    private CarUxRestrictions mCarUxRestrictions = getDefaultRestrictions();
-
-    private Set<OnUxRestrictionsChangedListener> mObservers;
-    private static CarUxRestrictionsUtil sInstance = null;
-
-    private CarUxRestrictionsUtil(Context context) {
-        CarUxRestrictionsManager.OnUxRestrictionsChangedListener listener =
-                (carUxRestrictions) -> {
-                    if (carUxRestrictions == null) {
-                        mCarUxRestrictions = getDefaultRestrictions();
-                    } else {
-                        mCarUxRestrictions = carUxRestrictions;
-                    }
-
-                    for (OnUxRestrictionsChangedListener observer : mObservers) {
-                        observer.onRestrictionsChanged(mCarUxRestrictions);
-                    }
-                };
-
-        mCarApi = Car.createCar(context.getApplicationContext());
-        mObservers = Collections.newSetFromMap(new WeakHashMap<>());
-
-        try {
-            mCarUxRestrictionsManager =
-                    (CarUxRestrictionsManager) mCarApi.getCarManager(
-                            Car.CAR_UX_RESTRICTION_SERVICE);
-            mCarUxRestrictionsManager.registerListener(listener);
-            listener.onUxRestrictionsChanged(
-                    mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
-        } catch (CarNotConnectedException | NullPointerException e) {
-            Log.e(TAG, "Car not connected", e);
-            // mCarUxRestrictions will be the default
-        }
-    }
-
-    @NonNull
-    private static CarUxRestrictions getDefaultRestrictions() {
-        return new CarUxRestrictions.Builder(
-                true, CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0)
-                .build();
-    }
-
-    /** Listener interface used to update clients on UxRestrictions changes */
-    public interface OnUxRestrictionsChangedListener {
-        /** Called when CarUxRestrictions changes */
-        void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions);
-    }
-
-    /** Returns the singleton sInstance of this class */
-    @NonNull
-    public static CarUxRestrictionsUtil getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new CarUxRestrictionsUtil(context);
-        }
-
-        return sInstance;
-    }
-
-    /**
-     * Registers a listener on this class for updates to CarUxRestrictions. Multiple listeners may
-     * be registered. Note that this class will only hold a weak reference to the listener, you
-     * must maintain a strong reference to it elsewhere.
-     */
-    public void register(OnUxRestrictionsChangedListener listener) {
-        mObservers.add(listener);
-        listener.onRestrictionsChanged(mCarUxRestrictions);
-    }
-
-    /** Unregisters a registered listener */
-    public void unregister(OnUxRestrictionsChangedListener listener) {
-        mObservers.remove(listener);
-    }
-
-    @NonNull
-    public CarUxRestrictions getCurrentRestrictions() {
-        return mCarUxRestrictions;
-    }
-
-    /**
-     * Returns whether any of the given flags are blocked by the specified restrictions. If null is
-     * given, the method returns true for safety.
-     */
-    public static boolean isRestricted(
-            @CarUxRestrictionsInfo int restrictionFlags, @Nullable CarUxRestrictions uxr) {
-        return (uxr == null) || ((uxr.getActiveRestrictions() & restrictionFlags) != 0);
-    }
-
-    /**
-     * Complies the input string with the given UX restrictions. Returns the original string if
-     * already compliant, otherwise a shortened ellipsized string.
-     */
-    public static String complyString(Context context, String str, CarUxRestrictions uxr) {
-
-        if (isRestricted(UX_RESTRICTIONS_LIMIT_STRING_LENGTH, uxr)) {
-            int maxLength =
-                    uxr == null
-                            ? context.getResources().getInteger(
-                            R.integer.car_ui_default_max_string_length)
-                            : uxr.getMaxRestrictedStringLength();
-
-            if (str.length() > maxLength) {
-                return str.substring(0, maxLength) + context.getString(R.string.car_ui_ellipsis);
-            }
-        }
-
-        return str;
-    }
-
-    /** Sets car UX restrictions. Only used for testing. */
-    @VisibleForTesting
-    public void setUxRestrictions(CarUxRestrictions carUxRestrictions) {
-        mCarUxRestrictions = carUxRestrictions;
-    }
-}
diff --git a/car-ui-lib/tests/apitest/auto-generate-resources.py b/car-ui-lib/tests/apitest/auto-generate-resources.py
index 035959c..10143c0 100755
--- a/car-ui-lib/tests/apitest/auto-generate-resources.py
+++ b/car-ui-lib/tests/apitest/auto-generate-resources.py
@@ -62,10 +62,10 @@
 
     output_file = args.file or 'current.xml'
     if args.compare:
-        compare_resources(ROOT_FOLDER+'/res', OUTPUT_FILE_PATH + 'current.xml')
+        compare_resources(ROOT_FOLDER+'/car-ui-lib/src/main/res', OUTPUT_FILE_PATH + 'current.xml')
     else:
-        generate_current_file(ROOT_FOLDER+'/res', output_file)
-        generate_overlayable_file(ROOT_FOLDER+'/res')
+        generate_current_file(ROOT_FOLDER+'/car-ui-lib/src/main/res', output_file)
+        generate_overlayable_file(ROOT_FOLDER+'/car-ui-lib/src/main/res')
 
 def generate_current_file(res_folder, output_file='current.xml'):
     resources = get_all_resources(res_folder)
@@ -167,7 +167,7 @@
 
     data = etree.ElementTree(root)
 
-    output_file=ROOT_FOLDER+'/res-overlayable/values/overlayable.xml'
+    output_file=ROOT_FOLDER+'/car-ui-lib/src/main/res-overlayable/values/overlayable.xml'
     with open(output_file, 'wb') as f:
         data.write(f, pretty_print=True, xml_declaration=True, encoding='utf-8')
 
diff --git a/car-ui-lib/tests/apitest/current.xml b/car-ui-lib/tests/apitest/current.xml
index 99adc12..6abc24d 100644
--- a/car-ui-lib/tests/apitest/current.xml
+++ b/car-ui-lib/tests/apitest/current.xml
@@ -5,6 +5,12 @@
   <public type="attr" name="carUiPreferenceStyle"/>
   <public type="attr" name="carUiRecyclerViewStyle"/>
   <public type="attr" name="state_ux_restricted"/>
+  <public type="bool" name="car_ui_alert_dialog_force_dismiss_button"/>
+  <public type="bool" name="car_ui_clear_focus_area_history_when_rotating"/>
+  <public type="bool" name="car_ui_enable_focus_area_background_highlight"/>
+  <public type="bool" name="car_ui_enable_focus_area_foreground_highlight"/>
+  <public type="bool" name="car_ui_escrow_check_components_automatically"/>
+  <public type="bool" name="car_ui_focus_area_default_focus_overrides_history"/>
   <public type="bool" name="car_ui_list_item_single_line_title"/>
   <public type="bool" name="car_ui_preference_list_show_full_screen"/>
   <public type="bool" name="car_ui_preference_show_chevron"/>
@@ -16,18 +22,18 @@
   <public type="bool" name="car_ui_toolbar_tabs_on_second_row"/>
   <public type="color" name="car_ui_activity_background_color"/>
   <public type="color" name="car_ui_color_accent"/>
-  <public type="color" name="car_ui_list_item_body_text_color"/>
+  <public type="color" name="car_ui_dialog_icon_color"/>
   <public type="color" name="car_ui_list_item_divider"/>
-  <public type="color" name="car_ui_list_item_header_text_color"/>
-  <public type="color" name="car_ui_list_item_title_text_color"/>
-  <public type="color" name="car_ui_preference_category_title_text_color"/>
-  <public type="color" name="car_ui_preference_edit_text_dialog_message_text_color"/>
   <public type="color" name="car_ui_preference_icon_color"/>
-  <public type="color" name="car_ui_preference_summary_text_color"/>
-  <public type="color" name="car_ui_preference_switch_track_text_color"/>
-  <public type="color" name="car_ui_preference_title_text_color"/>
+  <public type="color" name="car_ui_preference_two_action_divider_color"/>
   <public type="color" name="car_ui_recyclerview_divider_color"/>
   <public type="color" name="car_ui_ripple_color"/>
+  <public type="color" name="car_ui_rotary_focus_fill_color"/>
+  <public type="color" name="car_ui_rotary_focus_fill_secondary_color"/>
+  <public type="color" name="car_ui_rotary_focus_pressed_fill_color"/>
+  <public type="color" name="car_ui_rotary_focus_pressed_stroke_color"/>
+  <public type="color" name="car_ui_rotary_focus_stroke_color"/>
+  <public type="color" name="car_ui_rotary_focus_stroke_secondary_color"/>
   <public type="color" name="car_ui_scrollbar_thumb"/>
   <public type="color" name="car_ui_text_color_hint"/>
   <public type="color" name="car_ui_text_color_primary"/>
@@ -50,14 +56,12 @@
   <public type="dimen" name="car_ui_dialog_edittext_margin_top"/>
   <public type="dimen" name="car_ui_dialog_icon_size"/>
   <public type="dimen" name="car_ui_dialog_title_margin"/>
+  <public type="dimen" name="car_ui_divider_width"/>
   <public type="dimen" name="car_ui_header_list_item_text_start_margin"/>
-  <public type="dimen" name="car_ui_letter_spacing_body1"/>
-  <public type="dimen" name="car_ui_letter_spacing_body3"/>
   <public type="dimen" name="car_ui_list_item_action_divider_height"/>
   <public type="dimen" name="car_ui_list_item_action_divider_width"/>
   <public type="dimen" name="car_ui_list_item_avatar_icon_height"/>
   <public type="dimen" name="car_ui_list_item_avatar_icon_width"/>
-  <public type="dimen" name="car_ui_list_item_body_text_size"/>
   <public type="dimen" name="car_ui_list_item_check_box_end_inset"/>
   <public type="dimen" name="car_ui_list_item_check_box_height"/>
   <public type="dimen" name="car_ui_list_item_check_box_icon_container_width"/>
@@ -67,7 +71,6 @@
   <public type="dimen" name="car_ui_list_item_end_inset"/>
   <public type="dimen" name="car_ui_list_item_header_height"/>
   <public type="dimen" name="car_ui_list_item_header_start_inset"/>
-  <public type="dimen" name="car_ui_list_item_header_text_size"/>
   <public type="dimen" name="car_ui_list_item_height"/>
   <public type="dimen" name="car_ui_list_item_icon_container_width"/>
   <public type="dimen" name="car_ui_list_item_icon_size"/>
@@ -79,7 +82,6 @@
   <public type="dimen" name="car_ui_list_item_supplemental_icon_size"/>
   <public type="dimen" name="car_ui_list_item_text_no_icon_start_margin"/>
   <public type="dimen" name="car_ui_list_item_text_start_margin"/>
-  <public type="dimen" name="car_ui_list_item_title_text_size"/>
   <public type="dimen" name="car_ui_margin"/>
   <public type="dimen" name="car_ui_padding_0"/>
   <public type="dimen" name="car_ui_padding_1"/>
@@ -91,7 +93,6 @@
   <public type="dimen" name="car_ui_preference_category_icon_margin_end"/>
   <public type="dimen" name="car_ui_preference_category_icon_size"/>
   <public type="dimen" name="car_ui_preference_category_min_height"/>
-  <public type="dimen" name="car_ui_preference_category_text_size"/>
   <public type="dimen" name="car_ui_preference_content_margin_bottom"/>
   <public type="dimen" name="car_ui_preference_content_margin_top"/>
   <public type="dimen" name="car_ui_preference_dropdown_padding_start"/>
@@ -100,23 +101,18 @@
   <public type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_bottom"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_end"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_message_margin_start"/>
-  <public type="dimen" name="car_ui_preference_edit_text_dialog_message_text_size"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_end"/>
   <public type="dimen" name="car_ui_preference_edit_text_dialog_text_margin_start"/>
   <public type="dimen" name="car_ui_preference_icon_margin_end"/>
   <public type="dimen" name="car_ui_preference_icon_size"/>
-  <public type="dimen" name="car_ui_preference_summary_text_size"/>
-  <public type="dimen" name="car_ui_preference_switch_height"/>
-  <public type="dimen" name="car_ui_preference_switch_text_size"/>
-  <public type="dimen" name="car_ui_preference_switch_width"/>
-  <public type="dimen" name="car_ui_preference_switch_width_half"/>
-  <public type="dimen" name="car_ui_preference_title_text_size"/>
   <public type="dimen" name="car_ui_primary_icon_size"/>
   <public type="dimen" name="car_ui_recyclerview_divider_bottom_margin"/>
   <public type="dimen" name="car_ui_recyclerview_divider_end_margin"/>
   <public type="dimen" name="car_ui_recyclerview_divider_height"/>
   <public type="dimen" name="car_ui_recyclerview_divider_start_margin"/>
   <public type="dimen" name="car_ui_recyclerview_divider_top_margin"/>
+  <public type="dimen" name="car_ui_rotary_focus_pressed_stroke_width"/>
+  <public type="dimen" name="car_ui_rotary_focus_stroke_width"/>
   <public type="dimen" name="car_ui_scrollbar_button_size"/>
   <public type="dimen" name="car_ui_scrollbar_container_width"/>
   <public type="dimen" name="car_ui_scrollbar_decelerate_interpolator_factor"/>
@@ -161,15 +157,22 @@
   <public type="dimen" name="car_ui_toolbar_title_no_logo_margin_start"/>
   <public type="dimen" name="car_ui_toolbar_top_inset"/>
   <public type="dimen" name="car_ui_touch_target_height"/>
+  <public type="dimen" name="car_ui_touch_target_size"/>
   <public type="dimen" name="car_ui_touch_target_width"/>
   <public type="dimen" name="wrap_content"/>
   <public type="drawable" name="car_ui_activity_background"/>
   <public type="drawable" name="car_ui_divider"/>
+  <public type="drawable" name="car_ui_focus_area_background_highlight"/>
+  <public type="drawable" name="car_ui_focus_area_foreground_highlight"/>
+  <public type="drawable" name="car_ui_icon_add"/>
   <public type="drawable" name="car_ui_icon_arrow_back"/>
   <public type="drawable" name="car_ui_icon_close"/>
+  <public type="drawable" name="car_ui_icon_delete"/>
   <public type="drawable" name="car_ui_icon_down"/>
+  <public type="drawable" name="car_ui_icon_edit"/>
   <public type="drawable" name="car_ui_icon_lock"/>
   <public type="drawable" name="car_ui_icon_overflow_menu"/>
+  <public type="drawable" name="car_ui_icon_save"/>
   <public type="drawable" name="car_ui_icon_search"/>
   <public type="drawable" name="car_ui_icon_search_nav_icon"/>
   <public type="drawable" name="car_ui_icon_settings"/>
@@ -195,17 +198,18 @@
   <public type="id" name="action_container"/>
   <public type="id" name="action_container_touch_interceptor"/>
   <public type="id" name="action_divider"/>
+  <public type="id" name="action_widget_container"/>
   <public type="id" name="avatar_icon"/>
   <public type="id" name="body"/>
   <public type="id" name="car_ui_alert_icon"/>
   <public type="id" name="car_ui_alert_subtitle"/>
   <public type="id" name="car_ui_alert_title"/>
   <public type="id" name="car_ui_base_layout_content_container"/>
-  <public type="id" name="car_ui_check_box_end_guideline"/>
-  <public type="id" name="car_ui_check_box_start_guideline"/>
+  <public type="id" name="car_ui_focus_area"/>
   <public type="id" name="car_ui_list_item_end_guideline"/>
   <public type="id" name="car_ui_list_item_start_guideline"/>
   <public type="id" name="car_ui_list_limiting_message"/>
+  <public type="id" name="car_ui_preference_container_without_widget"/>
   <public type="id" name="car_ui_preference_fragment_container"/>
   <public type="id" name="car_ui_recycler_view"/>
   <public type="id" name="car_ui_scroll_bar"/>
@@ -223,6 +227,7 @@
   <public type="id" name="car_ui_toolbar_menu_item_icon_container"/>
   <public type="id" name="car_ui_toolbar_menu_item_switch"/>
   <public type="id" name="car_ui_toolbar_menu_item_text"/>
+  <public type="id" name="car_ui_toolbar_menu_item_text_container"/>
   <public type="id" name="car_ui_toolbar_menu_item_text_with_icon"/>
   <public type="id" name="car_ui_toolbar_menu_items_container"/>
   <public type="id" name="car_ui_toolbar_nav_icon"/>
@@ -244,8 +249,6 @@
   <public type="id" name="car_ui_toolbar_title_logo"/>
   <public type="id" name="car_ui_toolbar_title_logo_container"/>
   <public type="id" name="car_ui_toolbar_top_guideline"/>
-  <public type="id" name="check_box_container"/>
-  <public type="id" name="checkbox"/>
   <public type="id" name="checkbox_widget"/>
   <public type="id" name="container"/>
   <public type="id" name="content_icon"/>
@@ -253,22 +256,31 @@
   <public type="id" name="icon_container"/>
   <public type="id" name="list"/>
   <public type="id" name="nested_recycler_view_layout"/>
+  <public type="id" name="radio_button"/>
   <public type="id" name="radio_button_widget"/>
   <public type="id" name="recycler_view"/>
   <public type="id" name="reduced_touch_interceptor"/>
   <public type="id" name="search"/>
+  <public type="id" name="seek_bar"/>
+  <public type="id" name="seek_bar_text_left"/>
+  <public type="id" name="seek_bar_text_right"/>
+  <public type="id" name="seek_bar_text_top"/>
   <public type="id" name="seekbar"/>
   <public type="id" name="seekbar_value"/>
   <public type="id" name="spinner"/>
   <public type="id" name="supplemental_icon"/>
   <public type="id" name="switch_widget"/>
-  <public type="id" name="text"/>
+  <public type="id" name="text_container"/>
   <public type="id" name="textbox"/>
   <public type="id" name="title"/>
   <public type="id" name="title_template"/>
   <public type="id" name="toolbar"/>
   <public type="id" name="touch_interceptor"/>
   <public type="integer" name="car_ui_default_max_string_length"/>
+  <public type="integer" name="car_ui_focus_area_history_cache_type"/>
+  <public type="integer" name="car_ui_focus_area_history_expiration_period_ms"/>
+  <public type="integer" name="car_ui_focus_history_cache_type"/>
+  <public type="integer" name="car_ui_focus_history_expiration_period_ms"/>
   <public type="integer" name="car_ui_scrollbar_longpress_initial_delay"/>
   <public type="integer" name="car_ui_scrollbar_longpress_repeat_interval"/>
   <public type="layout" name="car_ui_alert_dialog_edit_text"/>
@@ -277,11 +289,11 @@
   <public type="layout" name="car_ui_base_layout"/>
   <public type="layout" name="car_ui_base_layout_toolbar"/>
   <public type="layout" name="car_ui_base_layout_toolbar_legacy"/>
-  <public type="layout" name="car_ui_check_box_list_item"/>
   <public type="layout" name="car_ui_header_list_item"/>
   <public type="layout" name="car_ui_list_item"/>
   <public type="layout" name="car_ui_list_limiting_message"/>
   <public type="layout" name="car_ui_list_preference"/>
+  <public type="layout" name="car_ui_list_preference_with_toolbar"/>
   <public type="layout" name="car_ui_preference"/>
   <public type="layout" name="car_ui_preference_category"/>
   <public type="layout" name="car_ui_preference_chevron"/>
@@ -292,9 +304,11 @@
   <public type="layout" name="car_ui_preference_widget_checkbox"/>
   <public type="layout" name="car_ui_preference_widget_seekbar"/>
   <public type="layout" name="car_ui_preference_widget_switch"/>
+  <public type="layout" name="car_ui_radio_button_preference_widget"/>
   <public type="layout" name="car_ui_recycler_view"/>
   <public type="layout" name="car_ui_recycler_view_item"/>
   <public type="layout" name="car_ui_recyclerview_scrollbar"/>
+  <public type="layout" name="car_ui_seekbar_dialog"/>
   <public type="layout" name="car_ui_toolbar"/>
   <public type="layout" name="car_ui_toolbar_menu_item"/>
   <public type="layout" name="car_ui_toolbar_search_view"/>
@@ -303,12 +317,12 @@
   <public type="layout" name="car_ui_toolbar_tab_item_layout"/>
   <public type="layout" name="car_ui_toolbar_tab_item_layout_flexible"/>
   <public type="layout" name="car_ui_toolbar_two_row"/>
+  <public type="layout" name="car_ui_two_action_preference"/>
   <public type="string" name="car_ui_alert_dialog_default_button"/>
   <public type="string" name="car_ui_dialog_preference_negative"/>
   <public type="string" name="car_ui_dialog_preference_positive"/>
   <public type="string" name="car_ui_ellipsis"/>
-  <public type="string" name="car_ui_list_item_header_font_family"/>
-  <public type="string" name="car_ui_preference_category_title_font_family"/>
+  <public type="string" name="car_ui_installer_process_name"/>
   <public type="string" name="car_ui_preference_switch_off"/>
   <public type="string" name="car_ui_preference_switch_on"/>
   <public type="string" name="car_ui_restricted_while_driving"/>
@@ -328,6 +342,12 @@
   <public type="style" name="Preference.CarUi.CheckBoxPreference"/>
   <public type="style" name="Preference.CarUi.DialogPreference"/>
   <public type="style" name="Preference.CarUi.DialogPreference.EditTextPreference"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.LeftText"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.RightText"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.Seekbar"/>
+  <public type="style" name="Preference.CarUi.DialogSeekBarPreference.TopText"/>
+  <public type="style" name="Preference.CarUi.Divider"/>
   <public type="style" name="Preference.CarUi.DropDown"/>
   <public type="style" name="Preference.CarUi.Icon"/>
   <public type="style" name="Preference.CarUi.Information"/>
diff --git a/car-ui-lib/tests/baselayouttests/src/com/android/car/ui/core/testsupport/CarUiInstallerRobolectric.java b/car-ui-lib/tests/baselayouttests/src/com/android/car/ui/core/testsupport/CarUiInstallerRobolectric.java
new file mode 100644
index 0000000..652819f
--- /dev/null
+++ b/car-ui-lib/tests/baselayouttests/src/com/android/car/ui/core/testsupport/CarUiInstallerRobolectric.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 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.car.ui.core.testsupport;
+
+import android.content.pm.ProviderInfo;
+
+import com.android.car.ui.core.CarUiInstaller;
+
+import org.robolectric.Robolectric;
+
+/**
+ * A helper class that can be used to install the base layout into robolectric test activities.
+ */
+public class CarUiInstallerRobolectric {
+
+    public static void install() {
+        ProviderInfo info = new ProviderInfo();
+        Class carUiInstallerClass = CarUiInstaller.class;
+        info.authority = carUiInstallerClass.getName();
+        Robolectric.buildContentProvider(carUiInstallerClass).create(info);
+    }
+}
diff --git a/car-ui-lib/tests/paintbooth/Android.mk b/car-ui-lib/tests/paintbooth/Android.mk
deleted file mode 100644
index fca93f1..0000000
--- a/car-ui-lib/tests/paintbooth/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# 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.
-#
-
-ifneq ($(TARGET_BUILD_PDK), true)
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := PaintBooth
-
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-        car-ui-lib
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
-    android.car.userlib \
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
-
-endif
diff --git a/car-ui-lib/tests/paintbooth/AndroidManifest-gradle.xml b/car-ui-lib/tests/paintbooth/AndroidManifest-gradle.xml
deleted file mode 100644
index 84ed351..0000000
--- a/car-ui-lib/tests/paintbooth/AndroidManifest-gradle.xml
+++ /dev/null
@@ -1,85 +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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.car.ui.paintbooth">
-
-  <application
-      android:supportsRtl="true"
-      android:icon="@drawable/ic_launcher"
-      android:label="@string/app_name"
-      android:theme="@style/Theme.CarUi.WithToolbar">
-    <activity
-        android:name=".MainActivity"
-        android:exported="true">
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN"/>
-        <category android:name="android.intent.category.LAUNCHER"/>
-      </intent-filter>
-    </activity>
-
-    <activity
-        android:name=".dialogs.DialogsActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".caruirecyclerview.CarUiRecyclerViewActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".caruirecyclerview.GridCarUiRecyclerViewActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".preferences.PreferenceActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".toolbar.ToolbarActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity">
-      <meta-data android:name="distractionOptimized" android:value="true"/>
-    </activity>
-    <activity
-        android:name=".toolbar.OldToolbarActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"
-        android:theme="@style/Theme.CarUi">
-      <meta-data android:name="distractionOptimized" android:value="true"/>
-    </activity>
-    <activity
-        android:name=".overlays.OverlayActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity">
-      <meta-data android:name="distractionOptimized" android:value="true"/>
-    </activity>
-    <activity
-        android:name=".widgets.WidgetActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".caruirecyclerview.CarUiListItemActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-
-    <!-- Remove this on R, it's to workaround a bug in the Qt manifest merger -->
-    <provider
-        android:name="com.android.car.ui.core.CarUiInstaller"
-        android:authorities="${applicationId}.CarUiInstaller"
-        android:exported="false"/>
-  </application>
-</manifest>
diff --git a/car-ui-lib/tests/paintbooth/AndroidManifest.xml b/car-ui-lib/tests/paintbooth/AndroidManifest.xml
deleted file mode 100644
index b8dd1ca..0000000
--- a/car-ui-lib/tests/paintbooth/AndroidManifest.xml
+++ /dev/null
@@ -1,106 +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.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.car.ui.paintbooth">
-
-  <uses-sdk
-      android:minSdkVersion="28"
-      android:targetSdkVersion="28"/>
-
-  <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
-  <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
-  <uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
-  <uses-permission android:name="android.permission.MANAGE_USERS"/>
-  <!-- Required to use the TYPE_DISPLAY_OVERLAY layout param for the current activity overlay -->
-  <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
-  <!-- Required for listening to android task stack changes -->
-  <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
-  <uses-permission android:name="android.permission.REAL_GET_TASKS" />
-  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
-  <!-- Required for using TYPE_APPLICATION_OVERLAY to display overlays -->
-  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
-  <!-- Required to test permission dialogs -->
-  <uses-permission android:name="android.permission.CAMERA"/>
-  <uses-permission android:name="android.permission.READ_CONTACTS"/>
-  <uses-permission android:name="android.permission.SEND_SMS"/>
-
-  <application
-      android:supportsRtl="true"
-      android:icon="@drawable/ic_launcher"
-      android:label="@string/app_name"
-      android:theme="@style/Theme.CarUi.WithToolbar">
-    <activity
-        android:name=".MainActivity"
-        android:exported="true">
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN"/>
-        <category android:name="android.intent.category.LAUNCHER"/>
-      </intent-filter>
-    </activity>
-
-    <activity
-        android:name=".dialogs.DialogsActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".caruirecyclerview.CarUiRecyclerViewActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".caruirecyclerview.GridCarUiRecyclerViewActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".preferences.PreferenceActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".toolbar.ToolbarActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity">
-      <meta-data android:name="distractionOptimized" android:value="true"/>
-    </activity>
-    <activity
-        android:name=".toolbar.OldToolbarActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"
-        android:theme="@style/Theme.CarUi">
-      <meta-data android:name="distractionOptimized" android:value="true"/>
-    </activity>
-    <activity
-        android:name=".overlays.OverlayActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity">
-      <meta-data android:name="distractionOptimized" android:value="true"/>
-    </activity>
-    <activity
-        android:name=".widgets.WidgetActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-    <activity
-        android:name=".caruirecyclerview.CarUiListItemActivity"
-        android:exported="false"
-        android:parentActivityName=".MainActivity"/>
-
-    <!-- Remove this on R, it's to workaround a bug in the Qt manifest merger -->
-    <provider
-        android:name="com.android.car.ui.core.CarUiInstaller"
-        android:authorities="${applicationId}.CarUiInstaller"
-        android:exported="false"/>
-  </application>
-</manifest>
diff --git a/car-ui-lib/tests/paintbooth/build.gradle b/car-ui-lib/tests/paintbooth/build.gradle
deleted file mode 100644
index a7265cd..0000000
--- a/car-ui-lib/tests/paintbooth/build.gradle
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-apply plugin: 'com.android.application'
-
-android {
-    compileSdkVersion 29
-    defaultConfig {
-        applicationId "com.android.car.ui.paintbooth"
-        minSdkVersion 28
-        targetSdkVersion 29
-        versionCode 1
-        versionName "1.0"
-    }
-
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-
-    sourceSets {
-        main {
-            manifest.srcFile 'AndroidManifest-gradle.xml'
-            java {
-                srcDirs = ['src']
-                filter.excludes = ["com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java"]
-            }
-            res.srcDirs = ['res']
-        }
-    }
-}
-
-dependencies {
-    implementation project(':')
-    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0'
-    api 'androidx.annotation:annotation:1.1.0'
-    api 'androidx.constraintlayout:constraintlayout:1.1.3'
-    api 'androidx.recyclerview:recyclerview:1.0.0'
-}
diff --git a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity.xml b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity.xml
deleted file mode 100644
index afc6bc8..0000000
--- a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity.xml
+++ /dev/null
@@ -1,23 +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.
-  -->
-<com.android.car.ui.recyclerview.CarUiRecyclerView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/list"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipToPadding="false"
-    android:background="@drawable/car_ui_activity_background"/>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml
deleted file mode 100644
index 266e9b8..0000000
--- a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_activity_with_old_toolbar.xml
+++ /dev/null
@@ -1,42 +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.
-  -->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@drawable/car_ui_activity_background">
-
-    <com.android.car.ui.recyclerview.CarUiRecyclerView
-        android:id="@+id/list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clipToPadding="false"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-    <com.android.car.ui.toolbar.Toolbar
-        android:id="@+id/toolbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent"/>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_list_item.xml b/car-ui-lib/tests/paintbooth/res/layout/car_ui_recycler_view_list_item.xml
deleted file mode 100644
index a9d45ad..0000000
--- a/car-ui-lib/tests/paintbooth/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>
\ No newline at end of file
diff --git a/car-ui-lib/tests/paintbooth/res/layout/grid_car_ui_recycler_view_activity.xml b/car-ui-lib/tests/paintbooth/res/layout/grid_car_ui_recycler_view_activity.xml
deleted file mode 100644
index 1a019dc..0000000
--- a/car-ui-lib/tests/paintbooth/res/layout/grid_car_ui_recycler_view_activity.xml
+++ /dev/null
@@ -1,24 +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.
-  -->
-<com.android.car.ui.recyclerview.CarUiRecyclerView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/list"
-    app:numOfColumns="4"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@drawable/car_ui_activity_background" />
\ No newline at end of file
diff --git a/car-ui-lib/tests/paintbooth/res/values/strings.xml b/car-ui-lib/tests/paintbooth/res/values/strings.xml
deleted file mode 100644
index 470b416..0000000
--- a/car-ui-lib/tests/paintbooth/res/values/strings.xml
+++ /dev/null
@@ -1,270 +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.
-  -->
-<resources>
-  <!-- Application name [CHAR LIMIT=30] -->
-  <string name="app_name" translatable="false">Paint Booth (Gerrit)</string>
-
-  <!-- Strings for Preference Samples -->
-  <eat-comment/>
-
-  <!-- Preferences page title [CHAR_LIMIT=13] -->
-  <string name="preferences_screen_title">Settings</string>
-
-  <!--This section is for basic attributes -->
-  <eat-comment/>
-  <!-- Category title for basic preferences [CHAR_LIMIT=26]-->
-  <string name="basic_preferences">Basic attributes</string>
-  <!-- Title of a basic preference [CHAR_LIMIT=10]-->
-  <string name="title_basic_preference">Preference</string>
-  <!-- Summary of a basic preference [CHAR_LIMIT=71]-->
-  <string name="summary_basic_preference">Simple preference with no special attributes</string>
-
-  <!-- Title of a preference with stylized text [CHAR_LIMIT=71]-->
-  <string name="title_stylish_preference"><b>Very</b> <i>stylish</i> <u>preference</u></string>
-  <!-- Summary of a preference with stylized text [CHAR_LIMIT=150]-->
-  <string name="summary_stylish_preference">Define style tags such as &lt;b&gt; in a string resource to customize a preference\'s text</string>
-
-  <!-- Title of an icon preference [CHAR_LIMIT=25]-->
-  <string name="title_icon_preference">Icon preference</string>
-  <!-- Summary of an icon preference [CHAR_LIMIT=103]-->
-  <string name="summary_icon_preference">Define a drawable to display it at the start of the preference</string>
-
-  <!-- Title of a single line title preference [CHAR_LIMIT=165]-->
-  <string name="title_single_line_title_preference">Single line title preference - no matter how long the title is it will never wrap to multiple lines</string>
-  <!-- Summary of a single line title preference [CHAR_LIMIT=108]-->
-  <string name="summary_single_line_title_preference">This title will be ellipsized instead of wrapping to another line</string>
-
-  <!-- Title of a single line title preference without summary [CHAR_LIMIT=28]-->
-  <string name="title_single_line_no_summary">Single line preference - no summary</string>
-
-  <!--This section is for preferences that contain a widget in their layout -->
-  <eat-comment/>
-  <!-- Category title for preferences with widgets [CHAR_LIMIT=12]-->
-  <string name="widgets">Widgets</string>
-
-  <!-- Title of a checkbox preference [CHAR_LIMIT=31]-->
-  <string name="title_checkbox_preference">Checkbox preference</string>
-  <!-- Summary of a checkbox preference [CHAR_LIMIT=78]-->
-  <string name="summary_checkbox_preference">Tap anywhere in this preference to toggle state</string>
-
-  <!-- Title of a switch preference [CHAR_LIMIT=28]-->
-  <string name="title_switch_preference">Switch preference</string>
-  <!-- Summary of a switch preference [CHAR_LIMIT=78]-->
-  <string name="summary_switch_preference">Tap anywhere in this preference to toggle state</string>
-
-  <!-- Title of a dropdown preference [CHAR_LIMIT=31]-->
-  <string name="title_dropdown_preference">Dropdown preference</string>
-
-  <!-- Title of a seekbar preference [CHAR_LIMIT=30]-->
-  <string name="title_seekbar_preference">Seekbar preference</string>
-
-  <!--This section is for preferences that launch a dialog to edit the preference -->
-  <eat-comment/>
-  <!-- Category title for preferences which launch dialogs [CHAR_LIMIT=12]-->
-  <string name="dialogs">Dialogs</string>
-
-  <!-- Title of an edittext preference [CHAR_LIMIT=32]-->
-  <string name="title_edittext_preference">EditText preference</string>
-  <!-- Title of the dialog for an edittext preference [CHAR_LIMIT=43]-->
-  <string name="dialog_title_edittext_preference">This title can be changed!</string>
-
-  <!-- Title of a list preference [CHAR_LIMIT=25]-->
-  <string name="title_list_preference">List preference</string>
-  <!-- Title of the dialog for a list preference [CHAR_LIMIT=30]-->
-  <string name="dialog_title_list_preference">Choose one option!</string>
-
-  <!-- Title of a multi-select list preference [CHAR_LIMIT=46]-->
-  <string name="title_multi_list_preference">Multi-select list preference</string>
-  <!-- Summary of a multi-select list preference [CHAR_LIMIT=71]-->
-  <string name="summary_multi_list_preference">Shows a dialog with multiple choice options</string>
-  <!-- Title of the dialog for a multi-select list preference [CHAR_LIMIT=33]-->
-  <string name="dialog_title_multi_list_preference">Choose some options!</string>
-
-  <!--This section is for advanced attributes-->
-  <eat-comment/>
-  <!-- Category title for preferences with advanced attributes [CHAR_LIMIT=32]-->
-  <string name="advanced_attributes">Advanced attributes</string>
-
-  <!-- Title of an expandable preference [CHAR_LIMIT=45]-->
-  <string name="title_expandable_preference">Expandable preference group</string>
-  <!-- Summary of an expandable preference [CHAR_LIMIT=131]-->
-  <string name="summary_expandable_preference">This group shows one item and collapses the rest into the advanced button below</string>
-
-  <!-- Title of a preference which launches an intent [CHAR_LIMIT=28]-->
-  <string name="title_intent_preference">Intent preference</string>
-  <!-- Summary of a preference which launches an intent [CHAR_LIMIT=51]-->
-  <string name="summary_intent_preference">Launches an intent when pressed</string>
-
-  <!-- Title of a parent preference [CHAR_LIMIT=28]-->
-  <string name="title_parent_preference">Parent preference</string>
-  <!-- Summary of a parent preference [CHAR_LIMIT=130]-->
-  <string name="summary_parent_preference">Toggling this preference will change the enabled state of the preference below</string>
-
-  <!-- Title of a child preference [CHAR_LIMIT=26]-->
-  <string name="title_child_preference">Child preference</string>
-  <!-- Summary of a child preference [CHAR_LIMIT=123]-->
-  <string name="summary_child_preference">The enabled state of this preference is controlled by the preference above</string>
-
-  <!-- Title of a switch preference with variable summaries [CHAR_LIMIT=45]-->
-  <string name="title_toggle_summary_preference">Variable summary preference</string>
-  <!-- Summary of a variable summary preference when the preference is on [CHAR_LIMIT=118]-->
-  <string name="summary_on_toggle_summary_preference">On! :) - the summary of this preference changes depending on its state</string>
-  <!-- Summary of a variable summary preference when the preference is off [CHAR_LIMIT=118]-->
-  <string name="summary_off_toggle_summary_preference">Off! :( - the summary of this preference changes depending on its state</string>
-
-  <!-- Title of a copyable preference [CHAR_LIMIT=31]-->
-  <string name="title_copyable_preference">Copyable preference</string>
-  <!-- Summary of a copyable preference [CHAR_LIMIT=81]-->
-  <string name="summary_copyable_preference">Long press on this preference to copy its summary</string>
-
-  <!-- Title of a Advanced preference [CHAR_LIMIT=13]-->
-  <string name="advanced_preference">Advanced</string>
-
-  <!-- Title of a Intent preference [CHAR_LIMIT=28]-->
-  <string name="intent_preference">Intent preference</string>
-
-  <!--This section is for toolbar attributes -->
-  <eat-comment/>
-
-  <!-- Text for change title button [CHAR_LIMIT=20]-->
-  <string name="toolbar_change_title">Change title</string>
-
-  <!-- Text for set xml button [CHAR_LIMIT=45]-->
-  <string name="toolbar_set_xml_resource">MenuItem: Set to XML source</string>
-
-  <!-- Text for add icon button [CHAR_LIMIT=30]-->
-  <string name="toolbar_add_icon">MenuItem: Add Icon</string>
-
-  <!-- Text for add untined icon button [CHAR_LIMIT=45]-->
-  <string name="toolbar_add_untined_icon">MenuItem: Add untinted icon</string>
-
-  <!-- Text for add overflow button [CHAR_LIMIT=36]-->
-  <string name="toolbar_add_overflow">MenuItem: Add Overflow</string>
-
-  <!-- Text for add switch button [CHAR_LIMIT=33]-->
-  <string name="toolbar_add_switch">MenuItem: Add Switch</string>
-
-  <!-- Text for add text button [CHAR_LIMIT=30]-->
-  <string name="toolbar_add_text">MenuItem: Add text</string>
-
-  <!-- Text for add icon text button [CHAR_LIMIT=45]-->
-  <string name="toolbar_add_icon_text">MenuItem: Add icon and text</string>
-
-  <!-- Text for add untined icon and text button [CHAR_LIMIT=60]-->
-  <string name="toolbar_add_untinted_icon_and_text">MenuItem: Add untinted icon and text</string>
-
-  <!-- Text for add activatable button [CHAR_LIMIT=41]-->
-  <string name="toolbar_add_activatable">MenuItem: Add activatable</string>
-
-  <!-- Text for add activatable button [CHAR_LIMIT=36]-->
-  <string name="toolbar_add_morphing">MenuItem: Add morphing</string>
-
-  <!-- Text for toggle visibility button [CHAR_LIMIT=45]-->
-  <string name="toolbar_toggle_visibility">MenuItem: Toggle Visibility</string>
-
-  <!-- Text for toggle enable button [CHAR_LIMIT=40]-->
-  <string name="toolbar_toggle_enable">MenuItem: Toggle Enabled</string>
-
-  <!-- Text for toggle enable button [CHAR_LIMIT=49]-->
-  <string name="toolbar_toggle_perform_click">MenuItem: Call PerformClick()</string>
-
-  <!-- Text for toggle icon button [CHAR_LIMIT=35]-->
-  <string name="toolbar_toggle_icon">MenuItem: Toggle Icon</string>
-
-  <!-- Text for toggle show while search button [CHAR_LIMIT=61]-->
-  <string name="toolbar_toggle_show_while_search">MenuItem: Toggle show while searching</string>
-
-  <!-- Text for cycle nav button mode button [CHAR_LIMIT=35]-->
-  <string name="toolbar_cycle_nav_button">Cycle nav button mode</string>
-
-  <!-- Text for toggle logo button [CHAR_LIMIT=19]-->
-  <string name="toolbar_toggle_logo">Toggle logo</string>
-
-  <!-- Text for cycle state button [CHAR_LIMIT=20]-->
-  <string name="toolbar_cycle_state">Cycle state</string>
-
-  <!-- Text for toggle search hint button [CHAR_LIMIT=30]-->
-  <string name="toolbar_toggle_search_hint">Toggle search hint</string>
-
-  <!-- Text for toggle background button [CHAR_LIMIT=30]-->
-  <string name="toolbar_toggle_background">Toggle background</string>
-
-  <!-- Text for add tab button [CHAR_LIMIT=12]-->
-  <string name="toolbar_add_tab">Add tab</string>
-
-  <!-- Text for add tab with custom text button [CHAR_LIMIT=40]-->
-  <string name="toolbar_add_tab_with_custom_text">Add tab with custom text</string>
-
-  <!-- Text for showing tabs in subpages [CHAR_LIMIT=50]-->
-  <string name="toolbar_show_tabs_in_subpage">Toggle showing tabs in subpages</string>
-
-  <!-- Text for toggle search icon button [CHAR_LIMIT=30]-->
-  <string name="toolbar_toggle_search_icon">Toggle search icon</string>
-
-  <!--This section is for dialog attributes -->
-  <eat-comment/>
-
-  <!-- Text for show dialog button [CHAR_LIMIT=18]-->
-  <string name="dialog_show_dialog">Show Dialog</string>
-
-  <!-- Text for show dialog button [CHAR_LIMIT=30]-->
-  <string name="dialog_show_dialog_icon">Show Dialog with icon</string>
-
-  <!-- Text for Dialog with edit text box button [CHAR_LIMIT=50]-->
-  <string name="dialog_show_dialog_edit">Show Dialog with edit text box</string>
-
-  <!-- Text for show Dialog with only positive button button [CHAR_LIMIT=61]-->
-  <string name="dialog_show_dialog_only_positive">Show Dialog with only positive button</string>
-
-  <!-- Text for show Dialog With no button provided button [CHAR_LIMIT=60]-->
-  <string name="dialog_show_dialog_no_button">Show Dialog With no button provided</string>
-
-  <!-- Text for show Dialog With Checkbox button [CHAR_LIMIT=41]-->
-  <string name="dialog_show_dialog_checkbox">Show Dialog With Checkbox</string>
-
-  <!-- Text for show Dialog without title button [CHAR_LIMIT=41]-->
-  <string name="dialog_show_dialog_no_title">Show Dialog without title</string>
-
-  <!-- Text for show Toast button [CHAR_LIMIT=16]-->
-  <string name="dialog_show_toast">Show Toast</string>
-
-  <!-- Button that shows a dialog with a subtitle [CHAR_LIMIT=50]-->
-  <string name="dialog_show_subtitle">Show Dialog with title and subtitle</string>
-
-  <!-- Button that shows a dialog with a subtitle and icon [CHAR_LIMIT=50]-->
-  <string name="dialog_show_subtitle_and_icon">Show Dialog with title, subtitle, and icon</string>
-
-  <!-- Button that shows a dialog with a long title, subtitle and icon [CHAR_LIMIT=500]-->
-  <string name="dialog_show_long_subtitle_and_icon">Show Dialog with a long title, subtitle, and icon</string>
-
-  <!-- Text to show Dialog with single choice items-->
-  <string name="dialog_show_single_choice">Show with single choice items</string>
-
-  <!-- Text to show a permission Dialog-->
-  <string name="dialog_show_permission_dialog">Show permission dialog</string>
-
-  <!-- Text to show a permission Dialog for multiple permissions-->
-  <string name="dialog_show_multi_permission_dialog">Show multiple permissions dialog</string>
-
-  <!--This section is for widget attributes -->
-  <eat-comment/>
-  <!-- Text for checkbox [CHAR_LIMIT=16]-->
-  <string name="widget_checkbox_text">I\'m a check box</string>
-  <!-- Text for switch [CHAR_LIMIT=25]-->
-  <string name="widget_switch_text">I\'m a switch</string>
-  
-</resources>
diff --git a/car-ui-lib/tests/paintbooth/res/xml/preference_overlays.xml b/car-ui-lib/tests/paintbooth/res/xml/preference_overlays.xml
deleted file mode 100644
index 27ef049..0000000
--- a/car-ui-lib/tests/paintbooth/res/xml/preference_overlays.xml
+++ /dev/null
@@ -1,20 +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.
-  -->
-<PreferenceScreen
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    app:title="Overlays">
-</PreferenceScreen>
\ No newline at end of file
diff --git a/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml b/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
deleted file mode 100644
index e483435..0000000
--- a/car-ui-lib/tests/paintbooth/res/xml/preference_samples.xml
+++ /dev/null
@@ -1,163 +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.
-  -->
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    app:title="@string/preferences_screen_title">
-
-    <PreferenceCategory
-        android:title="@string/basic_preferences">
-
-        <Preference
-            android:key="preference"
-            android:summary="@string/summary_basic_preference"
-            android:title="@string/title_basic_preference"/>
-
-        <Preference
-            android:key="preference_disabled_without_ripple"
-            android:summary="Without ripple"
-            android:title="@string/title_basic_preference"/>
-
-        <Preference
-            android:key="preference_disabled_with_ripple"
-            android:summary="With ripple"
-            android:title="@string/title_basic_preference"/>
-
-        <Preference
-            android:key="stylized"
-            android:dependency="preference"
-            android:summary="@string/summary_stylish_preference"
-            android:title="@string/title_stylish_preference"/>
-
-        <Preference
-            android:icon="@drawable/ic_settings_wifi"
-            android:key="icon"
-            android:summary="@string/summary_icon_preference"
-            android:title="@string/title_icon_preference"/>
-
-        <Preference
-            android:key="single_line_title"
-            android:summary="@string/summary_single_line_title_preference"
-            android:title="@string/title_single_line_title_preference"
-            app:singleLineTitle="true"/>
-
-        <Preference
-            android:key="single_line_no_summary"
-            android:title="@string/title_single_line_no_summary"
-            app:singleLineTitle="true"/>
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:title="@string/widgets">
-
-        <CheckBoxPreference
-            android:key="checkbox"
-            android:summary="@string/summary_checkbox_preference"
-            android:title="@string/title_checkbox_preference"/>
-
-        <DropDownPreference
-            android:entries="@array/entries"
-            android:entryValues="@array/entry_values"
-            android:key="dropdown"
-            android:title="@string/title_dropdown_preference"
-            app:useSimpleSummaryProvider="true"/>
-
-        <SeekBarPreference
-            android:defaultValue="5"
-            android:key="seekbar"
-            android:max="10"
-            android:title="@string/title_seekbar_preference"/>
-
-        <SwitchPreference
-            android:key="switch"
-            android:summary="@string/summary_switch_preference"
-            android:title="@string/title_switch_preference"/>
-
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:title="@string/dialogs">
-
-        <EditTextPreference
-            android:dialogTitle="@string/dialog_title_edittext_preference"
-            android:key="edittext"
-            android:title="@string/title_edittext_preference"
-            app:useSimpleSummaryProvider="true"/>
-
-        <ListPreference
-            android:dialogTitle="@string/dialog_title_list_preference"
-            android:entries="@array/entries"
-            android:entryValues="@array/entry_values"
-            android:key="list"
-            android:title="@string/title_list_preference"
-            app:useSimpleSummaryProvider="true"/>
-
-        <MultiSelectListPreference
-            android:dialogTitle="@string/dialog_title_multi_list_preference"
-            android:entries="@array/entries"
-            android:entryValues="@array/entry_values"
-            android:key="multi_select_list"
-            android:summary="@string/summary_multi_list_preference"
-            android:title="@string/title_multi_list_preference"/>
-
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:key="@string/advanced_preference"
-        android:title="@string/advanced_attributes"
-        app:initialExpandedChildrenCount="1">
-
-        <Preference
-            android:key="expandable"
-            android:summary="@string/summary_expandable_preference"
-            android:title="@string/title_expandable_preference"/>
-
-        <Preference
-            android:summary="@string/summary_intent_preference"
-            android:title="@string/title_intent_preference">
-
-            <intent android:action="android.intent.action.VIEW"
-                    android:data="http://www.android.com"/>
-
-        </Preference>
-
-        <Preference
-            android:key="copyable"
-            android:selectable="false"
-            android:summary="@string/summary_copyable_preference"
-            android:title="@string/title_copyable_preference"
-            app:enableCopying="true"/>
-
-        <SwitchPreference
-            android:dependency="parent"
-            android:key="child"
-            android:summary="@string/summary_child_preference"
-            android:title="@string/title_child_preference"/>
-
-        <SwitchPreference
-            android:key="toggle_summary"
-            android:summaryOff="@string/summary_off_toggle_summary_preference"
-            android:summaryOn="@string/summary_on_toggle_summary_preference"
-            android:title="@string/title_toggle_summary_preference"/>
-
-        <SwitchPreference
-            android:key="parent"
-            android:summary="@string/summary_parent_preference"
-            android:title="@string/title_parent_preference"/>
-    </PreferenceCategory>
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/MainActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/MainActivity.java
deleted file mode 100644
index e4a0a3d..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/MainActivity.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.core.CarUi;
-import com.android.car.ui.paintbooth.caruirecyclerview.CarUiListItemActivity;
-import com.android.car.ui.paintbooth.caruirecyclerview.CarUiRecyclerViewActivity;
-import com.android.car.ui.paintbooth.caruirecyclerview.GridCarUiRecyclerViewActivity;
-import com.android.car.ui.paintbooth.dialogs.DialogsActivity;
-import com.android.car.ui.paintbooth.overlays.OverlayActivity;
-import com.android.car.ui.paintbooth.preferences.PreferenceActivity;
-import com.android.car.ui.paintbooth.toolbar.OldToolbarActivity;
-import com.android.car.ui.paintbooth.toolbar.ToolbarActivity;
-import com.android.car.ui.paintbooth.widgets.WidgetActivity;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.ToolbarController;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Paint booth app
- */
-public class MainActivity extends Activity implements InsetsChangedListener {
-
-    /**
-     * List of all sample activities.
-     */
-    private final List<Pair<String, Class<? extends Activity>>> mActivities = Arrays.asList(
-            Pair.create("Dialogs sample", DialogsActivity.class),
-            Pair.create("List sample", CarUiRecyclerViewActivity.class),
-            Pair.create("Grid sample", GridCarUiRecyclerViewActivity.class),
-            Pair.create("Preferences sample", PreferenceActivity.class),
-            Pair.create("Overlays", OverlayActivity.class),
-            Pair.create("Toolbar sample", ToolbarActivity.class),
-            Pair.create("Old Toolbar sample", OldToolbarActivity.class),
-            Pair.create("Widget sample", WidgetActivity.class),
-            Pair.create("ListItem sample", CarUiListItemActivity.class)
-    );
-
-    private class ViewHolder extends RecyclerView.ViewHolder {
-        private Button mButton;
-
-        ViewHolder(@NonNull View itemView) {
-            super(itemView);
-            mButton = itemView.findViewById(R.id.button);
-        }
-
-        void update(String title, Class<? extends Activity> activityClass) {
-            mButton.setText(title);
-            mButton.setOnClickListener(e -> {
-                Intent intent = new Intent(mButton.getContext(), activityClass);
-                startActivity(intent);
-            });
-        }
-    }
-
-    private final RecyclerView.Adapter<ViewHolder> mAdapter =
-            new RecyclerView.Adapter<ViewHolder>() {
-        @NonNull
-        @Override
-        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
-            View item = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent,
-                    false);
-            return new ViewHolder(item);
-        }
-
-        @Override
-        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
-            Pair<String, Class<? extends Activity>> item = mActivities.get(position);
-            holder.update(item.first, item.second);
-        }
-
-        @Override
-        public int getItemCount() {
-            return mActivities.size();
-        }
-    };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.car_ui_recycler_view_activity);
-
-        ToolbarController toolbar = CarUi.requireToolbar(this);
-        toolbar.setLogo(R.drawable.ic_launcher);
-        toolbar.setTitle(getTitle());
-
-        CarUiRecyclerView prv = findViewById(R.id.list);
-        prv.setAdapter(mAdapter);
-
-        initLeakCanary();
-    }
-
-    private void initLeakCanary() {
-        // This sets LeakCanary to report errors after a single leak instead of 5, and to ask for
-        // permission to use storage, which it needs to work.
-        //
-        // Equivalent to this non-reflection code:
-        //
-        // Config config = LeakCanary.INSTANCE.getConfig();
-        // LeakCanary.INSTANCE.setConfig(config.copy(config.getDumpHeap(),
-        //     config.getDumpHeapWhenDebugging(),
-        //     1,
-        //     config.getReferenceMatchers(),
-        //     config.getObjectInspectors(),
-        //     config.getOnHeapAnalyzedListener(),
-        //     config.getMetatadaExtractor(),
-        //     config.getComputeRetainedHeapSize(),
-        //     config.getMaxStoredHeapDumps(),
-        //     true,
-        //     config.getUseExperimentalLeakFinders()));
-        try {
-            Class<?> canaryClass = Class.forName("leakcanary.LeakCanary");
-            try {
-                Class<?> onHeapAnalyzedListenerClass =
-                        Class.forName("leakcanary.OnHeapAnalyzedListener");
-                Class<?> metadataExtractorClass = Class.forName("shark.MetadataExtractor");
-                Method getConfig = canaryClass.getMethod("getConfig");
-                Class<?> configClass = getConfig.getReturnType();
-                Method setConfig = canaryClass.getMethod("setConfig", configClass);
-                Method copy = configClass.getMethod("copy", boolean.class, boolean.class,
-                        int.class, List.class, List.class, onHeapAnalyzedListenerClass,
-                        metadataExtractorClass, boolean.class, int.class, boolean.class,
-                        boolean.class);
-
-                Object canary = canaryClass.getField("INSTANCE").get(null);
-                Object currentConfig = getConfig.invoke(canary);
-
-                Boolean dumpHeap = (Boolean) configClass
-                        .getMethod("getDumpHeap").invoke(currentConfig);
-                Boolean dumpHeapWhenDebugging = (Boolean) configClass
-                        .getMethod("getDumpHeapWhenDebugging").invoke(currentConfig);
-                List<?> referenceMatchers = (List<?>) configClass
-                        .getMethod("getReferenceMatchers").invoke(currentConfig);
-                List<?> objectInspectors = (List<?>) configClass
-                        .getMethod("getObjectInspectors").invoke(currentConfig);
-                Object onHeapAnalyzedListener = configClass
-                        .getMethod("getOnHeapAnalyzedListener").invoke(currentConfig);
-                // Yes, LeakCanary misspelled metadata
-                Object metadataExtractor = configClass
-                        .getMethod("getMetatadaExtractor").invoke(currentConfig);
-                Boolean computeRetainedHeapSize = (Boolean) configClass
-                        .getMethod("getComputeRetainedHeapSize").invoke(currentConfig);
-                Integer maxStoredHeapDumps = (Integer) configClass
-                        .getMethod("getMaxStoredHeapDumps").invoke(currentConfig);
-                Boolean useExperimentalLeakFinders = (Boolean) configClass
-                        .getMethod("getUseExperimentalLeakFinders").invoke(currentConfig);
-
-                setConfig.invoke(canary, copy.invoke(currentConfig,
-                        dumpHeap,
-                        dumpHeapWhenDebugging,
-                        1,
-                        referenceMatchers,
-                        objectInspectors,
-                        onHeapAnalyzedListener,
-                        metadataExtractor,
-                        computeRetainedHeapSize,
-                        maxStoredHeapDumps,
-                        true,
-                        useExperimentalLeakFinders));
-
-            } catch (ReflectiveOperationException e) {
-                Log.e("paintbooth", "Error initializing LeakCanary", e);
-                Toast.makeText(this, "Error initializing LeakCanary", Toast.LENGTH_LONG).show();
-            }
-        } catch (ClassNotFoundException e) {
-            // LeakCanary is not used in this build, do nothing.
-        }
-    }
-
-    @Override
-    public void onCarUiInsetsChanged(Insets insets) {
-        requireViewById(R.id.list)
-                .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        requireViewById(android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
-    }
-}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
deleted file mode 100644
index 927b3f4..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiListItemActivity.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth.caruirecyclerview;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.widget.Toast;
-
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.core.CarUi;
-import com.android.car.ui.paintbooth.R;
-import com.android.car.ui.recyclerview.CarUiContentListItem;
-import com.android.car.ui.recyclerview.CarUiHeaderListItem;
-import com.android.car.ui.recyclerview.CarUiListItem;
-import com.android.car.ui.recyclerview.CarUiListItemAdapter;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.toolbar.ToolbarController;
-
-import java.util.ArrayList;
-
-/**
- * Activity that shows {@link CarUiRecyclerView} with dummy {@link CarUiContentListItem} entries
- */
-public class CarUiListItemActivity extends Activity implements InsetsChangedListener {
-
-    private final ArrayList<CarUiListItem> mData = new ArrayList<>();
-    private CarUiListItemAdapter mAdapter;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.car_ui_recycler_view_activity);
-
-        ToolbarController toolbar = CarUi.requireToolbar(this);
-        toolbar.setTitle(getTitle());
-        toolbar.setState(Toolbar.State.SUBPAGE);
-
-        CarUiRecyclerView recyclerView = findViewById(R.id.list);
-        mAdapter = new CarUiListItemAdapter(generateDummyData());
-        recyclerView.setAdapter(mAdapter);
-    }
-
-    private ArrayList<CarUiListItem> generateDummyData() {
-        Context context = this;
-
-        CarUiHeaderListItem header = new CarUiHeaderListItem("First header");
-        mData.add(header);
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test title");
-        item.setBody("Test body");
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test title with no body");
-        mData.add(item);
-
-        header = new CarUiHeaderListItem("Random header", "with header body");
-        mData.add(header);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setBody("Test body with no title");
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test Title");
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test Title");
-        item.setBody("Test body text");
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test Title -- with content icon");
-        item.setPrimaryIconType(CarUiContentListItem.IconType.CONTENT);
-        item.setIcon(getDrawable(R.drawable.ic_sample_logo));
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test Title");
-        item.setBody("With avatar icon.");
-        item.setIcon(getDrawable(R.drawable.ic_sample_logo));
-        item.setPrimaryIconType(CarUiContentListItem.IconType.AVATAR);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test Title");
-        item.setBody("Displays toast on click");
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        item.setOnItemClickedListener(item1 -> {
-            Toast.makeText(context, "Item clicked", Toast.LENGTH_SHORT).show();
-        });
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        item.setTitle("Title -- Item with checkbox");
-        item.setBody("Will present toast on change of selection state.");
-        item.setOnCheckedChangeListener(
-                (listItem, isChecked) -> Toast.makeText(context,
-                        "Item checked state is: " + isChecked, Toast.LENGTH_SHORT).show());
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        item.setEnabled(false);
-        item.setTitle("Title -- Checkbox that is disabled");
-        item.setBody("Clicks should not have any affect");
-        item.setOnCheckedChangeListener(
-                (listItem, isChecked) -> Toast.makeText(context,
-                        "Item checked state is: " + isChecked, Toast.LENGTH_SHORT).show());
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        item.setBody("Body -- Item with switch  -- with click listener");
-        item.setOnItemClickedListener(item1 -> {
-            Toast.makeText(context, "Click on item with switch", Toast.LENGTH_SHORT).show();
-        });
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        item.setTitle("Title -- Item with checkbox");
-        item.setBody("Item is initially checked");
-        item.setChecked(true);
-        mData.add(item);
-
-        CarUiContentListItem radioItem1 = new CarUiContentListItem(
-                CarUiContentListItem.Action.RADIO_BUTTON);
-        CarUiContentListItem radioItem2 = new CarUiContentListItem(
-                CarUiContentListItem.Action.RADIO_BUTTON);
-
-        radioItem1.setTitle("Title -- Item with radio button");
-        radioItem1.setBody("Item is initially unchecked checked");
-        radioItem1.setChecked(false);
-        radioItem1.setOnCheckedChangeListener((listItem, isChecked) -> {
-            if (isChecked) {
-                radioItem2.setChecked(false);
-                mAdapter.notifyItemChanged(mData.indexOf(radioItem2));
-            }
-        });
-        mData.add(radioItem1);
-
-        radioItem2.setIcon(getDrawable(R.drawable.ic_launcher));
-        radioItem2.setTitle("Item is mutually exclusive with item above");
-        radioItem2.setChecked(true);
-        radioItem2.setOnCheckedChangeListener((listItem, isChecked) -> {
-            if (isChecked) {
-                radioItem1.setChecked(false);
-                mAdapter.notifyItemChanged(mData.indexOf(radioItem1));
-            }
-        });
-        mData.add(radioItem2);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        item.setTitle("Title");
-        item.setBody("Random body text -- with action divider");
-        item.setActionDividerVisible(true);
-        item.setSupplementalIcon(getDrawable(R.drawable.ic_launcher));
-        item.setChecked(true);
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
-        item.setIcon(getDrawable(R.drawable.ic_launcher));
-        item.setTitle("Null supplemental icon");
-        item.setChecked(true);
-        mData.add(item);
-
-        item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
-        item.setTitle("Supplemental icon with listener");
-        item.setSupplementalIcon(getDrawable(R.drawable.ic_launcher),
-                v -> Toast.makeText(context, "Clicked supplemental icon",
-                        Toast.LENGTH_SHORT).show());
-        item.setChecked(true);
-        mData.add(item);
-
-        return mData;
-    }
-
-    @Override
-    public void onCarUiInsetsChanged(Insets insets) {
-        requireViewById(R.id.list)
-                .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        requireViewById(android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
-    }
-}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java
deleted file mode 100644
index a3ac9c2..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/CarUiRecyclerViewActivity.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth.caruirecyclerview;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-import androidx.recyclerview.widget.LinearLayoutManager;
-
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.core.CarUi;
-import com.android.car.ui.paintbooth.R;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.toolbar.ToolbarController;
-
-import java.util.ArrayList;
-
-/**
- * Activity that shows CarUiRecyclerView example with dummy data.
- */
-public class CarUiRecyclerViewActivity extends Activity implements InsetsChangedListener {
-    private final ArrayList<String> mData = new ArrayList<>();
-    private final int mDataToGenerate = 100;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.car_ui_recycler_view_activity);
-
-        ToolbarController toolbar = CarUi.requireToolbar(this);
-        toolbar.setTitle(getTitle());
-        toolbar.setState(Toolbar.State.SUBPAGE);
-
-        CarUiRecyclerView recyclerView = findViewById(R.id.list);
-        recyclerView.setLayoutManager(new LinearLayoutManager(this));
-
-        RecyclerViewAdapter adapter = new RecyclerViewAdapter(generateDummyData());
-        recyclerView.setAdapter(adapter);
-    }
-
-    private ArrayList<String> generateDummyData() {
-        for (int i = 0; i <= mDataToGenerate; i++) {
-            mData.add("data" + i);
-        }
-        return mData;
-    }
-
-    @Override
-    public void onCarUiInsetsChanged(Insets insets) {
-        requireViewById(R.id.list)
-                .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        requireViewById(android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
-    }
-}
-
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java
deleted file mode 100644
index 7f16d41..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/GridCarUiRecyclerViewActivity.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth.caruirecyclerview;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-import androidx.recyclerview.widget.GridLayoutManager;
-
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.core.CarUi;
-import com.android.car.ui.paintbooth.R;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.toolbar.ToolbarController;
-
-import java.util.ArrayList;
-
-/** Activity that shows GridCarUiRecyclerView example with dummy data. */
-public class GridCarUiRecyclerViewActivity extends Activity implements
-        InsetsChangedListener {
-    private final ArrayList<String> mData = new ArrayList<>();
-    private final int mDataToGenerate = 200;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.grid_car_ui_recycler_view_activity);
-
-        ToolbarController toolbar = CarUi.requireToolbar(this);
-        toolbar.setTitle(getTitle());
-        toolbar.setState(Toolbar.State.SUBPAGE);
-
-        CarUiRecyclerView recyclerView = findViewById(R.id.list);
-        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
-
-        RecyclerViewAdapter adapter = new RecyclerViewAdapter(generateDummyData());
-        recyclerView.setAdapter(adapter);
-    }
-
-    private ArrayList<String> generateDummyData() {
-        for (int i = 1; i <= mDataToGenerate; i++) {
-            mData.add("data" + i);
-        }
-        return mData;
-    }
-
-    @Override
-    public void onCarUiInsetsChanged(Insets insets) {
-        requireViewById(R.id.list)
-                .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        requireViewById(android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
-    }
-}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java
deleted file mode 100644
index 652a7a8..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/caruirecyclerview/RecyclerViewAdapter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth.caruirecyclerview;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.paintbooth.R;
-
-import java.util.ArrayList;
-
-/**
- * Implementation of {@link RecyclerViewAdapter} that can be used with RecyclerViews.
- */
-public class RecyclerViewAdapter extends
-        RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
-
-    private ArrayList<String> mData;
-
-    RecyclerViewAdapter(ArrayList<String> data) {
-        this.mData = data;
-    }
-
-    @NonNull
-    @Override
-    public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
-        LayoutInflater inflator = LayoutInflater.from(parent.getContext());
-        View view = inflator.inflate(R.layout.car_ui_recycler_view_list_item, parent, false);
-        return new RecyclerViewHolder(view);
-    }
-
-    @Override
-    public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
-        String title = mData.get(position);
-        holder.mTextTitle.setText(title);
-    }
-
-    @Override
-    public int getItemCount() {
-        return mData.size();
-    }
-
-
-    /**
-     * Holds views for each element in the list.
-     */
-    public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
-        TextView mTextTitle;
-
-        RecyclerViewHolder(@NonNull View itemView) {
-            super(itemView);
-            mTextTitle = itemView.findViewById(R.id.textTitle);
-        }
-    }
-}
-
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java
deleted file mode 100644
index c9760ec..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/dialogs/DialogsActivity.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth.dialogs;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-
-import com.android.car.ui.AlertDialogBuilder;
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.core.CarUi;
-import com.android.car.ui.paintbooth.R;
-import com.android.car.ui.recyclerview.CarUiRadioButtonListItem;
-import com.android.car.ui.recyclerview.CarUiRadioButtonListItemAdapter;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.toolbar.ToolbarController;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Activity that shows different dialogs from the device default theme.
- */
-public class DialogsActivity extends Activity implements InsetsChangedListener {
-
-    private final List<Pair<Integer, View.OnClickListener>> mButtons = new ArrayList<>();
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.car_ui_recycler_view_activity);
-        ToolbarController toolbar = CarUi.requireToolbar(this);
-        toolbar.setTitle(getTitle());
-        toolbar.setState(Toolbar.State.SUBPAGE);
-
-        mButtons.add(Pair.create(R.string.dialog_show_dialog,
-                v -> showDialog()));
-        mButtons.add(Pair.create(R.string.dialog_show_dialog_icon,
-                v -> showDialogWithIcon()));
-        mButtons.add(Pair.create(R.string.dialog_show_dialog_edit,
-                v -> showDialogWithTextBox()));
-        mButtons.add(Pair.create(R.string.dialog_show_dialog_only_positive,
-                v -> showDialogWithOnlyPositiveButton()));
-        mButtons.add(Pair.create(R.string.dialog_show_dialog_no_button,
-                v -> showDialogWithNoButtonProvided()));
-        mButtons.add(Pair.create(R.string.dialog_show_dialog_checkbox,
-                v -> showDialogWithCheckbox()));
-        mButtons.add(Pair.create(R.string.dialog_show_dialog_no_title,
-                v -> showDialogWithoutTitle()));
-        mButtons.add(Pair.create(R.string.dialog_show_toast,
-                v -> showToast()));
-        mButtons.add(Pair.create(R.string.dialog_show_subtitle,
-                v -> showDialogWithSubtitle()));
-        mButtons.add(Pair.create(R.string.dialog_show_subtitle_and_icon,
-                v -> showDialogWithSubtitleAndIcon()));
-        mButtons.add(Pair.create(R.string.dialog_show_long_subtitle_and_icon,
-                v -> showDialogWithLongSubtitleAndIcon()));
-        mButtons.add(Pair.create(R.string.dialog_show_single_choice,
-                v -> showDialogWithSingleChoiceItems()));
-        mButtons.add(Pair.create(R.string.dialog_show_permission_dialog,
-                v -> showPermissionDialog()));
-        mButtons.add(Pair.create(R.string.dialog_show_multi_permission_dialog,
-                v -> showMultiPermissionDialog()));
-
-        CarUiRecyclerView recyclerView = requireViewById(R.id.list);
-        recyclerView.setAdapter(mAdapter);
-    }
-
-    private void showDialog() {
-        new AlertDialogBuilder(this)
-                .setTitle("Standard Alert Dialog")
-                .setMessage("With a message to show.")
-                .setNeutralButton("NEUTRAL", (dialogInterface, which) -> {
-                })
-                .setPositiveButton("OK", (dialogInterface, which) -> {
-                })
-                .setNegativeButton("CANCEL", (dialogInterface, which) -> {
-                })
-                .show();
-    }
-
-    private void showDialogWithIcon() {
-        new AlertDialogBuilder(this)
-                .setTitle("Alert dialog with icon")
-                .setMessage("The message body of the alert")
-                .setIcon(R.drawable.ic_tracklist)
-                .show();
-    }
-
-    private void showDialogWithNoButtonProvided() {
-        new AlertDialogBuilder(this)
-                .setTitle("Standard Alert Dialog")
-                .show();
-    }
-
-    private void showDialogWithCheckbox() {
-        new AlertDialogBuilder(this)
-                .setTitle("Custom Dialog Box")
-                .setMultiChoiceItems(
-                        new CharSequence[]{"I am a checkbox"},
-                        new boolean[]{false},
-                        (dialog, which, isChecked) -> {
-                        })
-                .setPositiveButton("OK", (dialogInterface, which) -> {
-                })
-                .setNegativeButton("CANCEL", (dialogInterface, which) -> {
-                })
-                .show();
-    }
-
-    private void showDialogWithTextBox() {
-        new AlertDialogBuilder(this)
-                .setTitle("Standard Alert Dialog")
-                .setEditBox("Edit me please", null, null)
-                .setPositiveButton("OK", (dialogInterface, i) -> {
-                })
-                .show();
-    }
-
-    private void showDialogWithOnlyPositiveButton() {
-        new AlertDialogBuilder(this)
-                .setTitle("Standard Alert Dialog").setMessage("With a message to show.")
-                .setPositiveButton("OK", (dialogInterface, i) -> {
-                })
-                .show();
-    }
-
-    private void showDialogWithoutTitle() {
-        new AlertDialogBuilder(this)
-                .setMessage("I dont have a title.")
-                .setPositiveButton("OK", (dialogInterface, i) -> {
-                })
-                .setNegativeButton("CANCEL", (dialogInterface, which) -> {
-                })
-                .show();
-    }
-
-    private void showToast() {
-        Toast.makeText(this, "Toast message looks like this", Toast.LENGTH_LONG).show();
-    }
-
-    private void showDialogWithSubtitle() {
-        new AlertDialogBuilder(this)
-                .setTitle("My Title!")
-                .setSubtitle("My Subtitle!")
-                .setMessage("My Message!")
-                .show();
-    }
-
-    private void showDialogWithSingleChoiceItems() {
-        ArrayList<CarUiRadioButtonListItem> data = new ArrayList<>();
-
-        CarUiRadioButtonListItem item = new CarUiRadioButtonListItem();
-        item.setTitle("First item");
-        data.add(item);
-
-        item = new CarUiRadioButtonListItem();
-        item.setTitle("Second item");
-        data.add(item);
-
-        item = new CarUiRadioButtonListItem();
-        item.setTitle("Third item");
-        data.add(item);
-
-        new AlertDialogBuilder(this)
-                .setTitle("Select one option.")
-                .setSubtitle("Ony one option may be selected at a time")
-                .setSingleChoiceItems(new CarUiRadioButtonListItemAdapter(data), null)
-                .show();
-    }
-
-    private void showDialogWithSubtitleAndIcon() {
-        new AlertDialogBuilder(this)
-                .setTitle("My Title!")
-                .setSubtitle("My Subtitle!")
-                .setMessage("My Message!")
-                .setIcon(R.drawable.ic_tracklist)
-                .show();
-    }
-
-    private void showDialogWithLongSubtitleAndIcon() {
-        new AlertDialogBuilder(this)
-                .setTitle("This is a very long title. It should likely span across "
-                            + "multiple lines or something. It shouldn't get cut off.")
-                .setSubtitle("This is a very long subtitle. It should likely span across "
-                        + "multiple lines or something. It shouldn't get cut off.")
-                .setMessage("My Message!")
-                .setIcon(R.drawable.ic_tracklist)
-                .show();
-    }
-
-    private void showPermissionDialog() {
-        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
-            Toast.makeText(this, "Permission already granted. Remove CAMERA permission from "
-                    + "Settings > All apps > PaintBooth", Toast.LENGTH_SHORT).show();
-            return;
-        }
-        requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
-    }
-
-    private void showMultiPermissionDialog() {
-        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
-                && checkSelfPermission(Manifest.permission.SEND_SMS)
-                    == PackageManager.PERMISSION_GRANTED
-                && checkSelfPermission(Manifest.permission.READ_CONTACTS)
-                    == PackageManager.PERMISSION_GRANTED) {
-            Toast.makeText(this, "Permissions are already granted. Remove CAMERA, SEND_SMS or "
-                    + "READ_CONTACTS permission from Settings > All apps > PaintBooth",
-                    Toast.LENGTH_SHORT).show();
-            return;
-        }
-        requestPermissions(new String[]{Manifest.permission.CAMERA,
-                Manifest.permission.READ_CONTACTS, Manifest.permission.SEND_SMS}, 1);
-    }
-
-    @Override
-    public void onRequestPermissionsResult(int requestCode, String[] permissions,
-            int[] grantResults) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Permission ");
-        for (int i = 0; i < permissions.length; i++) {
-            sb.append(permissions[i]);
-            sb.append("=");
-            sb.append(grantResults[i] == PackageManager.PERMISSION_GRANTED ? "granted" : "denied");
-            sb.append("\n");
-        }
-        Toast.makeText(this, sb.toString(), Toast.LENGTH_SHORT).show();
-    }
-
-    private static class ViewHolder extends CarUiRecyclerView.ViewHolder {
-
-        private final Button mButton;
-
-        ViewHolder(View itemView) {
-            super(itemView);
-            mButton = itemView.requireViewById(R.id.button);
-        }
-
-        public void bind(Integer title, View.OnClickListener listener) {
-            mButton.setText(title);
-            mButton.setOnClickListener(listener);
-        }
-    }
-
-    private final CarUiRecyclerView.Adapter<ViewHolder> mAdapter =
-            new CarUiRecyclerView.Adapter<ViewHolder>() {
-                @Override
-                public int getItemCount() {
-                    return mButtons.size();
-                }
-
-                @Override
-                public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
-                    View item =
-                            LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,
-                                    parent, false);
-                    return new ViewHolder(item);
-                }
-
-                @Override
-                public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
-                    Pair<Integer, View.OnClickListener> pair = mButtons.get(position);
-                    holder.bind(pair.first, pair.second);
-                }
-            };
-
-    @Override
-    public void onCarUiInsetsChanged(Insets insets) {
-        requireViewById(R.id.list)
-                .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        requireViewById(android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
-    }
-}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java
deleted file mode 100644
index 32fcbc9..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/overlays/OverlayManagerImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth.overlays;
-
-import android.car.userlib.CarUserManagerHelper;
-import android.content.Context;
-import android.content.om.IOverlayManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import androidx.annotation.NonNull;
-
-import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * OverlayManager implementation. Exclude this file when building Paintbooth outside of the system
- * image.
- */
-public class OverlayManagerImpl implements OverlayManager {
-    private final CarUserManagerHelper mCarUserManagerHelper;
-    private final IOverlayManager mOverlayManager;
-
-    public OverlayManagerImpl(Context context) {
-        mCarUserManagerHelper = new CarUserManagerHelper(context);
-        mOverlayManager = IOverlayManager.Stub.asInterface(
-                ServiceManager.getService(Context.OVERLAY_SERVICE));
-    }
-
-    private OverlayInfo convertOverlayInfo(android.content.om.OverlayInfo info) {
-        return new OverlayInfo() {
-            @NonNull
-            @Override
-            public String getPackageName() {
-                return info.packageName;
-            }
-
-            @Override
-            public boolean isEnabled() {
-                return info.state == android.content.om.OverlayInfo.STATE_ENABLED;
-            }
-        };
-    }
-
-    @Override
-    @NonNull
-    public Map<String, List<OverlayManager.OverlayInfo>> getOverlays() throws RemoteException {
-        Map<String, List<android.content.om.OverlayInfo>> overlays = mOverlayManager
-                .getAllOverlays(mCarUserManagerHelper.getCurrentForegroundUserId());
-        return overlays.entrySet()
-                .stream()
-                .collect(toMap(Map.Entry::getKey, e -> e.getValue()
-                        .stream()
-                        .map(this::convertOverlayInfo)
-                        .collect(toList())));
-    }
-
-    @Override
-    public void applyOverlay(@NonNull String packageName, boolean enable) throws RemoteException {
-        mOverlayManager.setEnabled(packageName, enable,
-                mCarUserManagerHelper.getCurrentForegroundUserId());
-    }
-}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
deleted file mode 100644
index 233c873..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/preferences/PreferenceDemoFragment.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.paintbooth.preferences;
-
-import android.os.Bundle;
-
-import com.android.car.ui.paintbooth.R;
-import com.android.car.ui.preference.CarUiPreference;
-import com.android.car.ui.preference.CarUiSwitchPreference;
-import com.android.car.ui.preference.PreferenceFragment;
-
-/**
- * Fragment to load preferences
- */
-public class PreferenceDemoFragment extends PreferenceFragment {
-
-    @Override
-    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
-        // Load the preferences from an XML resource
-        setPreferencesFromResource(R.xml.preference_samples, rootKey);
-        CarUiPreference preferenceDisabledWithoutRipple = findPreference(
-                "preference_disabled_without_ripple");
-        preferenceDisabledWithoutRipple.setEnabled(false);
-        preferenceDisabledWithoutRipple.setMessageToShowWhenDisabledPreferenceClicked(
-                "I am disabled because...");
-        preferenceDisabledWithoutRipple.setShouldShowRippleOnDisabledPreference(false);
-
-        CarUiPreference preferenceDisabledWithRipple = findPreference(
-                "preference_disabled_with_ripple");
-        preferenceDisabledWithRipple.setEnabled(false);
-        preferenceDisabledWithRipple.setMessageToShowWhenDisabledPreferenceClicked(
-                "I am disabled because...");
-        preferenceDisabledWithRipple.setShouldShowRippleOnDisabledPreference(true);
-
-        CarUiSwitchPreference carUiSwitchPreference = findPreference("switch");
-        carUiSwitchPreference.setEnabled(false);
-        carUiSwitchPreference.setMessageToShowWhenDisabledPreferenceClicked(
-                "I am disabled because...");
-    }
-}
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
deleted file mode 100644
index 593b4ee..0000000
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.ui.paintbooth.toolbar;
-
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.AlertDialogBuilder;
-import com.android.car.ui.baselayout.Insets;
-import com.android.car.ui.baselayout.InsetsChangedListener;
-import com.android.car.ui.core.CarUi;
-import com.android.car.ui.paintbooth.R;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-import com.android.car.ui.toolbar.MenuItem;
-import com.android.car.ui.toolbar.TabLayout;
-import com.android.car.ui.toolbar.Toolbar;
-import com.android.car.ui.toolbar.ToolbarController;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ToolbarActivity extends AppCompatActivity implements InsetsChangedListener {
-
-    private List<MenuItem> mMenuItems = new ArrayList<>();
-    private List<Pair<CharSequence, View.OnClickListener>> mButtons = new ArrayList<>();
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(getLayout());
-
-        ToolbarController toolbarNonFinal = CarUi.getToolbar(this);
-        if (toolbarNonFinal == null) {
-            toolbarNonFinal = requireViewById(R.id.toolbar);
-        }
-        ToolbarController toolbar = toolbarNonFinal;
-        toolbar.setTitle(getTitle());
-        toolbar.setState(Toolbar.State.SUBPAGE);
-        toolbar.setLogo(R.drawable.ic_launcher);
-        toolbar.registerOnBackListener(
-                () -> {
-                    if (toolbar.getState() == Toolbar.State.SEARCH
-                            || toolbar.getState() == Toolbar.State.EDIT) {
-                        toolbar.setState(Toolbar.State.SUBPAGE);
-                        return true;
-                    }
-                    return false;
-                });
-
-        mMenuItems.add(MenuItem.builder(this)
-                .setToSearch()
-                .setOnClickListener(i -> toolbar.setState(Toolbar.State.SEARCH))
-                .build());
-
-        toolbar.setMenuItems(mMenuItems);
-
-        mButtons.add(Pair.create("Toggle progress bar", v -> {
-            toolbar.getProgressBar().setVisible(!toolbar.getProgressBar().isVisible());
-        }));
-
-        mButtons.add(Pair.create("Change title", v ->
-                toolbar.setTitle(toolbar.getTitle() + " X")));
-
-        mButtons.add(Pair.create("Add subtitle", v -> {
-            toolbar.setSubtitle("subtitle");
-        }));
-
-        mButtons.add(Pair.create("Update subtitle every 1 sec", v -> {
-            final int[] count = {0};
-            Thread t = new Thread() {
-                @Override
-                public void run() {
-                    try {
-                        while (count[0] < 6) {
-                            Thread.sleep(1000);
-                            runOnUiThread(new Runnable() {
-                                @Override
-                                public void run() {
-                                    toolbar.setSubtitle(
-                                            "subtitle updating count: " + count[0]);
-                                    count[0]++;
-                                }
-                            });
-                        }
-                    } catch (InterruptedException e) {
-                        // Do nothing
-                    }
-                }
-            };
-            t.start();
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_set_xml_resource), v -> {
-            mMenuItems.clear();
-            toolbar.setMenuItems(R.xml.menuitems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_icon), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setToSettings()
-                    .setOnClickListener(i -> Toast.makeText(this, "Clicked",
-                            Toast.LENGTH_SHORT).show())
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_untined_icon), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setIcon(R.drawable.ic_tracklist)
-                    .setTinted(false)
-                    .setOnClickListener(
-                            i -> Toast.makeText(this, "Clicked",
-                                    Toast.LENGTH_SHORT).show())
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        Mutable<Integer> overflowCounter = new Mutable<>(1);
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_overflow), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setTitle("Foo " + overflowCounter.value)
-                    .setOnClickListener(
-                            i -> Toast.makeText(this, "Clicked",
-                                    Toast.LENGTH_SHORT).show())
-                    .setDisplayBehavior(MenuItem.DisplayBehavior.NEVER)
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-            overflowCounter.value++;
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_switch), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setCheckable()
-                    .setOnClickListener(
-                            i ->
-                                    Toast.makeText(this,
-                                            "Checked? " + i.isChecked(),
-                                            Toast.LENGTH_SHORT)
-                                            .show())
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_text), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setTitle("Baz")
-                    .setOnClickListener(
-                            i -> Toast.makeText(this, "Clicked",
-                                    Toast.LENGTH_SHORT).show())
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_icon_text), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setIcon(R.drawable.ic_tracklist)
-                    .setTitle("Bar")
-                    .setShowIconAndTitle(true)
-                    .setOnClickListener(
-                            i -> Toast.makeText(this, "Clicked",
-                                    Toast.LENGTH_SHORT).show())
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_untinted_icon_and_text), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setIcon(R.drawable.ic_tracklist)
-                    .setTitle("Bar")
-                    .setShowIconAndTitle(true)
-                    .setTinted(false)
-                    .setOnClickListener(
-                            i -> Toast.makeText(this, "Clicked",
-                                    Toast.LENGTH_SHORT).show())
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_activatable), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setIcon(R.drawable.ic_tracklist)
-                    .setActivatable()
-                    .setOnClickListener(
-                            i -> Toast.makeText(this, "Clicked",
-                                    Toast.LENGTH_SHORT).show())
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_morphing), v -> {
-            mMenuItems.add(MenuItem.builder(this)
-                    .setTitle("Become icon")
-                    .setOnClickListener(i ->
-                            i.setIcon(i.getIcon() == null ? R.drawable.ic_tracklist : 0))
-                    .build());
-            toolbar.setMenuItems(mMenuItems);
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_visibility),
-                v -> getMenuItem(item -> item.setVisible(!item.isVisible()))));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_enable),
-                v -> getMenuItem(item -> item.setEnabled(!item.isEnabled()))));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_perform_click),
-                v -> getMenuItem(MenuItem::performClick)));
-
-        final Drawable altIcon = getDrawable(R.drawable.ic_cut);
-        Map<MenuItem, Drawable> iconBackups = new HashMap<>();
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_icon), v ->
-                getMenuItem(item -> {
-                    Drawable currentIcon = item.getIcon();
-                    Drawable newIcon = altIcon;
-                    if (iconBackups.containsKey(item)) {
-                        newIcon = iconBackups.get(item);
-                    }
-                    item.setIcon(newIcon);
-                    iconBackups.put(item, currentIcon);
-                })));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_show_while_search), v ->
-                toolbar.setShowMenuItemsWhileSearching(
-                        !toolbar.getShowMenuItemsWhileSearching())));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_cycle_nav_button), v -> {
-            Toolbar.NavButtonMode mode = toolbar.getNavButtonMode();
-            if (mode == Toolbar.NavButtonMode.BACK) {
-                toolbar.setNavButtonMode(Toolbar.NavButtonMode.CLOSE);
-            } else if (mode == Toolbar.NavButtonMode.CLOSE) {
-                toolbar.setNavButtonMode(Toolbar.NavButtonMode.DOWN);
-            } else {
-                toolbar.setNavButtonMode(Toolbar.NavButtonMode.BACK);
-            }
-        }));
-
-        Mutable<Boolean> hasLogo = new Mutable<>(true);
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_logo), v -> {
-            toolbar.setLogo(hasLogo.value ? 0 : R.drawable.ic_launcher);
-            hasLogo.value = !hasLogo.value;
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_cycle_state), v -> {
-            if (toolbar.getState() == Toolbar.State.SUBPAGE) {
-                toolbar.setState(Toolbar.State.HOME);
-            } else if (toolbar.getState() == Toolbar.State.HOME) {
-                toolbar.setState(Toolbar.State.EDIT);
-            } else {
-                toolbar.setState(Toolbar.State.SUBPAGE);
-            }
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_search_hint), v -> {
-            if (toolbar.getSearchHint().toString().contentEquals("Foo")) {
-                toolbar.setSearchHint("Bar");
-            } else {
-                toolbar.setSearchHint("Foo");
-            }
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_background),
-                v -> toolbar.setBackgroundShown(!toolbar.getBackgroundShown())));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_tab), v -> toolbar.addTab(
-                new TabLayout.Tab(getDrawable(R.drawable.ic_launcher), "Foo"))));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_add_tab_with_custom_text), v -> {
-            SimpleTextWatcher textWatcher = new SimpleTextWatcher();
-            new AlertDialogBuilder(this)
-                    .setEditBox(null, textWatcher, null)
-                    .setTitle("Enter the text for the title")
-                    .setPositiveButton("Ok", (dialog, which) ->
-                            toolbar.addTab(
-                                    new TabLayout.Tab(
-                                            getDrawable(
-                                                    R.drawable.ic_launcher),
-                                            textWatcher.getText())))
-                    .show();
-        }));
-
-        mButtons.add(Pair.create(getString(R.string.toolbar_show_tabs_in_subpage), v ->
-                toolbar.setShowTabsInSubpage(!toolbar.getShowTabsInSubpage())));
-
-        Mutable<Boolean> showingLauncherIcon = new Mutable<>(false);
-        mButtons.add(Pair.create(getString(R.string.toolbar_toggle_search_icon), v -> {
-            if (showingLauncherIcon.value) {
-                toolbar.setSearchIcon(0);
-            } else {
-                toolbar.setSearchIcon(R.drawable.ic_launcher);
-            }
-            showingLauncherIcon.value = !showingLauncherIcon.value;
-        }));
-
-        CarUiRecyclerView prv = requireViewById(R.id.list);
-        prv.setAdapter(mAdapter);
-    }
-
-    /** Override in subclasses to change the layout */
-    protected int getLayout() {
-        return R.layout.car_ui_recycler_view_activity;
-    }
-
-    @Override
-    public void onCarUiInsetsChanged(Insets insets) {
-        requireViewById(R.id.list)
-                .setPadding(0, insets.getTop(), 0, insets.getBottom());
-        requireViewById(android.R.id.content)
-                .setPadding(insets.getLeft(), 0, insets.getRight(), 0);
-    }
-
-    public void xmlMenuItemClicked(MenuItem item) {
-        Toast.makeText(this, "Xml item clicked! " + item.getTitle() + ", id: " + item.getId(),
-                Toast.LENGTH_SHORT).show();
-    }
-
-    private void getMenuItem(MenuItem.OnClickListener listener) {
-        if (mMenuItems.size() == 1) {
-            listener.onClick(mMenuItems.get(0));
-            return;
-        }
-
-        SimpleTextWatcher textWatcher = new SimpleTextWatcher();
-        new AlertDialogBuilder(this)
-                .setEditBox("", textWatcher, null, InputType.TYPE_CLASS_NUMBER)
-                .setTitle("Enter the index of the MenuItem")
-                .setPositiveButton("Ok", (dialog, which) -> {
-                    try {
-                        MenuItem item = mMenuItems.get(
-                                Integer.parseInt(textWatcher.getText()));
-                        listener.onClick(item);
-                    } catch (NumberFormatException | IndexOutOfBoundsException e) {
-                        Toast.makeText(this, "Invalid index \"" + textWatcher.getText()
-                                        + "\", valid range is 0 to " + (mMenuItems.size() - 1),
-                                Toast.LENGTH_LONG).show();
-                    }
-                }).show();
-    }
-
-    private static class ViewHolder extends RecyclerView.ViewHolder {
-
-        private final Button mButton;
-
-        ViewHolder(View itemView) {
-            super(itemView);
-            mButton = itemView.requireViewById(R.id.button);
-        }
-
-        public void bind(CharSequence title, View.OnClickListener listener) {
-            mButton.setText(title);
-            mButton.setOnClickListener(listener);
-        }
-    }
-
-    private final RecyclerView.Adapter<ViewHolder> mAdapter =
-            new RecyclerView.Adapter<ViewHolder>() {
-                @Override
-                public int getItemCount() {
-                    return mButtons.size();
-                }
-
-                @Override
-                public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
-                    View item =
-                            LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,
-                                    parent, false);
-                    return new ViewHolder(item);
-                }
-
-                @Override
-                public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
-                    Pair<CharSequence, View.OnClickListener> pair = mButtons.get(position);
-                    holder.bind(pair.first, pair.second);
-                }
-            };
-
-    /**
-     * For changing values from lambdas
-     */
-    private static final class Mutable<E> {
-
-        public E value;
-
-        Mutable() {
-            value = null;
-        }
-
-        Mutable(E value) {
-            this.value = value;
-        }
-    }
-
-    /**
-     * Used for getting text from a dialog.
-     */
-    private static final class SimpleTextWatcher implements TextWatcher {
-
-        private String mValue;
-
-        @Override
-        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-        }
-
-        @Override
-        public void onTextChanged(CharSequence s, int start, int before, int count) {
-        }
-
-        @Override
-        public void afterTextChanged(Editable s) {
-            mValue = s.toString();
-        }
-
-        public String getText() {
-            return mValue;
-        }
-    }
-}
diff --git a/car-ui-lib/tests/robotests/Android.mk b/car-ui-lib/tests/robotests/Android.mk
deleted file mode 100644
index a532bc9..0000000
--- a/car-ui-lib/tests/robotests/Android.mk
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH := $(call my-dir)
-
-############################################################
-# CarUi lib just for Robolectric test target.     #
-############################################################
-include $(CLEAR_VARS)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
-    $(LOCAL_PATH)/tests/robotests/res \
-
-LOCAL_PACKAGE_NAME := CarUi
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_JAVA_LIBRARIES := android.car
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    car-ui-lib
-
-include $(BUILD_PACKAGE)
-
-################################################
-# Car Ui Robolectric test target. #
-################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CarUiRoboTests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_RESOURCE_DIRS := config
-
-# Include the testing libraries
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    testng \
-    truth-prebuilt
-
-LOCAL_INSTRUMENTATION_FOR := CarUi
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-##################################################################
-# Car Ui runner target to run the previous target. #
-##################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := RunCarUiRoboTests
-
-LOCAL_JAVA_LIBRARIES := \
-    android.car \
-    CarUiRoboTests \
-    robolectric_android-all-stub \
-    Robolectric_all-target \
-    mockito-robolectric-prebuilt \
-    testng \
-    truth-prebuilt
-
-LOCAL_TEST_PACKAGE := CarUi
-
-LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
-    $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
-
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
-
-include external/robolectric-shadows/run_robotests.mk
diff --git a/car-ui-lib/tests/robotests/AndroidManifest.xml b/car-ui-lib/tests/robotests/AndroidManifest.xml
deleted file mode 100644
index b62579f..0000000
--- a/car-ui-lib/tests/robotests/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2019 Google Inc.
-
-    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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.car.ui">
-</manifest>
diff --git a/car-ui-lib/tests/robotests/build.gradle b/car-ui-lib/tests/robotests/build.gradle
deleted file mode 100644
index 0784a74..0000000
--- a/car-ui-lib/tests/robotests/build.gradle
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- */
-
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-
-buildscript {
-    repositories {
-        google()
-        jcenter()
-    }
-
-    dependencies {
-        classpath 'com.android.tools.build:gradle:3.5.3'
-
-        // NOTE: Do not place your application dependencies here; they belong
-        // in the individual module build.gradle files
-    }
-}
-
-allprojects {
-    repositories {
-        google()
-        jcenter()
-    }
-}
-
-// Library-level build file
-
-apply plugin: 'com.android.library'
-
-android {
-    compileSdkVersion 29
-
-    defaultConfig {
-        minSdkVersion 28
-        targetSdkVersion 29
-        versionCode 1
-        versionName "1.0"
-    }
-
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-
-    sourceSets {
-        main {
-            manifest.srcFile 'AndroidManifest.xml'
-            res.srcDirs = ['res']
-        }
-
-        test {
-            java.srcDirs = ['src']
-        }
-    }
-
-    testOptions {
-        unitTests {
-            includeAndroidResources = true
-        }
-    }
-}
-
-dependencies {
-    implementation project(':')
-    testImplementation "androidx.test.ext:junit:1.1.1"
-    testImplementation "org.robolectric:robolectric:4.0-alpha-3"
-    testImplementation "org.mockito:mockito-core:2.19.0"
-    testImplementation 'org.mockito:mockito-inline:2.19.0'
-    testImplementation "com.google.truth:truth:0.29"
-    testImplementation "org.testng:testng:6.9.9"
-
-    // This is the gradle equivalent of linking to android.car in our Android.mk
-    implementation files('../../../../../../../out/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/classes.jar')
-}
diff --git a/car-ui-lib/tests/robotests/config/robolectric.properties b/car-ui-lib/tests/robotests/config/robolectric.properties
deleted file mode 100644
index 8768f6b..0000000
--- a/car-ui-lib/tests/robotests/config/robolectric.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2019 Google Inc.
-#
-# 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.
-#
-manifest=packages/apps/Car/libs/car-ui-lib/tests/robotests/AndroidManifest.xml
-sdk=NEWEST_SDK
diff --git a/car-ui-lib/tests/robotests/res/layout/test_grid_car_ui_recycler_view.xml b/car-ui-lib/tests/robotests/res/layout/test_grid_car_ui_recycler_view.xml
deleted file mode 100644
index c09d1c7..0000000
--- a/car-ui-lib/tests/robotests/res/layout/test_grid_car_ui_recycler_view.xml
+++ /dev/null
@@ -1,28 +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.
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <com.android.car.ui.recyclerview.CarUiRecyclerView
-        android:id="@+id/test_prv"
-        app:layoutStyle="grid"
-        app:numOfColumns="4"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
-</FrameLayout>
\ No newline at end of file
diff --git a/car-ui-lib/tests/robotests/res/layout/test_linear_car_ui_recycler_view.xml b/car-ui-lib/tests/robotests/res/layout/test_linear_car_ui_recycler_view.xml
deleted file mode 100644
index e3b8218..0000000
--- a/car-ui-lib/tests/robotests/res/layout/test_linear_car_ui_recycler_view.xml
+++ /dev/null
@@ -1,25 +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.
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <com.android.car.ui.recyclerview.CarUiRecyclerView
-        android:id="@+id/test_prv"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
-</FrameLayout>
\ No newline at end of file
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiRobolectricTestRunner.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiRobolectricTestRunner.java
deleted file mode 100644
index 20561f2..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiRobolectricTestRunner.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui;
-
-import androidx.annotation.NonNull;
-
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.manifest.AndroidManifest;
-import org.robolectric.res.Fs;
-import org.robolectric.res.ResourcePath;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Custom test runner for CarUi. This is needed because the default behavior for
- * robolectric is just to grab the resource directory in the target package.
- * We want to override this to add several spanning different projects.
- */
-public class CarUiRobolectricTestRunner extends RobolectricTestRunner {
-    private static final Map<String, String> AAR_VERSIONS;
-    private static final String SUPPORT_RESOURCE_PATH_TEMPLATE =
-            "jar:file:%3$s/prebuilts/sdk/current/androidx/m2repository/androidx/"
-                    + "%1$s/%1$s/%2$s/%1$s-%2$s.aar!/res";
-    // contraint-layout aar lives in separate path.
-    // Note its path contains a hyphen.
-    private static final String CONSTRAINT_LAYOUT_RESOURCE_PATH_TEMPLATE =
-            "jar:file:%3$s/prebuilts/sdk/current/extras/constraint-layout-x/"
-                    + "%1$s/%2$s/%1$s-%2$s.aar!/res";
-
-    static {
-        AAR_VERSIONS = new HashMap<>();
-        AAR_VERSIONS.put("appcompat", "1.1.0-alpha06");
-        AAR_VERSIONS.put("constraintlayout", "1.1.2");
-        AAR_VERSIONS.put("preference", "1.1.0-alpha06");
-    }
-
-    public CarUiRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-    }
-
-    private static ResourcePath createResourcePath(@NonNull String filePath) {
-        try {
-            return new ResourcePath(null, Fs.fromURL(new URL(filePath)), null);
-        } catch (MalformedURLException e) {
-            throw new RuntimeException("CarUiRobolectricTestRunner failure", e);
-        }
-    }
-
-    /**
-     * Create the resource path for a support library component's JAR.
-     */
-    private static String createSupportResourcePathFromJar(@NonNull String pathRoot,
-            @NonNull String componentId) {
-        if (!AAR_VERSIONS.containsKey(componentId)) {
-            throw new IllegalArgumentException("Unknown component " + componentId
-                    + ". Update test with appropriate component name and version.");
-        }
-        if (componentId.equals("constraintlayout")) {
-            return String.format(CONSTRAINT_LAYOUT_RESOURCE_PATH_TEMPLATE, componentId,
-                    AAR_VERSIONS.get(componentId), pathRoot);
-        }
-        return String.format(SUPPORT_RESOURCE_PATH_TEMPLATE, componentId,
-                AAR_VERSIONS.get(componentId), pathRoot);
-    }
-
-    /**
-     * We modify the AndroidManifest such that we can add required resources.
-     */
-    @Override
-    protected AndroidManifest getAppManifest(Config config) {
-        try {
-            final URL appRoot;
-            final String rootRelativePath;
-            // Root path is workspace root when run from command line and module root when run from
-            // Android Studio.
-            if (new File(System.getProperty("user.dir")).getName().equals("robotests")) {
-                rootRelativePath = "../../../../../../../.";
-                appRoot = new File("../../.").toURI().toURL();
-            } else {
-                appRoot = new URL("file:packages/apps/Car/libs/car-ui-lib/");
-                rootRelativePath = "./";
-            }
-
-            // Using the manifest file's relative path, we can figure out the application directory.
-            URL manifestPath = new URL(appRoot, "AndroidManifest.xml");
-            URL resDir = new URL(appRoot, "tests/robotests/res");
-            URL assetsDir = new URL(appRoot, config.assetDir());
-
-            // By adding any resources from libraries we need to the AndroidManifest, we can access
-            // them from within the parallel universe's resource loader.
-            return new AndroidManifest(Fs.fromURL(manifestPath), Fs.fromURL(resDir),
-                    Fs.fromURL(assetsDir)) {
-                @Override
-                public List<ResourcePath> getIncludedResourcePaths() {
-                    List<ResourcePath> paths = super.getIncludedResourcePaths();
-                    paths.add(createResourcePath(
-                            String.format("file:%s/packages/apps/Car/libs/car-ui-lib/res",
-                                    rootRelativePath)));
-
-                    // Support library resources. These need to point to the prebuilts of support
-                    // library and not the source.
-                    paths.add(createResourcePath(
-                            createSupportResourcePathFromJar(rootRelativePath, "appcompat")));
-                    paths.add(createResourcePath(createSupportResourcePathFromJar(rootRelativePath,
-                            "constraintlayout")));
-                    paths.add(createResourcePath(
-                            createSupportResourcePathFromJar(rootRelativePath, "preference")));
-
-                    return paths;
-                }
-            };
-        } catch (MalformedURLException e) {
-            throw new RuntimeException("CarUiRobolectricTestRunner failure", e);
-        }
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiTestUtil.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiTestUtil.java
deleted file mode 100644
index 407e3ef..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/CarUiTestUtil.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2020 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.car.ui;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
-
-import org.robolectric.RuntimeEnvironment;
-
-/**
- * Collection of test utility methods
- */
-public class CarUiTestUtil {
-
-    /**
-     * Returns a mocked {@link Context} to be used in Robolectric tests.
-     */
-    public static Context getMockContext() {
-        Context context = spy(RuntimeEnvironment.application);
-        Resources mResources = spy(context.getResources());
-
-        when(context.getResources()).thenReturn(mResources);
-
-        // Temporarily create a layout inflater that will be used to clone a new one.
-        LayoutInflater tempInflater = LayoutInflater.from(context);
-        // Force layout inflater to use spied context
-        doAnswer(invocation -> tempInflater.cloneInContext(context))
-                .when(context).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-        // Older versions of Robolectric do not correctly handle the Resources#getValue() method.
-        // This breaks CarUtils.findViewByRefId() functionality in tests. To workaround this issue,
-        // use a spy to rely on findViewById() functionality instead.
-        doAnswer(invocation -> {
-            Object[] args = invocation.getArguments();
-            ((TypedValue) args[1]).resourceId = (int) args[0];
-            return null; // void method, so return null
-        }).when(mResources).getValue(anyInt(), isA(TypedValue.class), isA(Boolean.class));
-        return context;
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/TestConfig.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/TestConfig.java
deleted file mode 100644
index 46a9d0c..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/TestConfig.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui;
-
-public class TestConfig {
-    public static final int SDK_VERSION = 28;
-    public static final String MANIFEST_PATH =
-            "packages/apps/Car/car-ui-lib/AndroidManifest.xml";
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
deleted file mode 100644
index f404f6c..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiListItemTest.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
-import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class CarUiListItemTest {
-
-    private CarUiRecyclerView mListView;
-    private Context mContext;
-
-    @Mock
-    CarUiContentListItem.OnCheckedChangeListener mOnCheckedChangeListener;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = CarUiTestUtil.getMockContext();
-        mListView = new CarUiRecyclerView(mContext);
-    }
-
-    private CarUiListItemAdapter.ListItemViewHolder getListItemViewHolderAtPosition(int position) {
-        return (CarUiListItemAdapter.ListItemViewHolder) mListView.findViewHolderForAdapterPosition(
-                position);
-    }
-
-    private View getListItemTitleAtPosition(int position) {
-        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.title);
-    }
-
-    private View getListItemBodyAtPosition(int position) {
-        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.body);
-    }
-
-    private View getListItemIconContainerAtPosition(int position) {
-        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.icon_container);
-    }
-
-    private View getListItemActionContainerAtPosition(int position) {
-        return getListItemViewHolderAtPosition(position)
-                .itemView.findViewById(R.id.action_container);
-    }
-
-    private Switch getListItemSwitchAtPosition(int position) {
-        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.switch_widget);
-    }
-
-    private CheckBox getListItemCheckBoxAtPosition(int position) {
-        return getListItemViewHolderAtPosition(position)
-                .itemView.findViewById(R.id.checkbox_widget);
-    }
-
-    private View getListItemIconAtPosition(int position) {
-        return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.icon);
-    }
-
-    private CarUiListItemAdapter.HeaderViewHolder getHeaderViewHolderAtPosition(int position) {
-        return (CarUiListItemAdapter.HeaderViewHolder) mListView.findViewHolderForAdapterPosition(
-                position);
-    }
-
-    private TextView getHeaderViewHolderTitleAtPosition(int position) {
-        return getHeaderViewHolderAtPosition(position).itemView.findViewById(R.id.title);
-    }
-
-    private TextView getHeaderViewHolderBodyAtPosition(int position) {
-        return getHeaderViewHolderAtPosition(position).itemView.findViewById(R.id.body);
-    }
-
-    private void updateRecyclerViewAdapter(CarUiListItemAdapter adapter) {
-        mListView.setAdapter(adapter);
-
-        // Force CarUiRecyclerView and the nested RecyclerView to be laid out.
-        mListView.measure(0, 0);
-        mListView.layout(0, 0, 100, 10000);
-
-        if (mListView != null) {
-            mListView.measure(0, 0);
-            mListView.layout(0, 0, 100, 10000);
-        }
-
-        // Required to init nested RecyclerView
-        mListView.getViewTreeObserver().dispatchOnGlobalLayout();
-    }
-
-    @Test
-    public void testItemVisibility_withTitle() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test title");
-        items.add(item);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemActionContainerAtPosition(0).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void testItemVisibility_withTitle_withBody() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test title");
-        item.setBody("Test body");
-        items.add(item);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemBodyAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemActionContainerAtPosition(0).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void testItemVisibility_withTitle_withIcon() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
-        item.setTitle("Test title");
-        item.setIcon(mContext.getDrawable(R.drawable.car_ui_icon_close));
-        items.add(item);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemIconContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemIconAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemActionContainerAtPosition(0).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void testItemVisibility_withTitle_withCheckbox() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
-        item.setTitle("Test title");
-        items.add(item);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemActionContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemSwitchAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemCheckBoxAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemCheckBoxAtPosition(0).isChecked()).isEqualTo(false);
-    }
-
-    @Test
-    public void testItemVisibility_withTitle_withBody_withSwitch() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
-        item.setTitle("Test title");
-        item.setBody("Body text");
-        items.add(item);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemBodyAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemIconContainerAtPosition(0).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(getListItemActionContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemSwitchAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getListItemSwitchAtPosition(0).isChecked()).isEqualTo(false);
-        assertThat(getListItemCheckBoxAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void testCheckedState_switch() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
-        item.setTitle("Test title");
-        item.setOnCheckedChangeListener(mOnCheckedChangeListener);
-        item.setChecked(true);
-        items.add(item);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        Switch switchWidget = getListItemSwitchAtPosition(0);
-
-        assertThat(switchWidget.isChecked()).isEqualTo(true);
-        switchWidget.performClick();
-        assertThat(switchWidget.isChecked()).isEqualTo(false);
-        verify(mOnCheckedChangeListener, times(1))
-                .onCheckedChanged(item, false);
-    }
-
-    @Test
-    public void testCheckedState_checkbox() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
-        item.setTitle("Test title");
-        item.setOnCheckedChangeListener(mOnCheckedChangeListener);
-        items.add(item);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        CheckBox checkBox = getListItemCheckBoxAtPosition(0);
-
-        assertThat(checkBox.isChecked()).isEqualTo(false);
-        checkBox.performClick();
-        assertThat(checkBox.isChecked()).isEqualTo(true);
-        verify(mOnCheckedChangeListener, times(1))
-                .onCheckedChanged(item, true);
-    }
-
-    @Test
-    public void testHeader_onlyTitle() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CharSequence title = "Test header";
-        CarUiHeaderListItem header = new CarUiHeaderListItem(title);
-        items.add(header);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        assertThat(getHeaderViewHolderTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(getHeaderViewHolderTitleAtPosition(0).getText()).isEqualTo(title);
-        assertThat(getHeaderViewHolderBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void testHeader_titleAndBody() {
-        List<CarUiListItem> items = new ArrayList<>();
-
-        CharSequence title = "Test header";
-        CharSequence body = "With body text";
-
-        CarUiHeaderListItem header = new CarUiHeaderListItem(title, body);
-        items.add(header);
-
-        updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
-        TextView titleView = getHeaderViewHolderTitleAtPosition(0);
-        TextView bodyView = getHeaderViewHolderBodyAtPosition(0);
-
-        assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(titleView.getText()).isEqualTo(title);
-        assertThat(bodyView.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(bodyView.getText()).isEqualTo(body);
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
deleted file mode 100644
index 6c8954c..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.view.ViewGroup;
-
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
-import com.android.car.ui.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class CarUiRecyclerViewAdapterTest {
-
-    private Context mContext;
-    private CarUiRecyclerViewAdapter mCarUiRecyclerViewAdapter;
-
-    @Mock
-    private ViewGroup mParent;
-    @Mock
-    private ViewGroup.LayoutParams mLayoutParams;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = CarUiTestUtil.getMockContext();
-        mCarUiRecyclerViewAdapter = new CarUiRecyclerViewAdapter();
-    }
-
-    @Test
-    public void getItemCount_shouldAlwaysBeOne() {
-        assertThat(mCarUiRecyclerViewAdapter.getItemCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void onCreateViewHolder_frameLayoutNotNull() {
-
-        when(mParent.getContext()).thenReturn(mContext);
-        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
-
-        CarUiRecyclerViewAdapter.NestedRowViewHolder nestedRowViewHolder =
-                mCarUiRecyclerViewAdapter.onCreateViewHolder(mParent, 0);
-
-        assertThat(nestedRowViewHolder.frameLayout).isNotNull();
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
deleted file mode 100644
index f4d98f7..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.LinearLayoutManager;
-
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class CarUiRecyclerViewTest {
-
-    private Context mContext;
-    private View mView;
-    private CarUiRecyclerView mCarUiRecyclerView;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = RuntimeEnvironment.application;
-    }
-
-    @Test
-    public void onHeightChanged_shouldAddTheValueToInitialTopValue() {
-        mView = LayoutInflater.from(mContext)
-                .inflate(R.layout.test_linear_car_ui_recycler_view, null);
-
-        mCarUiRecyclerView = mView.findViewById(R.id.test_prv);
-
-        assertThat(mCarUiRecyclerView.getPaddingBottom()).isEqualTo(0);
-        assertThat(mCarUiRecyclerView.getPaddingTop()).isEqualTo(0);
-        assertThat(mCarUiRecyclerView.getPaddingStart()).isEqualTo(0);
-        assertThat(mCarUiRecyclerView.getPaddingEnd()).isEqualTo(0);
-
-        mCarUiRecyclerView.onHeightChanged(10);
-
-        assertThat(mCarUiRecyclerView.getPaddingTop()).isEqualTo(10);
-        assertThat(mCarUiRecyclerView.getPaddingBottom()).isEqualTo(0);
-        assertThat(mCarUiRecyclerView.getPaddingStart()).isEqualTo(0);
-        assertThat(mCarUiRecyclerView.getPaddingEnd()).isEqualTo(0);
-    }
-
-    @Test
-    public void setAdapter_shouldInitializeLinearLayoutManager() {
-        mView = LayoutInflater.from(mContext)
-                .inflate(R.layout.test_linear_car_ui_recycler_view, null);
-
-        mCarUiRecyclerView = mView.findViewById(R.id.test_prv);
-
-        assertThat(mCarUiRecyclerView.getEffectiveLayoutManager()).isInstanceOf(
-                LinearLayoutManager.class);
-    }
-
-    @Test
-    public void setAdapter_shouldInitializeGridLayoutManager() {
-        mView = LayoutInflater.from(mContext)
-                .inflate(R.layout.test_grid_car_ui_recycler_view, null);
-
-        mCarUiRecyclerView = mView.findViewById(R.id.test_prv);
-
-        assertThat(mCarUiRecyclerView.getEffectiveLayoutManager()).isInstanceOf(
-                GridLayoutManager.class);
-    }
-
-    @Test
-    public void init_shouldContainRecyclerView() {
-        mView = LayoutInflater.from(mContext)
-                .inflate(R.layout.test_grid_car_ui_recycler_view, null);
-
-        mCarUiRecyclerView = mView.findViewById(R.id.test_prv);
-
-        assertThat(mCarUiRecyclerView).isNotNull();
-    }
-
-    @Test
-    public void init_shouldHaveGridLayout() {
-        mCarUiRecyclerView = new CarUiRecyclerView(mContext,
-                Robolectric.buildAttributeSet().addAttribute(R.attr.layoutStyle, "grid").build());
-        assertThat(mCarUiRecyclerView.getEffectiveLayoutManager()).isInstanceOf(
-                GridLayoutManager.class);
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
deleted file mode 100644
index 052304c..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import static androidx.recyclerview.widget.LinearSmoothScroller.SNAP_TO_START;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class CarUiSmoothScrollerTest {
-
-    private Context mContext;
-    private CarUiSmoothScroller mCarUiSmoothScroller;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mCarUiSmoothScroller = new CarUiSmoothScroller(mContext);
-    }
-
-    @Test
-    public void calculateTimeForScrolling_shouldInitializeAllValues() {
-        assertThat(mCarUiSmoothScroller.mMillisecondsPerInch).isNotEqualTo(0);
-        assertThat(mCarUiSmoothScroller.mDecelerationTimeDivisor).isNotEqualTo(0);
-        assertThat(mCarUiSmoothScroller.mMillisecondsPerPixel).isNotEqualTo(0);
-        assertThat(mCarUiSmoothScroller.mInterpolator).isNotNull();
-        assertThat(mCarUiSmoothScroller.mDensityDpi).isNotEqualTo(0);
-    }
-
-    @Test
-    public void getVerticalSnapPreference_shouldReturnSnapToStart() {
-        assertThat(mCarUiSmoothScroller.getVerticalSnapPreference()).isEqualTo(SNAP_TO_START);
-    }
-
-    @Test
-    public void calculateTimeForScrolling_shouldReturnMultiplierOfMillisecondsPerPixel() {
-        assertThat(mCarUiSmoothScroller.calculateTimeForScrolling(20)).isEqualTo(
-                (int) Math.ceil(Math.abs(20) * mCarUiSmoothScroller.mMillisecondsPerPixel));
-    }
-
-    @Test
-    public void calculateTimeForDeceleration_shouldReturnNotBeZero() {
-        assertThat(mCarUiSmoothScroller.calculateTimeForDeceleration(20)).isNotEqualTo(0);
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
deleted file mode 100644
index b846103..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.view.View;
-
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class CarUiSnapHelperTest {
-
-    private Context mContext;
-    private CarUiSnapHelper mCarUiSnapHelper;
-
-    @Mock
-    private RecyclerView mRecyclerView;
-    @Mock
-    private LinearLayoutManager mLayoutManager;
-    @Mock
-    private RecyclerView.Adapter mAdapter;
-    @Mock
-    private View mChild;
-    @Mock
-    private RecyclerView.LayoutParams mLayoutParams;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-
-        mCarUiSnapHelper = new CarUiSnapHelper(mContext);
-
-        when(mRecyclerView.getContext()).thenReturn(mContext);
-        mCarUiSnapHelper.attachToRecyclerView(mRecyclerView);
-    }
-
-    @Test
-    public void calculateDistanceToFinalSnap_shouldReturnTopMarginDifference() {
-        when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
-        when(mLayoutManager.getItemCount()).thenReturn(1);
-        when(mLayoutManager.canScrollVertically()).thenReturn(true);
-        when(mLayoutManager.getChildCount()).thenReturn(1);
-        // some delta
-        when(mLayoutManager.getDecoratedTop(any())).thenReturn(10);
-        when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
-
-        int[] distance = mCarUiSnapHelper.calculateDistanceToFinalSnap(mLayoutManager, mChild);
-
-        assertThat(distance[1]).isEqualTo(10);
-    }
-
-    @Test
-    public void calculateScrollDistance_shouldScrollHeightOfView() {
-        when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
-        when(mLayoutManager.getItemCount()).thenReturn(1);
-        when(mLayoutManager.canScrollVertically()).thenReturn(true);
-        when(mLayoutManager.getChildCount()).thenReturn(1);
-        // some delta
-        when(mLayoutManager.getDecoratedTop(any())).thenReturn(10);
-        when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
-        when(mLayoutManager.getChildAt(0)).thenReturn(mChild);
-        when(mLayoutManager.getHeight()).thenReturn(-50);
-
-        int[] distance = mCarUiSnapHelper.calculateScrollDistance(0, 10);
-
-        assertThat(distance[1]).isEqualTo(50);
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/DefaultScrollBarTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
deleted file mode 100644
index d043064..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.recyclerview;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertThrows;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
-import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class DefaultScrollBarTest {
-
-    private Context mContext;
-    private ScrollBar mScrollBar;
-
-    @Mock
-    private RecyclerView mRecyclerView;
-    @Mock
-    private FrameLayout mParent;
-    @Mock
-    private FrameLayout.LayoutParams mLayoutParams;
-    @Mock
-    private RecyclerView.RecycledViewPool mRecycledViewPool;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = CarUiTestUtil.getMockContext();
-        mScrollBar = new DefaultScrollBar();
-    }
-
-    @Test
-    public void initialize_shouldInitializeScrollListener() {
-        when(mRecyclerView.getContext()).thenReturn(mContext);
-        when(mRecyclerView.getParent()).thenReturn(mParent);
-        when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
-        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
-
-        View scrollView = LayoutInflater.from(mContext).inflate(
-                R.layout.car_ui_recyclerview_scrollbar, null);
-        mScrollBar.initialize(mRecyclerView, scrollView);
-
-        // called once in DefaultScrollBar and once in SnapHelper while setting up the call backs
-        // when we use attachToRecyclerView(recyclerview)
-        verify(mRecyclerView, times(2)).addOnScrollListener(
-                any(RecyclerView.OnScrollListener.class));
-    }
-
-    @Test
-    public void initialize_shouldSetMaxRecyclerViews() {
-        when(mRecyclerView.getContext()).thenReturn(mContext);
-        when(mRecyclerView.getParent()).thenReturn(mParent);
-        when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
-        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
-
-        View scrollView = LayoutInflater.from(mContext).inflate(
-                R.layout.car_ui_recyclerview_scrollbar, null);
-        mScrollBar.initialize(mRecyclerView, scrollView);
-
-        verify(mRecycledViewPool).setMaxRecycledViews(0, 12);
-    }
-
-    @Test
-    public void initialize_shouldNotHaveFlingListener() {
-        when(mRecyclerView.getContext()).thenReturn(mContext);
-        when(mRecyclerView.getParent()).thenReturn(mParent);
-        when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
-        when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
-
-        View scrollView = LayoutInflater.from(mContext).inflate(
-                R.layout.car_ui_recyclerview_scrollbar, null);
-        mScrollBar.initialize(mRecyclerView, scrollView);
-
-        verify(mRecyclerView).setOnFlingListener(null);
-    }
-
-    @Test
-    public void setPadding_shouldThrowErrorWithoutInitialization() {
-        assertThrows(NullPointerException.class, () -> mScrollBar.setPadding(10, 20));
-    }
-
-    @Test
-    public void requestLayout_shouldThrowErrorWithoutInitialization() {
-        assertThrows(NullPointerException.class, () -> mScrollBar.requestLayout());
-    }
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ToolbarTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ToolbarTest.java
deleted file mode 100644
index 78aab7d..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/toolbar/ToolbarTest.java
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.toolbar;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.car.ui.CarUiRobolectricTestRunner;
-import com.android.car.ui.CarUiTestUtil;
-import com.android.car.ui.R;
-import com.android.car.ui.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-@RunWith(CarUiRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = {ExtendedShadowTypeface.class, ShadowAsyncLayoutInflater.class})
-public class ToolbarTest {
-    private Context mContext;
-    private Resources mResources;
-    private Toolbar mToolbar;
-
-    @Before
-    public void setUp() {
-        mContext = CarUiTestUtil.getMockContext();
-        mResources = mContext.getResources();
-        mToolbar = new Toolbar(mContext);
-    }
-
-    @Test
-    public void getters_nochanges_shouldReturnDefaults() {
-        assertThat(mToolbar.getBackgroundShown()).isEqualTo(true);
-        assertThat(mToolbar.getShowMenuItemsWhileSearching()).isEqualTo(false);
-        assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.HOME);
-        assertThat(mToolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
-                Toolbar.NavButtonMode.BACK);
-    }
-
-    @Test
-    public void setState_subpage_shouldCauseGetStateToReturnSubpage() {
-        mToolbar.setState(Toolbar.State.SUBPAGE);
-
-        assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
-    }
-
-    @Test
-    public void setters_and_getters_test() {
-        mToolbar.setTitle("Foo");
-        mToolbar.setSearchHint("Foo2");
-        mToolbar.setBackgroundShown(false);
-        mToolbar.setShowMenuItemsWhileSearching(true);
-        mToolbar.setState(Toolbar.State.SUBPAGE);
-        mToolbar.setNavButtonMode(Toolbar.NavButtonMode.CLOSE);
-
-        assertThat(mToolbar.getTitle().toString()).isEqualTo("Foo");
-        assertThat(mToolbar.getSearchHint().toString()).isEqualTo("Foo2");
-        assertThat(mToolbar.getBackgroundShown()).isEqualTo(false);
-        assertThat(mToolbar.getShowMenuItemsWhileSearching()).isEqualTo(true);
-        assertThat(mToolbar.getState()).isEquivalentAccordingToCompareTo(Toolbar.State.SUBPAGE);
-        assertThat(mToolbar.getNavButtonMode()).isEquivalentAccordingToCompareTo(
-                Toolbar.NavButtonMode.CLOSE);
-    }
-
-    @Test
-    public void showLogo_whenSet_andStateIsHome() {
-        mToolbar.setState(Toolbar.State.HOME);
-        mToolbar.setLogo(R.drawable.test_ic_launcher);
-
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void hideLogo_andTitleLogo_whenSet_andStateIsHome_andLogoIsDisabled() {
-        when(mResources.getBoolean(R.bool.car_ui_toolbar_show_logo)).thenReturn(false);
-
-        Toolbar toolbar = new Toolbar(mContext);
-        toolbar.setState(Toolbar.State.HOME);
-        toolbar.setLogo(R.drawable.test_ic_launcher);
-
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void showTitleLogo_whenSet_andStateIsNotHome() {
-        mToolbar.setState(Toolbar.State.SUBPAGE);
-        mToolbar.setLogo(R.drawable.test_ic_launcher);
-
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo).getVisibility())
-                .isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void hideLogo_andTitleLogo_whenNotSet_andStateIsHome() {
-        mToolbar.setState(Toolbar.State.HOME);
-        mToolbar.setLogo(0);
-
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);    }
-
-    @Test
-    public void hideLogo_andTitleLogo_whenNotSet_andStateIsNotHome() {
-        mToolbar.setState(Toolbar.State.SUBPAGE);
-        mToolbar.setLogo(0);
-
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_logo).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_title_logo_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void registerOnBackListener_whenBackIsPressed_shouldCallListener() {
-        mToolbar.setState(Toolbar.State.SUBPAGE);
-        Mutable<Integer> timesBackPressed = new Mutable<>(0);
-        Toolbar.OnBackListener listener = () -> {
-            timesBackPressed.value++;
-            return false;
-        };
-
-        mToolbar.registerOnBackListener(listener);
-        pressBack();
-
-        assertThat(timesBackPressed.value).isEqualTo(1);
-    }
-
-    @Test
-    public void testState_twoRow_withTitle_withTabs() {
-        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
-
-        Toolbar toolbar = new Toolbar(mContext);
-        assertThat(toolbar.isTabsInSecondRow()).isTrue();
-
-        // Set title and tabs for toolbar.
-        toolbar.setTitle("Test title");
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-
-        // Toolbar should display two rows, showing both title and tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void testState_twoRow_withTitle() {
-        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
-
-        Toolbar toolbar = new Toolbar(mContext);
-        assertThat(toolbar.isTabsInSecondRow()).isTrue();
-
-        toolbar.setTitle("Test title");
-
-        // Toolbar should display two rows, but no tabs are set so they should not be visible.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void testState_twoRow_withTabs() {
-        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(true);
-
-        Toolbar toolbar = new Toolbar(mContext);
-        assertThat(toolbar.isTabsInSecondRow()).isTrue();
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-
-        // Toolbar should display two rows with an empty title and tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void testState_oneRow_withTitle_withTabs() {
-        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
-
-        Toolbar toolbar = new Toolbar(mContext);
-        assertThat(toolbar.isTabsInSecondRow()).isFalse();
-
-        // Set title and tabs for toolbar.
-        toolbar.setTitle("Test title");
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-
-        // With only one row available, toolbar will only show tabs and not the title.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void testState_oneRow_withTitle() {
-        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
-
-        Toolbar toolbar = new Toolbar(mContext);
-        assertThat(toolbar.isTabsInSecondRow()).isFalse();
-
-        toolbar.setTitle("Test title");
-
-        // Toolbar should display one row with the title and no tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void testState_oneRow_withTabs() {
-        when(mResources.getBoolean(R.bool.car_ui_toolbar_tabs_on_second_row)).thenReturn(false);
-
-
-        Toolbar toolbar = new Toolbar(mContext);
-        assertThat(toolbar.isTabsInSecondRow()).isFalse();
-
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-        toolbar.addTab(new TabLayout.Tab(mContext.getDrawable(R.drawable.test_ic_launcher), "Foo"));
-
-        // Toolbar should display one row with only tabs.
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_tabs).getVisibility()).isEqualTo(
-                View.VISIBLE);
-        assertThat(toolbar.findViewById(R.id.car_ui_toolbar_title).getVisibility()).isNotEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void registerOnBackListener_whenListenerRegisteredTwice_shouldntCallListenerTwice() {
-        mToolbar.setState(Toolbar.State.SUBPAGE);
-        Mutable<Integer> timesBackPressed = new Mutable<>(0);
-        Toolbar.OnBackListener listener = () -> {
-            timesBackPressed.value++;
-            return false;
-        };
-
-        // Registering a second time shouldn't do anything
-        mToolbar.registerOnBackListener(listener);
-        mToolbar.registerOnBackListener(listener);
-        pressBack();
-
-        assertThat(timesBackPressed.value).isEqualTo(1);
-    }
-
-    @Test
-    public void unregisterOnBackListener_previouslyRegisteredListener_shouldUnregister() {
-        mToolbar.setState(Toolbar.State.SUBPAGE);
-        Mutable<Integer> timesBackPressed = new Mutable<>(0);
-        Toolbar.OnBackListener listener = () -> {
-            timesBackPressed.value++;
-            return false;
-        };
-
-        mToolbar.registerOnBackListener(listener);
-        mToolbar.unregisterOnBackListener(listener);
-        pressBack();
-
-        assertThat(timesBackPressed.value).isEqualTo(0);
-    }
-
-    @Test
-    public void menuItems_builder_id() {
-        MenuItem item = MenuItem.builder(mContext)
-                .setId(5)
-                .build();
-
-        assertThat(item.getId()).isEqualTo(5);
-    }
-
-    @Test
-    public void menuItems_setId_shouldWork() {
-        MenuItem item = MenuItem.builder(mContext).build();
-
-        assertThat(item.getId()).isEqualTo(View.NO_ID);
-
-        item.setId(7);
-
-        assertThat(item.getId()).isEqualTo(7);
-    }
-
-    @Test
-    public void menuItems_whenClicked_shouldCallListener() {
-        assertThat(getMenuItemCount()).isEqualTo(0);
-
-        Mutable<Boolean> button1Clicked = new Mutable<>(false);
-        Mutable<Boolean> button2Clicked = new Mutable<>(false);
-        mToolbar.setMenuItems(Arrays.asList(
-                createMenuItem(i -> button1Clicked.value = true),
-                createMenuItem(i -> button2Clicked.value = true)));
-
-        assertThat(getMenuItemCount()).isEqualTo(2);
-
-        getMenuItemView(0).performClick();
-
-        assertThat(button1Clicked.value).isTrue();
-
-        getMenuItemView(1).performClick();
-
-        assertThat(button2Clicked.value).isTrue();
-    }
-
-    @Test
-    public void menuItems_null_shouldRemoveExistingMenuItems() {
-        mToolbar.setMenuItems(Arrays.asList(
-                createMenuItem(i -> {
-                }),
-                createMenuItem(i -> {
-                })));
-
-        assertThat(getMenuItemCount()).isEqualTo(2);
-
-        mToolbar.setMenuItems(null);
-
-        assertThat(getMenuItemCount()).isEqualTo(0);
-    }
-
-    @Test
-    public void menuItems_setVisibility_shouldDefaultToShown() {
-        MenuItem item = createMenuItem(i -> {
-        });
-        mToolbar.setMenuItems(Collections.singletonList(item));
-
-        assertThat(getMenuItemView(0).getVisibility()).isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void menuItems_setVisibility_shouldHide() {
-        MenuItem item = createMenuItem(i -> {
-        });
-        mToolbar.setMenuItems(Collections.singletonList(item));
-
-        item.setVisible(false);
-        assertThat(getMenuItemView(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void menuItems_setVisibility_shouldReshowAfterHiding() {
-        MenuItem item = createMenuItem(i -> {
-        });
-        mToolbar.setMenuItems(Collections.singletonList(item));
-
-        item.setVisible(false);
-        item.setVisible(true);
-        assertThat(getMenuItemView(0).getVisibility()).isEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void menuItems_equalItems_shouldntRecreateViews() {
-        List<MenuItem> menuItems = Arrays.asList(
-                createMenuItem(i -> {
-                }),
-                createMenuItem(i -> {
-                }));
-        mToolbar.setMenuItems(menuItems);
-
-        assertThat(getMenuItemCount()).isEqualTo(2);
-
-        View firstMenuItemView = getMenuItemView(0);
-
-        mToolbar.setMenuItems(menuItems);
-
-        assertThat(firstMenuItemView).isSameAs(getMenuItemView(0));
-    }
-
-    @Test
-    public void menuItems_searchScreen_shouldHideMenuItems() {
-        mToolbar.setMenuItems(Arrays.asList(
-                MenuItem.builder(mContext).setToSearch().build(),
-                createMenuItem(i -> {
-                })));
-
-        mToolbar.setShowMenuItemsWhileSearching(false);
-        mToolbar.setState(Toolbar.State.SEARCH);
-
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_menu_items_container).getVisibility())
-                .isNotEqualTo(View.VISIBLE);
-    }
-
-    @Test
-    public void menuItems_showMenuItemsWhileSearching() {
-        mToolbar.setMenuItems(Arrays.asList(
-                MenuItem.builder(mContext).setToSearch().build(),
-                createMenuItem(i -> {
-                })));
-
-        mToolbar.setShowMenuItemsWhileSearching(true);
-        mToolbar.setState(Toolbar.State.SEARCH);
-
-        assertThat(mToolbar.findViewById(R.id.car_ui_toolbar_menu_items_container).getVisibility())
-                .isEqualTo(View.VISIBLE);
-        assertThat(getMenuItemView(0).getVisibility()).isNotEqualTo(View.VISIBLE);
-        assertThat(getMenuItemView(1).getVisibility()).isEqualTo(View.VISIBLE);
-    }
-
-    private MenuItem createMenuItem(MenuItem.OnClickListener listener) {
-        return MenuItem.builder(mContext)
-                .setTitle("Button!")
-                .setOnClickListener(listener)
-                .build();
-    }
-
-    private int getMenuItemCount() {
-        return mToolbar.getMenuItems().size();
-    }
-
-    private View getMenuItemView(int index) {
-        return ((ViewGroup) mToolbar
-                .findViewById(R.id.car_ui_toolbar_menu_items_container))
-                .getChildAt(index);
-    }
-
-    private void pressBack() {
-        mToolbar.findViewById(R.id.car_ui_toolbar_nav_icon_container).performClick();
-    }
-
-    private static class Mutable<T> {
-        public T value;
-
-        Mutable(T value) {
-            this.value = value;
-        }
-    }
-
-}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
deleted file mode 100644
index fe6f80c..0000000
--- a/car-ui-lib/tests/robotests/src/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.ui.utils;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.car.drivingstate.CarUxRestrictions;
-
-import com.android.car.ui.TestConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class CarUxRestrictionsUtilTest {
-    private int[] mRestrictionsArray;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mRestrictionsArray = new int[]{
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
-                        | CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
-                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED
-        };
-    }
-
-    @Test
-    public void testNullActiveRestriction() {
-        CarUxRestrictions activeRestrictions = null;
-        boolean[] expectedResults = {true, true, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-
-    @Test
-    public void testOneActiveRestriction() {
-        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD, /* timestamp= */0).build();
-        boolean[] expectedResults = {true, false, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-
-    @Test
-    public void testMultipleActiveRestrictions() {
-        CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
-                CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
-                        | CarUxRestrictions.UX_RESTRICTIONS_NO_TEXT_MESSAGE, /* timestamp= */
-                0).build();
-        boolean[] expectedResults = {true, false, true, true};
-        for (int i = 0; i < mRestrictionsArray.length; i++) {
-            boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
-                    activeRestrictions);
-            assertThat(actualResult == expectedResults[i]).isTrue();
-        }
-    }
-}
diff --git a/car-ui-lib/tests/tools/quick_rro.py b/car-ui-lib/tests/tools/quick_rro.py
index 3d7d9ea..aaf186b 100755
--- a/car-ui-lib/tests/tools/quick_rro.py
+++ b/car-ui-lib/tests/tools/quick_rro.py
@@ -142,11 +142,11 @@
     if len(packages) == 0:
         print('No quick RROs to uninstall')
 
-def delete_arsc_flat_files(path):
-    """Deletes all .arsc.flat files under `path`"""
+def delete_flat_files(path):
+    """Deletes all .flat files under `path`"""
     for filename in os.listdir(path):
-        if filename.endswith('.arsc.flat'):
-            run_command(['rm', os.path.join(path, filename)])
+        if filename.endswith('.flat'):
+            os.remove(os.path.join(path, filename))
 
 def build(args, package_name):
     """Builds the RRO apk"""
@@ -200,7 +200,7 @@
     run_command(['aapt2', 'compile', '-o', os.path.join(root_folder, 'compiled.zip'),
                  '--dir', resource_folder])
 
-    delete_arsc_flat_files(root_folder)
+    delete_flat_files(root_folder)
 
     run_command(['unzip', os.path.join(root_folder, 'compiled.zip'),
                  '-d', root_folder])
@@ -209,14 +209,14 @@
                     '-o', unsigned_apk, '--manifest', manifest_file,
                     '-I', android_jar_path]
     for filename in os.listdir(root_folder):
-        if filename.endswith('.arsc.flat'):
+        if filename.endswith('.flat'):
             link_command.extend(['-R', os.path.join(root_folder, filename)])
     run_command(link_command)
 
-    # For some reason signapk.jar requires a relative path to out/host/linux-x86/lib64
+    # For some reason signapk.jar requires a relative path to out/soong/host/linux-x86/lib64
     os.chdir(os.environ['ANDROID_BUILD_TOP'])
-    run_command(['java', '-Djava.library.path=out/host/linux-x86/lib64',
-                 '-jar', 'out/host/linux-x86/framework/signapk.jar',
+    run_command(['java', '-Djava.library.path=out/soong/host/linux-x86/lib64',
+                 '-jar', 'out/soong/host/linux-x86/framework/signapk.jar',
                  'build/target/product/security/platform.x509.pem',
                  'build/target/product/security/platform.pk8',
                  unsigned_apk, signed_apk])
@@ -281,8 +281,8 @@
         sys.exit(1)
 
     if not os.path.isfile(os.path.join(
-            os.environ['ANDROID_BUILD_TOP'], 'out/host/linux-x86/framework/signapk.jar')):
-        print('out/host/linux-x86/framework/signapk.jar missing, please do an android build first')
+            os.environ['ANDROID_BUILD_TOP'], 'out/soong/host/linux-x86/framework/signapk.jar')):
+        print('out/soong/host/linux-x86/framework/signapk.jar missing, please do an android build first')
         sys.exit(1)
 
     package_name = get_package_name(args)
@@ -299,7 +299,7 @@
     print('Enabling...')
     # Enabling RROs sometimes fails shortly after installing them
     time.sleep(1)
-    run_command(['adb', 'shell', 'cmd', 'overlay', 'enable', '--user', '10', package_name])
+    run_command(['adb', 'shell', 'cmd', 'overlay', 'enable', '--user', 'current', package_name])
 
     print('Done!')
 
diff --git a/car-ui-lib/trailing-blank-line-hook.sh b/car-ui-lib/trailing-blank-line-hook.sh
new file mode 100755
index 0000000..a850d8e
--- /dev/null
+++ b/car-ui-lib/trailing-blank-line-hook.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+result=$(find car-ui-lib/ -type f \( -iname \*.java -o -iname \*.xml \) -a \( ! -wholename \*/.idea/\* \) \( ! -wholename \*/build/\* \) -print0 | xargs -0 -L1 bash -c 'test "$(tail -c 1 "$0")" && echo "No new line at end of $0"')
+if [ \( ! -z "$result" \)  -o \( $(echo "$result" | wc -l) -gt 1 \) ]
+then
+    echo "$result" && false;
+fi
diff --git a/car-uxr-client-lib/Android.bp b/car-uxr-client-lib/Android.bp
index 72751f3..c112734 100644
--- a/car-uxr-client-lib/Android.bp
+++ b/car-uxr-client-lib/Android.bp
@@ -31,6 +31,6 @@
     static_libs: [
         "androidx.recyclerview_recyclerview",
         "androidx.lifecycle_lifecycle-common-java8",
-        "car-ui-lib-bp",
+        "car-ui-lib",
     ],
 }
diff --git a/connected-device-lib/Android.bp b/connected-device-lib/Android.bp
index ca1de00..4383a20 100644
--- a/connected-device-lib/Android.bp
+++ b/connected-device-lib/Android.bp
@@ -21,13 +21,11 @@
 
     manifest: "AndroidManifest.xml",
 
-    resource_dirs: ["res"],
-
     optimize: {
         enabled: false,
     },
 
-    libs: ["android.car-stubs"],
+    libs: ["android.car-system-stubs"],
 
     static_libs: [
         "androidx.room_room-runtime",
@@ -37,9 +35,9 @@
     ],
 
     plugins: [
-        "car-androidx-room-compiler",
+        "androidx.room_room-compiler-plugin",
     ],
 
     sdk_version: "system_current",
-    min_sdk_version: "29",
+    min_sdk_version: "28",
 }
diff --git a/connected-device-lib/lib/kotlin-reflect-sources.jar b/connected-device-lib/lib/kotlin-reflect-sources.jar
deleted file mode 100644
index 917a722..0000000
--- a/connected-device-lib/lib/kotlin-reflect-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-reflect.jar b/connected-device-lib/lib/kotlin-reflect.jar
deleted file mode 100644
index e872351..0000000
--- a/connected-device-lib/lib/kotlin-reflect.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk7-sources.jar b/connected-device-lib/lib/kotlin-stdlib-jdk7-sources.jar
deleted file mode 100644
index 551568d..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk7-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk7.jar b/connected-device-lib/lib/kotlin-stdlib-jdk7.jar
deleted file mode 100644
index d80ae96..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk7.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk8-sources.jar b/connected-device-lib/lib/kotlin-stdlib-jdk8-sources.jar
deleted file mode 100644
index 3538660..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk8-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-jdk8.jar b/connected-device-lib/lib/kotlin-stdlib-jdk8.jar
deleted file mode 100644
index 08101a3..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-jdk8.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib-sources.jar b/connected-device-lib/lib/kotlin-stdlib-sources.jar
deleted file mode 100644
index 2bdaf9e..0000000
--- a/connected-device-lib/lib/kotlin-stdlib-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-stdlib.jar b/connected-device-lib/lib/kotlin-stdlib.jar
deleted file mode 100644
index 2bd7644..0000000
--- a/connected-device-lib/lib/kotlin-stdlib.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-test-sources.jar b/connected-device-lib/lib/kotlin-test-sources.jar
deleted file mode 100644
index 7bd21ce..0000000
--- a/connected-device-lib/lib/kotlin-test-sources.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/lib/kotlin-test.jar b/connected-device-lib/lib/kotlin-test.jar
deleted file mode 100644
index ede1d8b..0000000
--- a/connected-device-lib/lib/kotlin-test.jar
+++ /dev/null
Binary files differ
diff --git a/connected-device-lib/proto/ble_device_message.proto b/connected-device-lib/proto/ble_device_message.proto
deleted file mode 100644
index 581d6a0..0000000
--- a/connected-device-lib/proto/ble_device_message.proto
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.
- */
-
-syntax = "proto3";
-
-package com.android.car.connecteddevice.proto;
-
-import "packages/apps/Car/libs/connected-device-lib/proto/operation_type.proto";
-
-option java_package = "com.android.car.connecteddevice.BleStreamProtos";
-option java_outer_classname = "BleDeviceMessageProto";
-
-// A message between devices.
-message BleDeviceMessage {
-  // The operation that this message represents.
-  OperationType operation = 1;
-
-  // Whether the payload field is encrypted.
-  bool is_payload_encrypted = 2;
-
-  // Identifier of the intended recipient.
-  bytes recipient = 3;
-
-  // The bytes that represent the content for this message.
-  bytes payload = 4;
-}
\ No newline at end of file
diff --git a/connected-device-lib/proto/ble_packet.proto b/connected-device-lib/proto/ble_packet.proto
deleted file mode 100644
index c2ce262..0000000
--- a/connected-device-lib/proto/ble_packet.proto
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-
-syntax = "proto3";
-
-package com.android.car.connecteddevice.proto;
-
-option java_package = "com.android.car.connecteddevice.BleStreamProtos";
-option java_outer_classname = "BlePacketProto";
-
-// A packet across a BLE channel.
-message BlePacket {
-  // A 1-based packet number. The first message will have a value of "1" rather
-  // than "0".
-  fixed32 packet_number = 1;
-
-  // The total number of packets in the message stream.
-  int32 total_packets = 2;
-
-  // Id of message for reassembly on other side
-  int32 message_id = 3;
-
-  // The bytes that represent the message content for this packet.
-  bytes payload = 4;
-}
diff --git a/connected-device-lib/proto/ble_version_exchange.proto b/connected-device-lib/proto/ble_version_exchange.proto
deleted file mode 100644
index a7e8021..0000000
--- a/connected-device-lib/proto/ble_version_exchange.proto
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-
-syntax = "proto3";
-
-package com.android.car.connecteddevice.proto;
-
-option java_package = "com.android.car.connecteddevice.BleStreamProtos";
-option java_outer_classname = "VersionExchangeProto";
-
-message BleVersionExchange {
-  // Minimum supported protobuf version.
-  int32 minSupportedMessagingVersion = 1;
-
-  // Maximum supported protobuf version.
-  int32 maxSupportedMessagingVersion = 2;
-
-  // Minimum supported version of the encryption engine.
-  int32 minSupportedSecurityVersion = 3;
-
-  // Maximum supported version of the encryption engine.
-  int32 maxSupportedSecurityVersion = 4;
-}
diff --git a/connected-device-lib/proto/device_message.proto b/connected-device-lib/proto/device_message.proto
new file mode 100644
index 0000000..79b98df
--- /dev/null
+++ b/connected-device-lib/proto/device_message.proto
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package com.android.car.connecteddevice.proto;
+
+import "packages/apps/Car/libs/connected-device-lib/proto/operation_type.proto";
+
+option java_package = "com.android.car.connecteddevice.StreamProtos";
+option java_outer_classname = "DeviceMessageProto";
+
+// A message between devices.
+message Message {
+  // The operation that this message represents.
+  OperationType operation = 1;
+
+  // Whether the payload field is encrypted.
+  bool is_payload_encrypted = 2;
+
+  // Identifier of the intended recipient.
+  bytes recipient = 3;
+
+  // The bytes that represent the content for this message.
+  bytes payload = 4;
+}
\ No newline at end of file
diff --git a/connected-device-lib/proto/operation_type.proto b/connected-device-lib/proto/operation_type.proto
index d447ccc..3e38e27 100644
--- a/connected-device-lib/proto/operation_type.proto
+++ b/connected-device-lib/proto/operation_type.proto
@@ -18,8 +18,8 @@
 
 package com.android.car.connecteddevice.proto;
 
-option java_package = "com.android.car.connecteddevice.BleStreamProtos";
-option java_outer_classname = "BleOperationProto";
+option java_package = "com.android.car.connecteddevice.StreamProtos";
+option java_outer_classname = "OperationProto";
 
 // The different message types that indicate the content of the payload.
 //
diff --git a/connected-device-lib/proto/packet.proto b/connected-device-lib/proto/packet.proto
new file mode 100644
index 0000000..f761622
--- /dev/null
+++ b/connected-device-lib/proto/packet.proto
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package com.android.car.connecteddevice.proto;
+
+option java_package = "com.android.car.connecteddevice.StreamProtos";
+option java_outer_classname = "PacketProto";
+
+// A packet across a stream.
+message Packet {
+  // A 1-based packet number. The first message will have a value of "1" rather
+  // than "0".
+  fixed32 packet_number = 1;
+
+  // The total number of packets in the message stream.
+  int32 total_packets = 2;
+
+  // Id of message for reassembly on other side
+  int32 message_id = 3;
+
+  // The bytes that represent the message content for this packet.
+  bytes payload = 4;
+}
diff --git a/connected-device-lib/proto/version_exchange.proto b/connected-device-lib/proto/version_exchange.proto
new file mode 100644
index 0000000..a7c3493
--- /dev/null
+++ b/connected-device-lib/proto/version_exchange.proto
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package com.android.car.connecteddevice.proto;
+
+option java_package = "com.android.car.connecteddevice.StreamProtos";
+option java_outer_classname = "VersionExchangeProto";
+
+message VersionExchange {
+  // Minimum supported protobuf version.
+  int32 minSupportedMessagingVersion = 1;
+
+  // Maximum supported protobuf version.
+  int32 maxSupportedMessagingVersion = 2;
+
+  // Minimum supported version of the encryption engine.
+  int32 minSupportedSecurityVersion = 3;
+
+  // Maximum supported version of the encryption engine.
+  int32 maxSupportedSecurityVersion = 4;
+}
diff --git a/connected-device-lib/res/values/config.xml b/connected-device-lib/res/values/config.xml
index b090b92..c719462 100644
--- a/connected-device-lib/res/values/config.xml
+++ b/connected-device-lib/res/values/config.xml
@@ -16,22 +16,5 @@
   -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- These values must be modified for the connected device lib to function properly.-->
-    <string name="car_service_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
-    <string name="car_association_service_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
-    <string name="car_reconnect_service_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
-    <string name="car_reconnect_data_uuid" translatable="false">00000000-0000-0000-0000-000000000000</string>
-    <string name="car_bg_mask" translatable="false">00000000000000000000000000000000</string>
-
-    <string name="car_secure_read_uuid" translatable="false">5e2a68a6-27be-43f9-8d1e-4546976fabd7</string>
-    <string name="car_secure_write_uuid" translatable="false">5e2a68a5-27be-43f9-8d1e-4546976fabd7</string>
-
     <string name="connected_device_shared_preferences" translatable="false">com.android.car.connecteddevice</string>
-
-    <!--
-    This value must be between 23 and 185. 23 is the default MTU size for Android, and 185 is
-    the max MTU size supported for iOS. Verify your device and target companion devices support a
-    larger MTU prior to modifying.
-    -->
-    <integer name="car_default_mtu_size">23</integer>
 </resources>
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/AssociationCallback.java b/connected-device-lib/src/com/android/car/connecteddevice/AssociationCallback.java
index d628459..7697131 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/AssociationCallback.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/AssociationCallback.java
@@ -26,10 +26,10 @@
      *
      * @param deviceName The device name to identify the car.
      */
-    void onAssociationStartSuccess(@NonNull String deviceName);
+    default void onAssociationStartSuccess(String deviceName) {}
 
     /** Invoked when IHU failed to start advertising for association. */
-    void onAssociationStartFailure();
+    default void onAssociationStartFailure() {}
 
     /**
      * Invoked when a {@link ConnectedDeviceManager.DeviceError} has been encountered in attempting
@@ -37,7 +37,7 @@
      *
      * @param error The failure indication.
      */
-    void onAssociationError(@ConnectedDeviceManager.DeviceError int error);
+    default void onAssociationError(@ConnectedDeviceManager.DeviceError int error) {}
 
     /**
      * Invoked when a verification code needs to be displayed. The user needs to confirm, and
@@ -45,12 +45,12 @@
      *
      * @param code The verification code.
      */
-    void onVerificationCodeAvailable(@NonNull String code);
+    default void onVerificationCodeAvailable(@NonNull String code) {}
 
     /**
      * Invoked when the association has completed.
      *
      * @param deviceId The id of the newly associated device.
      */
-    void onAssociationCompleted(@NonNull String deviceId);
+    default void onAssociationCompleted(@NonNull String deviceId) {}
 }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java
index 6e8b6e0..b1397e2 100644
--- a/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java
+++ b/connected-device-lib/src/com/android/car/connecteddevice/ConnectedDeviceManager.java
@@ -22,21 +22,18 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
-import android.content.Context;
-
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.car.connecteddevice.ble.BleCentralManager;
-import com.android.car.connecteddevice.ble.BlePeripheralManager;
-import com.android.car.connecteddevice.ble.CarBleCentralManager;
-import com.android.car.connecteddevice.ble.CarBleManager;
-import com.android.car.connecteddevice.ble.CarBlePeripheralManager;
-import com.android.car.connecteddevice.ble.DeviceMessage;
+import com.android.car.connecteddevice.connection.CarBluetoothManager;
+import com.android.car.connecteddevice.connection.DeviceMessage;
 import com.android.car.connecteddevice.model.AssociatedDevice;
 import com.android.car.connecteddevice.model.ConnectedDevice;
+import com.android.car.connecteddevice.model.OobEligibleDevice;
+import com.android.car.connecteddevice.oob.BluetoothRfcommChannel;
+import com.android.car.connecteddevice.oob.OobChannel;
 import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
 import com.android.car.connecteddevice.storage.ConnectedDeviceStorage.AssociatedDeviceCallback;
 import com.android.car.connecteddevice.util.ByteUtils;
@@ -44,7 +41,6 @@
 import com.android.car.connecteddevice.util.ThreadSafeCallbacks;
 
 import java.lang.annotation.Retention;
-import java.time.Duration;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -73,15 +69,9 @@
     // Subtracting 2 bytes used by header, we have 8 bytes for device name.
     private static final int DEVICE_NAME_LENGTH_LIMIT = 8;
 
-    // The mac address randomly rotates every 7-15 minutes. To be safe, we will rotate our
-    // reconnect advertisement every 6 minutes to avoid crossing a rotation.
-    private static final Duration MAX_ADVERTISEMENT_DURATION = Duration.ofMinutes(6);
-
     private final ConnectedDeviceStorage mStorage;
 
-    private final CarBleCentralManager mCentralManager;
-
-    private final CarBlePeripheralManager mPeripheralManager;
+    private final CarBluetoothManager mCarBluetoothManager;
 
     private final ThreadSafeCallbacks<DeviceAssociationCallback> mDeviceAssociationCallbacks =
             new ThreadSafeCallbacks<>();
@@ -97,7 +87,7 @@
             new ConcurrentHashMap<>();
 
     // deviceId -> device
-    private final Map<String, InternalConnectedDevice> mConnectedDevices =
+    private final Map<String, ConnectedDevice> mConnectedDevices =
             new ConcurrentHashMap<>();
 
     // recipientId -> (deviceId -> message bytes)
@@ -120,6 +110,8 @@
 
     private MessageDeliveryDelegate mMessageDeliveryDelegate;
 
+    private OobChannel mOobChannel;
+
     @Retention(SOURCE)
     @IntDef({
             DEVICE_ERROR_INVALID_HANDSHAKE,
@@ -134,6 +126,7 @@
             DEVICE_ERROR_UNEXPECTED_DISCONNECTION
     })
     public @interface DeviceError {}
+
     public static final int DEVICE_ERROR_INVALID_HANDSHAKE = 0;
     public static final int DEVICE_ERROR_INVALID_MSG = 1;
     public static final int DEVICE_ERROR_INVALID_DEVICE_ID = 2;
@@ -145,53 +138,15 @@
     public static final int DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED = 8;
     public static final int DEVICE_ERROR_UNEXPECTED_DISCONNECTION = 9;
 
-    public ConnectedDeviceManager(@NonNull Context context) {
-        this(context, new ConnectedDeviceStorage(context), new BleCentralManager(context),
-                new BlePeripheralManager(context),
-                UUID.fromString(context.getString(R.string.car_service_uuid)),
-                UUID.fromString(context.getString(R.string.car_association_service_uuid)),
-                UUID.fromString(context.getString(R.string.car_reconnect_service_uuid)),
-                UUID.fromString(context.getString(R.string.car_reconnect_data_uuid)),
-                context.getString(R.string.car_bg_mask),
-                UUID.fromString(context.getString(R.string.car_secure_write_uuid)),
-                UUID.fromString(context.getString(R.string.car_secure_read_uuid)),
-                context.getResources().getInteger(R.integer.car_default_mtu_size));
-    }
-
-    private ConnectedDeviceManager(
-            @NonNull Context context,
-            @NonNull ConnectedDeviceStorage storage,
-            @NonNull BleCentralManager bleCentralManager,
-            @NonNull BlePeripheralManager blePeripheralManager,
-            @NonNull UUID serviceUuid,
-            @NonNull UUID associationServiceUuid,
-            @NonNull UUID reconnectServiceUuid,
-            @NonNull UUID reconnectDataUuid,
-            @NonNull String bgMask,
-            @NonNull UUID writeCharacteristicUuid,
-            @NonNull UUID readCharacteristicUuid,
-            int defaultMtuSize) {
-        this(storage,
-                new CarBleCentralManager(context, bleCentralManager, storage, serviceUuid, bgMask,
-                        writeCharacteristicUuid, readCharacteristicUuid),
-                new CarBlePeripheralManager(blePeripheralManager, storage, associationServiceUuid,
-                        reconnectServiceUuid, reconnectDataUuid, writeCharacteristicUuid,
-                        readCharacteristicUuid, MAX_ADVERTISEMENT_DURATION, defaultMtuSize));
-    }
-
-    @VisibleForTesting
-    ConnectedDeviceManager(
-            @NonNull ConnectedDeviceStorage storage,
-            @NonNull CarBleCentralManager centralManager,
-            @NonNull CarBlePeripheralManager peripheralManager) {
+    public ConnectedDeviceManager(@NonNull CarBluetoothManager carBluetoothManager,
+            @NonNull ConnectedDeviceStorage storage) {
         Executor callbackExecutor = Executors.newSingleThreadExecutor();
         mStorage = storage;
-        mCentralManager = centralManager;
-        mPeripheralManager = peripheralManager;
-        mCentralManager.registerCallback(generateCarBleCallback(centralManager), callbackExecutor);
-        mPeripheralManager.registerCallback(generateCarBleCallback(peripheralManager),
+        mCarBluetoothManager = carBluetoothManager;
+        mCarBluetoothManager.registerCallback(generateCarBleCallback(carBluetoothManager),
                 callbackExecutor);
         mStorage.setAssociatedDeviceCallback(mAssociatedDeviceCallback);
+        logd(TAG, "ConnectedDeviceManager created successfully.");
     }
 
     /**
@@ -205,29 +160,32 @@
             logd(TAG, "Starting ConnectedDeviceManager.");
             EventLog.onConnectedDeviceManagerStarted();
         }
-        // TODO (b/141312136) Start central manager
-        mPeripheralManager.start();
+        mCarBluetoothManager.start();
         connectToActiveUserDevice();
     }
 
     /** Reset internal processes and disconnect any active connections. */
     public void reset() {
         logd(TAG, "Resetting ConnectedDeviceManager.");
-        for (InternalConnectedDevice device : mConnectedDevices.values()) {
-            removeConnectedDevice(device.mConnectedDevice.getDeviceId(), device.mCarBleManager);
+        for (ConnectedDevice device : mConnectedDevices.values()) {
+            removeConnectedDevice(device.getDeviceId());
         }
-        mPeripheralManager.stop();
-        // TODO (b/141312136) Stop central manager
+        mCarBluetoothManager.stop();
         mIsConnectingToUserDevice.set(false);
+        if (mOobChannel != null) {
+            mOobChannel.interrupt();
+            mOobChannel = null;
+        }
+        mAssociationCallback = null;
     }
 
     /** Returns {@link List<ConnectedDevice>} of devices currently connected. */
     @NonNull
     public List<ConnectedDevice> getActiveUserConnectedDevices() {
         List<ConnectedDevice> activeUserConnectedDevices = new ArrayList<>();
-        for (InternalConnectedDevice device : mConnectedDevices.values()) {
-            if (device.mConnectedDevice.isAssociatedWithActiveUser()) {
-                activeUserConnectedDevices.add(device.mConnectedDevice);
+        for (ConnectedDevice device : mConnectedDevices.values()) {
+            if (device.isAssociatedWithActiveUser()) {
+                activeUserConnectedDevices.add(device);
             }
         }
         logd(TAG, "Returned " + activeUserConnectedDevices.size() + " active user devices.");
@@ -315,10 +273,9 @@
                 return;
             }
             EventLog.onStartDeviceSearchStarted();
-            mPeripheralManager.connectToDevice(UUID.fromString(userDevice.getDeviceId()));
+            mCarBluetoothManager.connectToDevice(UUID.fromString(userDevice.getDeviceId()));
         } catch (Exception e) {
             loge(TAG, "Exception while attempting connection with active user's device.", e);
-            mIsConnectingToUserDevice.set(false);
         }
     }
 
@@ -331,19 +288,57 @@
         mAssociationCallback = callback;
         Executors.defaultThreadFactory().newThread(() -> {
             logd(TAG, "Received request to start association.");
-            mPeripheralManager.startAssociation(getNameForAssociation(),
+            mCarBluetoothManager.startAssociation(getNameForAssociation(),
                     mInternalAssociationCallback);
         }).start();
     }
 
+    /**
+     * Start association with an out of band device.
+     *
+     * @param device   The out of band eligible device.
+     * @param callback Callback for association events.
+     */
+    public void startOutOfBandAssociation(@NonNull OobEligibleDevice device,
+            @NonNull AssociationCallback callback) {
+        logd(TAG, "Received request to start out of band association.");
+        mAssociationCallback = callback;
+        mOobChannel = new BluetoothRfcommChannel();
+        mOobChannel.completeOobDataExchange(device, new OobChannel.Callback() {
+            @Override
+            public void onOobExchangeSuccess() {
+                logd(TAG, "Out of band exchange succeeded. Proceeding to association with device.");
+                Executors.defaultThreadFactory().newThread(() -> {
+                    mCarBluetoothManager.startOutOfBandAssociation(
+                            getNameForAssociation(),
+                            mOobChannel, mInternalAssociationCallback);
+                }).start();
+            }
+
+            @Override
+            public void onOobExchangeFailure() {
+                loge(TAG, "Out of band exchange failed.");
+                mInternalAssociationCallback.onAssociationError(
+                        DEVICE_ERROR_INVALID_ENCRYPTION_KEY);
+                mOobChannel = null;
+                mAssociationCallback = null;
+            }
+        });
+    }
+
     /** Stop the association with any device. */
     public void stopAssociation(@NonNull AssociationCallback callback) {
         if (mAssociationCallback != callback) {
             logd(TAG, "Stop association called with unrecognized callback. Ignoring.");
             return;
         }
+        logd(TAG, "Stopping association.");
         mAssociationCallback = null;
-        mPeripheralManager.stopAssociation(mInternalAssociationCallback);
+        mCarBluetoothManager.stopAssociation();
+        if (mOobChannel != null) {
+            mOobChannel.interrupt();
+        }
+        mOobChannel = null;
     }
 
     /**
@@ -358,7 +353,7 @@
 
     /** Notify that the user has accepted a pairing code or any out-of-band confirmation. */
     public void notifyOutOfBandAccepted() {
-        mPeripheralManager.notifyOutOfBandAccepted();
+        mCarBluetoothManager.notifyOutOfBandAccepted();
     }
 
     /**
@@ -380,6 +375,7 @@
         logd(TAG, "enableAssociatedDeviceConnection() called on " + deviceId);
         mStorage.updateAssociatedDeviceConnectionEnabled(deviceId,
                 /* isConnectionEnabled= */ true);
+
         connectToActiveUserDevice();
     }
 
@@ -396,20 +392,20 @@
     }
 
     private void disconnectDevice(String deviceId) {
-        InternalConnectedDevice device = mConnectedDevices.get(deviceId);
+        ConnectedDevice device = mConnectedDevices.get(deviceId);
         if (device != null) {
-            device.mCarBleManager.disconnectDevice(deviceId);
-            removeConnectedDevice(deviceId, device.mCarBleManager);
+            mCarBluetoothManager.disconnectDevice(deviceId);
+            removeConnectedDevice(deviceId);
         }
     }
 
     /**
      * Register a callback for a specific device and recipient.
      *
-     * @param device {@link ConnectedDevice} to register triggers on.
+     * @param device      {@link ConnectedDevice} to register triggers on.
      * @param recipientId {@link UUID} to register as recipient of.
-     * @param callback {@link DeviceCallback} to register.
-     * @param executor {@link Executor} on which to execute callback.
+     * @param callback    {@link DeviceCallback} to register.
+     * @param executor    {@link Executor} on which to execute callback.
      */
     public void registerDeviceCallback(@NonNull ConnectedDevice device, @NonNull UUID recipientId,
             @NonNull DeviceCallback callback, @NonNull Executor executor) {
@@ -476,9 +472,9 @@
      * registered.
      *
      * @param recipientId Recipient's id
-     * @param deviceId Device id
+     * @param deviceId    Device id
      * @return The missed {@code byte[]} messages, or {@code null} if no messages were
-     *         missed.
+     * missed.
      */
     @Nullable
     private List<byte[]> popMissedMessages(@NonNull UUID recipientId, @NonNull String deviceId) {
@@ -493,9 +489,9 @@
     /**
      * Unregister callback from device events.
      *
-     * @param device {@link ConnectedDevice} callback was registered on.
+     * @param device      {@link ConnectedDevice} callback was registered on.
      * @param recipientId {@link UUID} callback was registered under.
-     * @param callback {@link DeviceCallback} to unregister.
+     * @param callback    {@link DeviceCallback} to unregister.
      */
     public void unregisterDeviceCallback(@NonNull ConnectedDevice device,
             @NonNull UUID recipientId, @NonNull DeviceCallback callback) {
@@ -521,9 +517,9 @@
     /**
      * Securely send message to a device.
      *
-     * @param device {@link ConnectedDevice} to send the message to.
+     * @param device      {@link ConnectedDevice} to send the message to.
      * @param recipientId Recipient {@link UUID}.
-     * @param message Message to send.
+     * @param message     Message to send.
      * @throws IllegalStateException Secure channel has not been established.
      */
     public void sendMessageSecurely(@NonNull ConnectedDevice device, @NonNull UUID recipientId,
@@ -534,9 +530,9 @@
     /**
      * Send an unencrypted message to a device.
      *
-     * @param device {@link ConnectedDevice} to send the message to.
+     * @param device      {@link ConnectedDevice} to send the message to.
      * @param recipientId Recipient {@link UUID}.
-     * @param message Message to send.
+     * @param message     Message to send.
      */
     public void sendMessageUnsecurely(@NonNull ConnectedDevice device, @NonNull UUID recipientId,
             @NonNull byte[] message) {
@@ -550,19 +546,19 @@
                 + " containing " + message.length + ". Message will be sent securely: "
                 + isEncrypted + ".");
 
-        InternalConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
+        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
         if (connectedDevice == null) {
             loge(TAG, "Attempted to send message to unknown device " + deviceId + ". Ignoring.");
             return;
         }
 
-        if (isEncrypted && !connectedDevice.mConnectedDevice.hasSecureChannel()) {
+        if (isEncrypted && !connectedDevice.hasSecureChannel()) {
             throw new IllegalStateException("Cannot send a message securely to device that has not "
                     + "established a secure channel.");
         }
 
-        connectedDevice.mCarBleManager.sendMessage(deviceId,
-                new DeviceMessage(recipientId, isEncrypted, message));
+        mCarBluetoothManager.sendMessage(deviceId, new DeviceMessage(recipientId, isEncrypted,
+                message));
     }
 
     private boolean isRecipientBlacklisted(UUID recipientId) {
@@ -583,11 +579,11 @@
             return;
         }
 
-        InternalConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
+        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
         if (connectedDevice != null) {
             recipientCallbacks.get(recipientId).invoke(
                     callback ->
-                            callback.onDeviceError(connectedDevice.mConnectedDevice,
+                            callback.onDeviceError(connectedDevice,
                                     DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED)
             );
         }
@@ -597,7 +593,7 @@
     }
 
     @VisibleForTesting
-    void addConnectedDevice(@NonNull String deviceId, @NonNull CarBleManager bleManager) {
+    void addConnectedDevice(@NonNull String deviceId) {
         if (mConnectedDevices.containsKey(deviceId)) {
             // Device already connected. No-op until secure channel established.
             return;
@@ -610,30 +606,24 @@
                 /* hasSecureChannel= */ false
         );
 
-        mConnectedDevices.put(deviceId, new InternalConnectedDevice(connectedDevice, bleManager));
+        mConnectedDevices.put(deviceId, connectedDevice);
         invokeConnectionCallbacks(connectedDevice.isAssociatedWithActiveUser(),
                 callback -> callback.onDeviceConnected(connectedDevice));
     }
 
     @VisibleForTesting
-    void removeConnectedDevice(@NonNull String deviceId, @NonNull CarBleManager bleManager) {
-        logd(TAG, "Device " + deviceId + " disconnected from manager " + bleManager);
-        InternalConnectedDevice connectedDevice = getConnectedDeviceForManager(deviceId,
-                bleManager);
-
-        // If disconnect happened on peripheral, open for future requests to connect.
-        if (bleManager == mPeripheralManager) {
-            mIsConnectingToUserDevice.set(false);
-        }
-
+    void removeConnectedDevice(@NonNull String deviceId) {
+        logd(TAG, "Device " + deviceId + " disconnected.");
+        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
+        mIsConnectingToUserDevice.set(false);
         if (connectedDevice == null) {
             return;
         }
 
         mConnectedDevices.remove(deviceId);
-        boolean isAssociated = connectedDevice.mConnectedDevice.isAssociatedWithActiveUser();
+        boolean isAssociated = connectedDevice.isAssociatedWithActiveUser();
         invokeConnectionCallbacks(isAssociated,
-                callback -> callback.onDeviceDisconnected(connectedDevice.mConnectedDevice));
+                callback -> callback.onDeviceDisconnected(connectedDevice));
 
         if (isAssociated || mConnectedDevices.isEmpty()) {
             // Try to regain connection to active user's device.
@@ -642,25 +632,23 @@
     }
 
     @VisibleForTesting
-    void onSecureChannelEstablished(@NonNull String deviceId,
-            @NonNull CarBleManager bleManager) {
+    void onSecureChannelEstablished(@NonNull String deviceId) {
         if (mConnectedDevices.get(deviceId) == null) {
             loge(TAG, "Secure channel established on unknown device " + deviceId + ".");
             return;
         }
-        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId).mConnectedDevice;
+        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
         ConnectedDevice updatedConnectedDevice = new ConnectedDevice(connectedDevice.getDeviceId(),
                 connectedDevice.getDeviceName(), connectedDevice.isAssociatedWithActiveUser(),
                 /* hasSecureChannel= */ true);
 
-        boolean notifyCallbacks = getConnectedDeviceForManager(deviceId, bleManager) != null;
+        boolean notifyCallbacks = mConnectedDevices.get(deviceId) != null;
 
         // TODO (b/143088482) Implement interrupt
         // Ignore if central already holds the active device connection and interrupt the
         // connection.
 
-        mConnectedDevices.put(deviceId,
-                new InternalConnectedDevice(updatedConnectedDevice, bleManager));
+        mConnectedDevices.put(deviceId, updatedConnectedDevice);
         logd(TAG, "Secure channel established to " + deviceId + " . Notifying callbacks: "
                 + notifyCallbacks + ".");
         if (notifyCallbacks) {
@@ -675,7 +663,7 @@
                 + message.getRecipient() + " containing " + message.getMessage().length
                 + " bytes.");
 
-        InternalConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
+        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
         if (connectedDevice == null) {
             logw(TAG, "Received message from unknown device " + deviceId + "or to unknown "
                     + "recipient " + message.getRecipient() + ".");
@@ -683,8 +671,7 @@
         }
 
         if (mMessageDeliveryDelegate != null
-                && !mMessageDeliveryDelegate.shouldDeliverMessageForDevice(
-                        connectedDevice.mConnectedDevice)) {
+                && !mMessageDeliveryDelegate.shouldDeliverMessageForDevice(connectedDevice)) {
             logw(TAG, "The message delegate has rejected this message. It will not be "
                     + "delivered to the intended recipient.");
             return;
@@ -705,39 +692,36 @@
         }
 
         recipientCallbacks.invoke(
-                callback -> callback.onMessageReceived(connectedDevice.mConnectedDevice,
-                        message.getMessage()));
+                callback -> callback.onMessageReceived(connectedDevice, message.getMessage()));
     }
 
     @VisibleForTesting
     void deviceErrorOccurred(@NonNull String deviceId) {
-        InternalConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
+        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
         if (connectedDevice == null) {
             logw(TAG, "Failed to establish secure channel on unknown device " + deviceId + ".");
             return;
         }
 
-        notifyAllDeviceCallbacks(deviceId,
-                callback -> callback.onDeviceError(connectedDevice.mConnectedDevice,
+        notifyAllDeviceCallbacks(deviceId, callback -> callback.onDeviceError(connectedDevice,
                         DEVICE_ERROR_INVALID_SECURITY_KEY));
     }
 
     @VisibleForTesting
     void onAssociationCompleted(@NonNull String deviceId) {
-        InternalConnectedDevice connectedDevice =
-                getConnectedDeviceForManager(deviceId, mPeripheralManager);
+        ConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
         if (connectedDevice == null) {
             return;
         }
 
         // The previous device is now obsolete and should be replaced with a new one properly
         // reflecting the state of belonging to the active user and notify features.
-        if (connectedDevice.mConnectedDevice.isAssociatedWithActiveUser()) {
+        if (connectedDevice.isAssociatedWithActiveUser()) {
             // Device was already marked as belonging to active user. No need to reissue callbacks.
             return;
         }
-        removeConnectedDevice(deviceId, mPeripheralManager);
-        addConnectedDevice(deviceId, mPeripheralManager);
+        removeConnectedDevice(deviceId);
+        addConnectedDevice(deviceId);
     }
 
     @NonNull
@@ -745,17 +729,6 @@
         return mStorage.getActiveUserAssociatedDeviceIds();
     }
 
-    @Nullable
-    private InternalConnectedDevice getConnectedDeviceForManager(@NonNull String deviceId,
-            @NonNull CarBleManager bleManager) {
-        InternalConnectedDevice connectedDevice = mConnectedDevices.get(deviceId);
-        if (connectedDevice != null && connectedDevice.mCarBleManager == bleManager) {
-            return connectedDevice;
-        }
-
-        return null;
-    }
-
     private void invokeConnectionCallbacks(boolean belongsToActiveUser,
             @NonNull Consumer<ConnectionCallback> notification) {
         logd(TAG, "Notifying connection callbacks for device belonging to active user "
@@ -794,23 +767,24 @@
     }
 
     @NonNull
-    private CarBleManager.Callback generateCarBleCallback(@NonNull CarBleManager carBleManager) {
-        return new CarBleManager.Callback() {
+    private CarBluetoothManager.Callback generateCarBleCallback(
+            @NonNull CarBluetoothManager carBluetoothManager) {
+        return new CarBluetoothManager.Callback() {
             @Override
             public void onDeviceConnected(String deviceId) {
                 EventLog.onDeviceIdReceived();
-                addConnectedDevice(deviceId, carBleManager);
+                addConnectedDevice(deviceId);
             }
 
             @Override
             public void onDeviceDisconnected(String deviceId) {
-                removeConnectedDevice(deviceId, carBleManager);
+                removeConnectedDevice(deviceId);
             }
 
             @Override
             public void onSecureChannelEstablished(String deviceId) {
                 EventLog.onSecureChannelEstablished();
-                ConnectedDeviceManager.this.onSecureChannelEstablished(deviceId, carBleManager);
+                ConnectedDeviceManager.this.onSecureChannelEstablished(deviceId);
             }
 
             @Override
@@ -865,26 +839,25 @@
 
     private final AssociatedDeviceCallback mAssociatedDeviceCallback =
             new AssociatedDeviceCallback() {
-        @Override
-        public void onAssociatedDeviceAdded(
-                AssociatedDevice device) {
-            mDeviceAssociationCallbacks.invoke(callback ->
-                    callback.onAssociatedDeviceAdded(device));
-        }
+                @Override
+                public void onAssociatedDeviceAdded(AssociatedDevice device) {
+                    mDeviceAssociationCallbacks.invoke(callback ->
+                            callback.onAssociatedDeviceAdded(device));
+                }
 
-        @Override
-        public void onAssociatedDeviceRemoved(AssociatedDevice device) {
-            mDeviceAssociationCallbacks.invoke(callback ->
-                    callback.onAssociatedDeviceRemoved(device));
-            logd(TAG, "Successfully removed associated device " + device + ".");
-        }
+                @Override
+                public void onAssociatedDeviceRemoved(AssociatedDevice device) {
+                    mDeviceAssociationCallbacks.invoke(callback ->
+                            callback.onAssociatedDeviceRemoved(device));
+                    logd(TAG, "Successfully removed associated device " + device + ".");
+                }
 
-        @Override
-        public void onAssociatedDeviceUpdated(AssociatedDevice device) {
-            mDeviceAssociationCallbacks.invoke(callback ->
-                    callback.onAssociatedDeviceUpdated(device));
-        }
-    };
+                @Override
+                public void onAssociatedDeviceUpdated(AssociatedDevice device) {
+                    mDeviceAssociationCallbacks.invoke(callback ->
+                            callback.onAssociatedDeviceUpdated(device));
+                }
+            };
 
     /** Callback for triggered connection events from {@link ConnectedDeviceManager}. */
     public interface ConnectionCallback {
@@ -929,15 +902,4 @@
         /** Indicate whether a message should be delivered for the specified device. */
         boolean shouldDeliverMessageForDevice(@NonNull ConnectedDevice device);
     }
-
-    private static class InternalConnectedDevice {
-        private final ConnectedDevice mConnectedDevice;
-        private final CarBleManager mCarBleManager;
-
-        InternalConnectedDevice(@NonNull ConnectedDevice connectedDevice,
-                @NonNull CarBleManager carBleManager) {
-            mConnectedDevice = connectedDevice;
-            mCarBleManager = carBleManager;
-        }
-    }
 }
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/AssociationSecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/AssociationSecureChannel.java
deleted file mode 100644
index f397922..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/AssociationSecureChannel.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.connecteddevice.ble;
-
-import static android.car.encryptionrunner.EncryptionRunnerFactory.EncryptionRunnerType;
-import static android.car.encryptionrunner.EncryptionRunnerFactory.newRunner;
-import static android.car.encryptionrunner.HandshakeMessage.HandshakeState;
-
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-
-import android.car.encryptionrunner.EncryptionRunner;
-import android.car.encryptionrunner.HandshakeException;
-import android.car.encryptionrunner.HandshakeMessage;
-import android.car.encryptionrunner.Key;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-import com.android.car.connecteddevice.util.ByteUtils;
-
-import java.security.InvalidParameterException;
-import java.util.Arrays;
-import java.util.UUID;
-
-/**
- * A secure channel established with the association flow.
- */
-class AssociationSecureChannel extends SecureBleChannel {
-
-    private static final String TAG = "AssociationSecureChannel";
-
-    private static final int DEVICE_ID_BYTES = 16;
-
-    private final ConnectedDeviceStorage mStorage;
-
-    private ShowVerificationCodeListener mShowVerificationCodeListener;
-
-    @HandshakeState
-    private int mState = HandshakeState.UNKNOWN;
-
-    private Key mPendingKey;
-
-    private String mDeviceId;
-
-    AssociationSecureChannel(BleDeviceMessageStream stream, ConnectedDeviceStorage storage) {
-        this(stream, storage, newRunner(EncryptionRunnerType.UKEY2));
-    }
-
-    AssociationSecureChannel(BleDeviceMessageStream stream, ConnectedDeviceStorage storage,
-            EncryptionRunner encryptionRunner) {
-        super(stream, encryptionRunner);
-        encryptionRunner.setIsReconnect(false);
-        mStorage = storage;
-    }
-
-    @Override
-    void processHandshake(@NonNull byte[] message) throws HandshakeException {
-        switch (mState) {
-            case HandshakeState.UNKNOWN:
-                processHandshakeUnknown(message);
-                break;
-            case HandshakeState.IN_PROGRESS:
-                processHandshakeInProgress(message);
-                break;
-            case HandshakeState.FINISHED:
-                processHandshakeDeviceIdAndSecret(message);
-                break;
-            default:
-                loge(TAG, "Encountered unexpected handshake state: " + mState + ".");
-                notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-        }
-    }
-
-    private void processHandshakeUnknown(@NonNull byte[] message) throws HandshakeException {
-        logd(TAG, "Responding to handshake init request.");
-        HandshakeMessage handshakeMessage = getEncryptionRunner().respondToInitRequest(message);
-        mState = handshakeMessage.getHandshakeState();
-        sendHandshakeMessage(handshakeMessage.getNextMessage(), /* isEncrypted= */ false);
-    }
-
-    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
-        logd(TAG, "Continuing handshake.");
-        HandshakeMessage handshakeMessage = getEncryptionRunner().continueHandshake(message);
-        mState = handshakeMessage.getHandshakeState();
-
-        if (mState != HandshakeState.VERIFICATION_NEEDED) {
-            loge(TAG, "processHandshakeInProgress: Encountered unexpected handshake state: "
-                    + mState + ".");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-            return;
-        }
-
-        String code = handshakeMessage.getVerificationCode();
-        if (code == null) {
-            loge(TAG, "Unable to get verification code.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
-            return;
-        }
-
-        if (mShowVerificationCodeListener == null) {
-            loge(TAG, "No verification code listener has been set. Unable to display verification "
-                    + "code to user.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-            return;
-        }
-
-        logd(TAG, "Showing pairing code: " + code);
-        mShowVerificationCodeListener.showVerificationCode(code);
-    }
-
-    private void processHandshakeDeviceIdAndSecret(@NonNull byte[] message) {
-        UUID deviceId = ByteUtils.bytesToUUID(Arrays.copyOf(message, DEVICE_ID_BYTES));
-        if (deviceId == null) {
-            loge(TAG, "Received invalid device id. Aborting.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_DEVICE_ID);
-            return;
-        }
-        mDeviceId = deviceId.toString();
-        notifyCallback(callback -> callback.onDeviceIdReceived(mDeviceId));
-
-        mStorage.saveEncryptionKey(mDeviceId, mPendingKey.asBytes());
-        mPendingKey = null;
-        try {
-            mStorage.saveChallengeSecret(mDeviceId,
-                    Arrays.copyOfRange(message, DEVICE_ID_BYTES, message.length));
-        } catch (InvalidParameterException e) {
-            loge(TAG, "Error saving challenge secret.", e);
-            notifySecureChannelFailure(CHANNEL_ERROR_STORAGE_ERROR);
-            return;
-        }
-
-        notifyCallback(Callback::onSecureChannelEstablished);
-    }
-
-    /** Set the listener that notifies to show verification code. {@code null} to clear. */
-    void setShowVerificationCodeListener(@Nullable ShowVerificationCodeListener listener) {
-        mShowVerificationCodeListener = listener;
-    }
-
-    @VisibleForTesting
-    @Nullable
-    ShowVerificationCodeListener getShowVerificationCodeListener() {
-        return mShowVerificationCodeListener;
-    }
-
-    /**
-     * Called by the client to notify that the user has accepted a pairing code or any out-of-band
-     * confirmation, and send confirmation signals to remote bluetooth device.
-     */
-    void notifyOutOfBandAccepted() {
-        HandshakeMessage message;
-        try {
-            message = getEncryptionRunner().verifyPin();
-        } catch (HandshakeException e) {
-            loge(TAG, "Error during PIN verification", e);
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
-            return;
-        }
-        if (message.getHandshakeState() != HandshakeState.FINISHED) {
-            loge(TAG, "Handshake not finished after calling verify PIN. Instead got "
-                    + "state: " + message.getHandshakeState() + ".");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-            return;
-        }
-
-        Key localKey = message.getKey();
-        if (localKey == null) {
-            loge(TAG, "Unable to finish association, generated key is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
-            return;
-        }
-        mState = message.getHandshakeState();
-        setEncryptionKey(localKey);
-        mPendingKey = localKey;
-        logd(TAG, "Pairing code successfully verified.");
-        sendUniqueIdToClient();
-    }
-
-    private void sendUniqueIdToClient() {
-        UUID uniqueId = mStorage.getUniqueId();
-        DeviceMessage deviceMessage = new DeviceMessage(/* recipient= */ null,
-                /* isMessageEncrypted= */ true, ByteUtils.uuidToBytes(uniqueId));
-        logd(TAG, "Sending car's device id of " + uniqueId + " to device.");
-        sendHandshakeMessage(ByteUtils.uuidToBytes(uniqueId), /* isEncrypted= */ true);
-    }
-
-    /** Listener that will be invoked to display verification code. */
-    interface ShowVerificationCodeListener {
-        /**
-         * Invoke when a verification need to be displayed during device association.
-         *
-         * @param code The verification code to show.
-         */
-        void showVerificationCode(@NonNull String code);
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/BleCentralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/BleCentralManager.java
deleted file mode 100644
index 7a01366..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/BleCentralManager.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-import static com.android.car.connecteddevice.util.SafeLog.logw;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.le.BluetoothLeScanner;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Handler;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Class that manages BLE scanning operations.
- */
-public class BleCentralManager {
-
-    private static final String TAG = "BleCentralManager";
-
-    private static final int RETRY_LIMIT = 5;
-
-    private static final int RETRY_INTERVAL_MS = 1000;
-
-    private final Context mContext;
-
-    private final Handler mHandler;
-
-    private List<ScanFilter> mScanFilters;
-
-    private ScanSettings mScanSettings;
-
-    private ScanCallback mScanCallback;
-
-    private BluetoothLeScanner mScanner;
-
-    private int mScannerStartCount = 0;
-
-    private AtomicInteger mScannerState = new AtomicInteger(STOPPED);
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            STOPPED,
-            STARTED,
-            SCANNING
-    })
-    private @interface ScannerState {}
-    private static final int STOPPED = 0;
-    private static final int STARTED = 1;
-    private static final int SCANNING = 2;
-
-    public BleCentralManager(@NonNull Context context) {
-        mContext = context;
-        mHandler = new Handler(context.getMainLooper());
-    }
-
-    /**
-     * Start the BLE scanning process.
-     *
-     * @param filters Optional list of {@link ScanFilter}s to apply to scan results.
-     * @param settings {@link ScanSettings} to apply to scanner.
-     * @param callback {@link ScanCallback} for scan events.
-     */
-    public void startScanning(@Nullable List<ScanFilter> filters, @NonNull ScanSettings settings,
-            @NonNull ScanCallback callback) {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
-            loge(TAG, "Attempted start scanning, but system does not support BLE. Ignoring");
-            return;
-        }
-        logd(TAG, "Request received to start scanning.");
-        mScannerStartCount = 0;
-        mScanFilters = filters;
-        mScanSettings = settings;
-        mScanCallback = callback;
-        updateScannerState(STARTED);
-        startScanningInternally();
-    }
-
-    /** Stop the scanner */
-    public void stopScanning() {
-        logd(TAG, "Attempting to stop scanning");
-        if (mScanner != null) {
-            mScanner.stopScan(mInternalScanCallback);
-        }
-        mScanCallback = null;
-        updateScannerState(STOPPED);
-    }
-
-    /** Returns {@code true} if currently scanning, {@code false} otherwise. */
-    public boolean isScanning() {
-        return mScannerState.get() == SCANNING;
-    }
-
-    /** Clean up the scanning process. */
-    public void cleanup() {
-        if (isScanning()) {
-            stopScanning();
-        }
-    }
-
-    private void startScanningInternally() {
-        logd(TAG, "Attempting to start scanning");
-        if (mScanner == null && BluetoothAdapter.getDefaultAdapter() != null) {
-            mScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
-        }
-        if (mScanner != null) {
-            mScanner.startScan(mScanFilters, mScanSettings, mInternalScanCallback);
-            updateScannerState(SCANNING);
-        } else {
-            mHandler.postDelayed(() -> {
-                // Keep trying
-                logd(TAG, "Scanner unavailable. Trying again.");
-                startScanningInternally();
-            }, RETRY_INTERVAL_MS);
-        }
-    }
-
-    private void updateScannerState(@ScannerState int newState) {
-        mScannerState.set(newState);
-    }
-
-    private final ScanCallback mInternalScanCallback = new ScanCallback() {
-        @Override
-        public void onScanResult(int callbackType, ScanResult result) {
-            if (mScanCallback != null) {
-                mScanCallback.onScanResult(callbackType, result);
-            }
-        }
-
-        @Override
-        public void onBatchScanResults(List<ScanResult> results) {
-            logd(TAG, "Batch scan found " + results.size() + " results.");
-            if (mScanCallback != null) {
-                mScanCallback.onBatchScanResults(results);
-            }
-        }
-
-        @Override
-        public void onScanFailed(int errorCode) {
-            if (mScannerStartCount >= RETRY_LIMIT) {
-                loge(TAG, "Cannot start BLE Scanner. Scanning Retry count: "
-                        + mScannerStartCount);
-                if (mScanCallback != null) {
-                    mScanCallback.onScanFailed(errorCode);
-                }
-                return;
-            }
-
-            mScannerStartCount++;
-            logw(TAG, "BLE Scanner failed to start. Error: "
-                    + errorCode
-                    + " Retry: "
-                    + mScannerStartCount);
-            switch(errorCode) {
-                case SCAN_FAILED_ALREADY_STARTED:
-                    // Scanner already started. Do nothing.
-                    break;
-                case SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
-                case SCAN_FAILED_INTERNAL_ERROR:
-                    mHandler.postDelayed(BleCentralManager.this::startScanningInternally,
-                            RETRY_INTERVAL_MS);
-                    break;
-                default:
-                    // Ignore other codes.
-            }
-        }
-    };
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/BleDeviceMessageStream.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/BleDeviceMessageStream.java
deleted file mode 100644
index 3e19d41..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/BleDeviceMessageStream.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
-import static com.android.car.connecteddevice.BleStreamProtos.BlePacketProto.BlePacket;
-import static com.android.car.connecteddevice.BleStreamProtos.VersionExchangeProto.BleVersionExchange;
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-import static com.android.car.connecteddevice.util.SafeLog.logw;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.os.Handler;
-import android.os.Looper;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.connecteddevice.BleStreamProtos.BleDeviceMessageProto.BleDeviceMessage;
-import com.android.car.connecteddevice.util.ByteUtils;
-import com.android.car.protobuf.ByteString;
-import com.android.car.protobuf.InvalidProtocolBufferException;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayDeque;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-/** BLE message stream to a device. */
-class BleDeviceMessageStream {
-
-    private static final String TAG = "BleDeviceMessageStream";
-
-    // Only version 2 of the messaging and version 2 of the security supported.
-    private static final int MESSAGING_VERSION = 2;
-    private static final int SECURITY_VERSION = 2;
-
-    /*
-     * During bandwidth testing, it was discovered that allowing the stream to send as fast as it
-     * can blocked outgoing notifications from being received by the connected device. Adding a
-     * throttle to the outgoing messages alleviated this block and allowed both sides to
-     * send/receive in parallel successfully.
-     */
-    private static final long THROTTLE_DEFAULT_MS = 10L;
-    private static final long THROTTLE_WAIT_MS = 75L;
-
-    private final ArrayDeque<BlePacket> mPacketQueue = new ArrayDeque<>();
-
-    private final Map<Integer, ByteArrayOutputStream> mPendingData = new HashMap<>();
-
-    // messageId -> nextExpectedPacketNumber
-    private final Map<Integer, Integer> mPendingPacketNumber = new HashMap<>();
-
-    private final MessageIdGenerator mMessageIdGenerator = new MessageIdGenerator();
-
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
-
-    private final AtomicBoolean mIsVersionExchanged = new AtomicBoolean(false);
-
-    private final AtomicBoolean mIsSendingInProgress = new AtomicBoolean(false);
-
-    private final AtomicLong mThrottleDelay = new AtomicLong(THROTTLE_DEFAULT_MS);
-
-    private final BlePeripheralManager mBlePeripheralManager;
-
-    private final BluetoothDevice mDevice;
-
-    private final BluetoothGattCharacteristic mWriteCharacteristic;
-
-    private final BluetoothGattCharacteristic mReadCharacteristic;
-
-    private MessageReceivedListener mMessageReceivedListener;
-
-    private MessageReceivedErrorListener mMessageReceivedErrorListener;
-
-    private int mMaxWriteSize;
-
-    BleDeviceMessageStream(@NonNull BlePeripheralManager blePeripheralManager,
-            @NonNull BluetoothDevice device,
-            @NonNull BluetoothGattCharacteristic writeCharacteristic,
-            @NonNull BluetoothGattCharacteristic readCharacteristic,
-            int defaultMaxWriteSize) {
-        mBlePeripheralManager = blePeripheralManager;
-        mDevice = device;
-        mWriteCharacteristic = writeCharacteristic;
-        mReadCharacteristic = readCharacteristic;
-        mBlePeripheralManager.addOnCharacteristicWriteListener(this::onCharacteristicWrite);
-        mBlePeripheralManager.addOnCharacteristicReadListener(this::onCharacteristicRead);
-        mMaxWriteSize = defaultMaxWriteSize;
-    }
-
-    /**
-     * Writes the given message to the write characteristic of this stream with operation type
-     * {@code CLIENT_MESSAGE}.
-     *
-     * This method will handle the chunking of messages based on the max write size.
-     *
-     * @param deviceMessage The data object contains recipient, isPayloadEncrypted and message.
-     */
-    void writeMessage(@NonNull DeviceMessage deviceMessage) {
-        writeMessage(deviceMessage, OperationType.CLIENT_MESSAGE);
-    }
-
-    /**
-     * Writes the given message to the write characteristic of this stream.
-     *
-     * This method will handle the chunking of messages based on the max write size. If it is
-     * a handshake message, the message recipient should be {@code null} and it cannot be
-     * encrypted.
-     *
-     * @param deviceMessage The data object contains recipient, isPayloadEncrypted and message.
-     * @param operationType The {@link OperationType} of this message.
-     */
-    void writeMessage(@NonNull DeviceMessage deviceMessage, OperationType operationType) {
-        logd(TAG, "Writing message with " + deviceMessage.getMessage().length + " bytes to device: "
-                + mDevice.getAddress() + ".");
-        BleDeviceMessage.Builder builder = BleDeviceMessage.newBuilder()
-                .setOperation(operationType)
-                .setIsPayloadEncrypted(deviceMessage.isMessageEncrypted())
-                .setPayload(ByteString.copyFrom(deviceMessage.getMessage()));
-
-        UUID recipient = deviceMessage.getRecipient();
-        if (recipient != null) {
-            builder.setRecipient(ByteString.copyFrom(ByteUtils.uuidToBytes(recipient)));
-        }
-
-        BleDeviceMessage bleDeviceMessage = builder.build();
-        byte[] rawBytes = bleDeviceMessage.toByteArray();
-        List<BlePacket> blePackets;
-        try {
-            blePackets = BlePacketFactory.makeBlePackets(rawBytes, mMessageIdGenerator.next(),
-                    mMaxWriteSize);
-        } catch (BlePacketFactoryException e) {
-            loge(TAG, "Error while creating message packets.", e);
-            return;
-        }
-        mPacketQueue.addAll(blePackets);
-        writeNextMessageInQueue();
-    }
-
-    private void writeNextMessageInQueue() {
-        mHandler.postDelayed(() -> {
-            if (mPacketQueue.isEmpty()) {
-                logd(TAG, "No more packets to send.");
-                return;
-            }
-            boolean isLockAcquired = mIsSendingInProgress.compareAndSet(false, true);
-            if (!isLockAcquired) {
-                logd(TAG, "Unable to send packet at this time.");
-                return;
-            }
-
-            BlePacket packet = mPacketQueue.remove();
-            logd(TAG, "Writing packet " + packet.getPacketNumber() + " of "
-                    + packet.getTotalPackets() + " for " + packet.getMessageId() + ".");
-            mWriteCharacteristic.setValue(packet.toByteArray());
-            mBlePeripheralManager.notifyCharacteristicChanged(mDevice, mWriteCharacteristic,
-                    /* confirm= */ false);
-        }, mThrottleDelay.get());
-    }
-
-    private void onCharacteristicRead(@NonNull BluetoothDevice device) {
-        if (!mDevice.equals(device)) {
-            logw(TAG, "Received a read notification from a device (" + device.getAddress()
-                    + ") that is not the expected device (" + mDevice.getAddress() + ") registered "
-                    + "to this stream. Ignoring.");
-            return;
-        }
-
-        logd(TAG, "Releasing lock on characteristic.");
-        mIsSendingInProgress.set(false);
-        writeNextMessageInQueue();
-    }
-
-    private void onCharacteristicWrite(@NonNull BluetoothDevice device,
-            @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
-        logd(TAG, "Received a message from a device (" + device.getAddress() + ").");
-        if (!mDevice.equals(device)) {
-            logw(TAG, "Received a message from a device (" + device.getAddress() + ") that is not "
-                    + "the expected device (" + mDevice.getAddress() + ") registered to this "
-                    + "stream. Ignoring.");
-            return;
-        }
-
-        if (!characteristic.getUuid().equals(mReadCharacteristic.getUuid())) {
-            logw(TAG, "Received a write to a characteristic (" + characteristic.getUuid() + ") that"
-                    + " is not the expected UUID (" + mReadCharacteristic.getUuid() + "). "
-                    + "Ignoring.");
-            return;
-        }
-
-        if (!mIsVersionExchanged.get()) {
-            processVersionExchange(device, value);
-            return;
-        }
-
-        BlePacket packet;
-        try {
-            packet = BlePacket.parseFrom(value);
-        } catch (InvalidProtocolBufferException e) {
-            loge(TAG, "Can not parse Ble packet from client.", e);
-            if (mMessageReceivedErrorListener != null) {
-                mMessageReceivedErrorListener.onMessageReceivedError(e);
-            }
-            return;
-        }
-        processPacket(packet);
-    }
-
-    private void processVersionExchange(@NonNull BluetoothDevice device, @NonNull byte[] value) {
-        BleVersionExchange versionExchange;
-        try {
-            versionExchange = BleVersionExchange.parseFrom(value);
-        } catch (InvalidProtocolBufferException e) {
-            loge(TAG, "Could not parse version exchange message", e);
-            if (mMessageReceivedErrorListener != null) {
-                mMessageReceivedErrorListener.onMessageReceivedError(e);
-            }
-            return;
-        }
-        int minMessagingVersion = versionExchange.getMinSupportedMessagingVersion();
-        int maxMessagingVersion = versionExchange.getMaxSupportedMessagingVersion();
-        int minSecurityVersion = versionExchange.getMinSupportedSecurityVersion();
-        int maxSecurityVersion = versionExchange.getMaxSupportedSecurityVersion();
-        if (minMessagingVersion > MESSAGING_VERSION || maxMessagingVersion < MESSAGING_VERSION
-                || minSecurityVersion > SECURITY_VERSION || maxSecurityVersion < SECURITY_VERSION) {
-            loge(TAG, "Unsupported message version for min " + minMessagingVersion + " and max "
-                    + maxMessagingVersion + " or security version for " + minSecurityVersion
-                    + " and max " + maxSecurityVersion + ".");
-            if (mMessageReceivedErrorListener != null) {
-                mMessageReceivedErrorListener.onMessageReceivedError(
-                        new IllegalStateException("Unsupported version."));
-            }
-            return;
-        }
-
-        BleVersionExchange headunitVersion = BleVersionExchange.newBuilder()
-                .setMinSupportedMessagingVersion(MESSAGING_VERSION)
-                .setMaxSupportedMessagingVersion(MESSAGING_VERSION)
-                .setMinSupportedSecurityVersion(SECURITY_VERSION)
-                .setMaxSupportedSecurityVersion(SECURITY_VERSION)
-                .build();
-        mWriteCharacteristic.setValue(headunitVersion.toByteArray());
-        mBlePeripheralManager.notifyCharacteristicChanged(device, mWriteCharacteristic,
-                /* confirm= */ false);
-        mIsVersionExchanged.set(true);
-        logd(TAG, "Sent supported version to the phone.");
-    }
-
-    @VisibleForTesting
-    void processPacket(@NonNull BlePacket packet) {
-        // Messages are coming in. Need to throttle outgoing messages to allow outgoing
-        // notifications to make it to the device.
-        mThrottleDelay.set(THROTTLE_WAIT_MS);
-
-        int messageId = packet.getMessageId();
-        int packetNumber = packet.getPacketNumber();
-        int expectedPacket = mPendingPacketNumber.getOrDefault(messageId, 1);
-        if (packetNumber == expectedPacket - 1) {
-            logw(TAG, "Received duplicate packet " + packet.getPacketNumber() + " for message "
-                    + messageId + ". Ignoring.");
-            return;
-        }
-        if (packetNumber != expectedPacket) {
-            loge(TAG, "Received unexpected packet " + packetNumber + " for message "
-                    + messageId + ".");
-            if (mMessageReceivedErrorListener != null) {
-                mMessageReceivedErrorListener.onMessageReceivedError(
-                        new IllegalStateException("Packet received out of order."));
-            }
-            return;
-        }
-        mPendingPacketNumber.put(messageId, packetNumber + 1);
-
-        ByteArrayOutputStream currentPayloadStream =
-                mPendingData.getOrDefault(messageId, new ByteArrayOutputStream());
-        mPendingData.putIfAbsent(messageId, currentPayloadStream);
-
-        byte[] payload = packet.getPayload().toByteArray();
-        try {
-            currentPayloadStream.write(payload);
-        } catch (IOException e) {
-            loge(TAG, "Error writing packet to stream.", e);
-            if (mMessageReceivedErrorListener != null) {
-                mMessageReceivedErrorListener.onMessageReceivedError(e);
-            }
-            return;
-        }
-        logd(TAG, "Parsed packet " + packet.getPacketNumber() + " of "
-                + packet.getTotalPackets() + " for message " + messageId + ". Writing "
-                + payload.length + ".");
-
-        if (packet.getPacketNumber() != packet.getTotalPackets()) {
-            return;
-        }
-
-        byte[] messageBytes = currentPayloadStream.toByteArray();
-        mPendingData.remove(messageId);
-
-        // All message packets received. Resetting throttle back to default until next message
-        // started.
-        mThrottleDelay.set(THROTTLE_DEFAULT_MS);
-
-        logd(TAG, "Received complete device message " + messageId + " of " + messageBytes.length
-                + " bytes.");
-        BleDeviceMessage message;
-        try {
-            message = BleDeviceMessage.parseFrom(messageBytes);
-        } catch (InvalidProtocolBufferException e) {
-            loge(TAG, "Cannot parse device message from client.", e);
-            if (mMessageReceivedErrorListener != null) {
-                mMessageReceivedErrorListener.onMessageReceivedError(e);
-            }
-            return;
-        }
-
-        DeviceMessage deviceMessage = new DeviceMessage(
-                ByteUtils.bytesToUUID(message.getRecipient().toByteArray()),
-                message.getIsPayloadEncrypted(), message.getPayload().toByteArray());
-        if (mMessageReceivedListener != null) {
-            mMessageReceivedListener.onMessageReceived(deviceMessage, message.getOperation());
-        }
-    }
-
-    /** The maximum amount of bytes that can be written over BLE. */
-    void setMaxWriteSize(int maxWriteSize) {
-        if (maxWriteSize <= 0) {
-            return;
-        }
-        mMaxWriteSize = maxWriteSize;
-    }
-
-    /**
-     * Set the given listener to be notified when a new message was received from the
-     * client. If listener is {@code null}, clear.
-     */
-    void setMessageReceivedListener(@Nullable MessageReceivedListener listener) {
-        mMessageReceivedListener = listener;
-    }
-
-    /**
-     * Set the given listener to be notified when there was an error during receiving
-     * message from the client. If listener is {@code null}, clear.
-     */
-    void setMessageReceivedErrorListener(
-            @Nullable MessageReceivedErrorListener listener) {
-        mMessageReceivedErrorListener = listener;
-    }
-
-    /**
-     * Listener to be invoked when a complete message is received from the client.
-     */
-    interface MessageReceivedListener {
-
-        /**
-         * Called when a complete message is received from the client.
-         *
-         * @param deviceMessage The message received from the client.
-         * @param operationType The {@link OperationType} of the received message.
-         */
-        void onMessageReceived(@NonNull DeviceMessage deviceMessage, OperationType operationType);
-    }
-
-    /**
-     * Listener to be invoked when there was an error during receiving message from the client.
-     */
-    interface MessageReceivedErrorListener {
-        /**
-         * Called when there was an error during receiving message from the client.
-         *
-         * @param exception The error.
-         */
-        void onMessageReceivedError(@NonNull Exception exception);
-    }
-
-    /** A generator of unique IDs for messages. */
-    private static class MessageIdGenerator {
-        private final AtomicInteger mMessageId = new AtomicInteger(0);
-
-        int next() {
-            int current = mMessageId.getAndIncrement();
-            mMessageId.compareAndSet(Integer.MAX_VALUE, 0);
-            return current;
-        }
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePacketFactory.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePacketFactory.java
deleted file mode 100644
index 24249a3..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePacketFactory.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.connecteddevice.BleStreamProtos.BlePacketProto.BlePacket;
-import com.android.car.protobuf.ByteString;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Factory for creating {@link BlePacket} protos.
- */
-class BlePacketFactory {
-    private static final String TAG = "BlePacketFactory";
-
-    /**
-     * The size in bytes of a {@code fixed32} field in the proto.
-     */
-    private static final int FIXED_32_SIZE = 4;
-
-    /**
-     * The bytes needed to encode the field number in the proto.
-     *
-     * <p>Since the {@link BlePacket} only has 4 fields, it will only take 1 additional byte to
-     * encode.
-     */
-    private static final int FIELD_NUMBER_ENCODING_SIZE = 1;
-
-    /**
-     * The size in bytes of field {@code packet_number}. The proto field is a {@code fixed32}.
-     */
-    private static final int PACKET_NUMBER_ENCODING_SIZE =
-            FIXED_32_SIZE + FIELD_NUMBER_ENCODING_SIZE;
-
-    /**
-     * Split given data if necessary to fit within the given {@code maxSize}.
-     *
-     * @param payload The payload to potentially split across multiple {@link BlePacket}s.
-     * @param messageId The unique id for identifying message.
-     * @param maxSize The maximum size of each chunk.
-     * @return A list of {@link BlePacket}s.
-     * @throws BlePacketFactoryException if an error occurred during the splitting of data.
-     */
-    static List<BlePacket> makeBlePackets(byte[] payload, int messageId, int maxSize)
-            throws BlePacketFactoryException {
-        List<BlePacket> blePackets = new ArrayList<>();
-        int payloadSize = payload.length;
-        int totalPackets = getTotalPacketNumber(messageId, payloadSize, maxSize);
-        int maxPayloadSize = maxSize
-                - getPacketHeaderSize(totalPackets, messageId, Math.min(payloadSize, maxSize));
-
-        int start = 0;
-        int end = Math.min(payloadSize, maxPayloadSize);
-        for (int packetNum = 1; packetNum <= totalPackets; packetNum++) {
-            blePackets.add(BlePacket.newBuilder()
-                    .setPacketNumber(packetNum)
-                    .setTotalPackets(totalPackets)
-                    .setMessageId(messageId)
-                    .setPayload(ByteString.copyFrom(Arrays.copyOfRange(payload, start, end)))
-                    .build());
-            start = end;
-            end = Math.min(start + maxPayloadSize, payloadSize);
-        }
-        return blePackets;
-    }
-
-    /**
-     * Compute the header size for the {@link BlePacket} proto in bytes. This method assumes that
-     * the proto contains a payload.
-     */
-    @VisibleForTesting
-    static int getPacketHeaderSize(int totalPackets, int messageId, int payloadSize) {
-        return FIXED_32_SIZE + FIELD_NUMBER_ENCODING_SIZE
-                + getEncodedSize(totalPackets) + FIELD_NUMBER_ENCODING_SIZE
-                + getEncodedSize(messageId) + FIELD_NUMBER_ENCODING_SIZE
-                + getEncodedSize(payloadSize) + FIELD_NUMBER_ENCODING_SIZE;
-    }
-
-    /**
-     * Compute the total packets required to encode a payload of the given size.
-     */
-    @VisibleForTesting
-    static int getTotalPacketNumber(int messageId, int payloadSize, int maxSize)
-            throws BlePacketFactoryException {
-        int headerSizeWithoutTotalPackets = FIXED_32_SIZE + FIELD_NUMBER_ENCODING_SIZE
-                + getEncodedSize(messageId) + FIELD_NUMBER_ENCODING_SIZE
-                + getEncodedSize(Math.min(payloadSize, maxSize)) + FIELD_NUMBER_ENCODING_SIZE;
-
-        for (int value = 1; value <= PACKET_NUMBER_ENCODING_SIZE; value++) {
-            int packetHeaderSize = headerSizeWithoutTotalPackets + value
-                    + FIELD_NUMBER_ENCODING_SIZE;
-            int maxPayloadSize = maxSize - packetHeaderSize;
-            if (maxPayloadSize < 0) {
-                throw new BlePacketFactoryException("Packet header size too large.");
-            }
-            int totalPackets = (int) Math.ceil(payloadSize / (double) maxPayloadSize);
-            if (getEncodedSize(totalPackets) == value) {
-                return totalPackets;
-            }
-        }
-
-        loge(TAG, "Cannot get valid total packet number for message: messageId: "
-                + messageId + ", payloadSize: " + payloadSize + ", maxSize: " + maxSize);
-        throw new BlePacketFactoryException("No valid total packet number.");
-    }
-
-    /**
-     * This method implements Protocol Buffers encoding algorithm.
-     *
-     * <p>Computes the number of bytes that would be needed to store a 32-bit variant.
-     *
-     * @param value the data that need to be encoded
-     * @return the size of the encoded data
-     * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding#varints">
-     *     Protocol Buffers Encoding</a>
-     */
-    private static int getEncodedSize(int value) {
-        if (value < 0) {
-            return 10;
-        }
-        if ((value & (~0 << 7)) == 0) {
-            return 1;
-        }
-        if ((value & (~0 << 14)) == 0) {
-            return 2;
-        }
-        if ((value & (~0 << 21)) == 0) {
-            return 3;
-        }
-        if ((value & (~0 << 28)) == 0) {
-            return 4;
-        }
-        return 5;
-    }
-
-    private BlePacketFactory() {}
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePacketFactoryException.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePacketFactoryException.java
deleted file mode 100644
index 690ce28..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePacketFactoryException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-package com.android.car.connecteddevice.ble;
-
-/**
- * Exception for signaling {@link BlePacketFactory} errors.
- */
-class BlePacketFactoryException extends Exception {
-    BlePacketFactoryException(String message) {
-        super(message);
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePeripheralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePeripheralManager.java
deleted file mode 100644
index a25cb0b..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/BlePeripheralManager.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-import static com.android.car.connecteddevice.util.SafeLog.logw;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCallback;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.BluetoothGattServer;
-import android.bluetooth.BluetoothGattServerCallback;
-import android.bluetooth.BluetoothGattService;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.le.AdvertiseCallback;
-import android.bluetooth.le.AdvertiseData;
-import android.bluetooth.le.AdvertiseSettings;
-import android.bluetooth.le.BluetoothLeAdvertiser;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Handler;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.car.connecteddevice.util.ByteUtils;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * A generic class that manages BLE peripheral operations like start/stop advertising, notifying
- * connects/disconnects and reading/writing values to GATT characteristics.
- */
-// TODO(b/123248433) This could move to a separate comms library.
-public class BlePeripheralManager {
-    private static final String TAG = "BlePeripheralManager";
-
-    private static final int BLE_RETRY_LIMIT = 5;
-    private static final int BLE_RETRY_INTERVAL_MS = 1000;
-
-    private static final int GATT_SERVER_RETRY_LIMIT = 20;
-    private static final int GATT_SERVER_RETRY_DELAY_MS = 200;
-
-    // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth
-    // .service.generic_access.xml
-    private static final UUID GENERIC_ACCESS_PROFILE_UUID =
-            UUID.fromString("00001800-0000-1000-8000-00805f9b34fb");
-    // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth
-    // .characteristic.gap.device_name.xml
-    private static final UUID DEVICE_NAME_UUID =
-            UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb");
-
-    private final Handler mHandler;
-
-    private final Context mContext;
-    private final Set<Callback> mCallbacks = new CopyOnWriteArraySet<>();
-    private final Set<OnCharacteristicWriteListener> mWriteListeners = new HashSet<>();
-    private final Set<OnCharacteristicReadListener> mReadListeners = new HashSet<>();
-    private final AtomicReference<BluetoothGattServer> mGattServer = new AtomicReference<>();
-    private final AtomicReference<BluetoothGatt> mBluetoothGatt = new AtomicReference<>();
-
-    private int mMtuSize = 20;
-
-    private BluetoothManager mBluetoothManager;
-    private AtomicReference<BluetoothLeAdvertiser> mAdvertiser = new AtomicReference<>();
-    private int mAdvertiserStartCount;
-    private int mGattServerRetryStartCount;
-    private BluetoothGattService mBluetoothGattService;
-    private AdvertiseCallback mAdvertiseCallback;
-    private AdvertiseData mAdvertiseData;
-    private AdvertiseData mScanResponse;
-
-    public BlePeripheralManager(Context context) {
-        mContext = context;
-        mHandler = new Handler(mContext.getMainLooper());
-    }
-
-    /**
-     * Registers the given callback to be notified of various events within the {@link
-     * BlePeripheralManager}.
-     *
-     * @param callback The callback to be notified.
-     */
-    void registerCallback(@NonNull Callback callback) {
-        mCallbacks.add(callback);
-    }
-
-    /**
-     * Unregisters a previously registered callback.
-     *
-     * @param callback The callback to unregister.
-     */
-    void unregisterCallback(@NonNull Callback callback) {
-        mCallbacks.remove(callback);
-    }
-
-    /**
-     * Adds a listener to be notified of a write to characteristics.
-     *
-     * @param listener The listener to invoke.
-     */
-    void addOnCharacteristicWriteListener(@NonNull OnCharacteristicWriteListener listener) {
-        mWriteListeners.add(listener);
-    }
-
-    /**
-     * Removes the given listener from being notified of characteristic writes.
-     *
-     * @param listener The listener to remove.
-     */
-    void removeOnCharacteristicWriteListener(@NonNull OnCharacteristicWriteListener listener) {
-        mWriteListeners.remove(listener);
-    }
-
-    /**
-     * Adds a listener to be notified of reads to characteristics.
-     *
-     * @param listener The listener to invoke.
-     */
-    void addOnCharacteristicReadListener(@NonNull OnCharacteristicReadListener listener) {
-        mReadListeners.add(listener);
-    }
-
-    /**
-     * Removes the given listener from being notified of characteristic reads.
-     *
-     * @param listener The listener to remove.
-     */
-    void removeOnCharacteristicReadistener(@NonNull OnCharacteristicReadListener listener) {
-        mReadListeners.remove(listener);
-    }
-
-    /**
-     * Returns the current MTU size.
-     *
-     * @return The size of the MTU in bytes.
-     */
-    int getMtuSize() {
-        return mMtuSize;
-    }
-
-    /**
-     * Starts the GATT server with the given {@link BluetoothGattService} and begins advertising.
-     *
-     * <p>It is possible that BLE service is still in TURNING_ON state when this method is invoked.
-     * Therefore, several retries will be made to ensure advertising is started.
-     *
-     * @param service           {@link BluetoothGattService} that will be discovered by clients
-     * @param data              {@link AdvertiseData} data to advertise
-     * @param scanResponse      {@link AdvertiseData} scan response
-     * @param advertiseCallback {@link AdvertiseCallback} callback for advertiser
-     */
-    void startAdvertising(
-            BluetoothGattService service, AdvertiseData data,
-            AdvertiseData scanResponse, AdvertiseCallback advertiseCallback) {
-        logd(TAG, "Request to start advertising with service " + service.getUuid() + ".");
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
-            loge(TAG, "Attempted start advertising, but system does not support BLE. Ignoring.");
-            return;
-        }
-        // Clears previous session before starting advertising.
-        cleanup();
-        mBluetoothGattService = service;
-        mAdvertiseCallback = advertiseCallback;
-        mAdvertiseData = data;
-        mScanResponse = scanResponse;
-        mGattServerRetryStartCount = 0;
-        mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
-        mGattServer.set(mBluetoothManager.openGattServer(mContext, mGattServerCallback));
-        openGattServer();
-    }
-
-    /**
-     * Stops the GATT server from advertising.
-     *
-     * @param advertiseCallback The callback that is associated with the advertisement.
-     */
-    void stopAdvertising(AdvertiseCallback advertiseCallback) {
-        BluetoothLeAdvertiser advertiser = mAdvertiser.getAndSet(null);
-        if (advertiser != null) {
-            advertiser.stopAdvertising(advertiseCallback);
-            logd(TAG, "Advertising stopped.");
-        }
-    }
-
-    /**
-     * Notifies the characteristic change via {@link BluetoothGattServer}
-     */
-    void notifyCharacteristicChanged(
-            @NonNull BluetoothDevice device,
-            @NonNull BluetoothGattCharacteristic characteristic,
-            boolean confirm) {
-        BluetoothGattServer gattServer = mGattServer.get();
-        if (gattServer == null) {
-            return;
-        }
-
-        if (!gattServer.notifyCharacteristicChanged(device, characteristic, confirm)) {
-            loge(TAG, "notifyCharacteristicChanged failed");
-        }
-    }
-
-    /**
-     * Connect the Gatt server of the remote device to retrieve device name.
-     */
-    final void retrieveDeviceName(BluetoothDevice device) {
-        mBluetoothGatt.compareAndSet(null, device.connectGatt(mContext, false, mGattCallback));
-    }
-
-    /**
-     * Cleans up the BLE GATT server state.
-     */
-    void cleanup() {
-        logd(TAG, "Cleaning up manager.");
-        // Stops the advertiser, scanner and GATT server. This needs to be done to avoid leaks.
-        stopAdvertising(mAdvertiseCallback);
-        // Clears all registered listeners. IHU only supports single connection in peripheral role.
-        mReadListeners.clear();
-        mWriteListeners.clear();
-
-        BluetoothGattServer gattServer = mGattServer.getAndSet(null);
-        if (gattServer == null) {
-            return;
-        }
-
-        logd(TAG, "Stopping gatt server.");
-        BluetoothGatt bluetoothGatt = mBluetoothGatt.getAndSet(null);
-        if (bluetoothGatt != null) {
-            gattServer.cancelConnection(bluetoothGatt.getDevice());
-            logd(TAG, "Disconnecting gatt.");
-            bluetoothGatt.disconnect();
-            bluetoothGatt.close();
-        }
-        gattServer.clearServices();
-        gattServer.close();
-    }
-
-    private void openGattServer() {
-        // Only open one Gatt server.
-        BluetoothGattServer gattServer = mGattServer.get();
-        if (gattServer != null) {
-            logd(TAG, "Gatt Server created, retry count: " + mGattServerRetryStartCount);
-            gattServer.clearServices();
-            gattServer.addService(mBluetoothGattService);
-            AdvertiseSettings settings =
-                    new AdvertiseSettings.Builder()
-                            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
-                            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
-                            .setConnectable(true)
-                            .build();
-            mAdvertiserStartCount = 0;
-            startAdvertisingInternally(settings, mAdvertiseData, mScanResponse, mAdvertiseCallback);
-            mGattServerRetryStartCount = 0;
-        } else if (mGattServerRetryStartCount < GATT_SERVER_RETRY_LIMIT) {
-            mGattServer.set(mBluetoothManager.openGattServer(mContext, mGattServerCallback));
-            mGattServerRetryStartCount++;
-            mHandler.postDelayed(() -> openGattServer(), GATT_SERVER_RETRY_DELAY_MS);
-        } else {
-            loge(TAG, "Gatt server not created - exceeded retry limit.");
-        }
-    }
-
-    private void startAdvertisingInternally(
-            AdvertiseSettings settings, AdvertiseData advertisement, AdvertiseData scanResponse,
-            AdvertiseCallback advertiseCallback) {
-        if (BluetoothAdapter.getDefaultAdapter() != null) {
-            mAdvertiser.compareAndSet(null,
-                    BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser());
-        }
-        BluetoothLeAdvertiser advertiser = mAdvertiser.get();
-        if (advertiser != null) {
-            logd(TAG, "Advertiser created, retry count: " + mAdvertiserStartCount);
-            advertiser.startAdvertising(settings, advertisement, scanResponse, advertiseCallback);
-            mAdvertiserStartCount = 0;
-        } else if (mAdvertiserStartCount < BLE_RETRY_LIMIT) {
-            mHandler.postDelayed(
-                    () -> startAdvertisingInternally(settings, advertisement, scanResponse,
-                            advertiseCallback),
-                    BLE_RETRY_INTERVAL_MS);
-            mAdvertiserStartCount += 1;
-        } else {
-            loge(TAG, "Cannot start BLE Advertisement. Advertise Retry count: "
-                            + mAdvertiserStartCount);
-        }
-    }
-
-    private final BluetoothGattServerCallback mGattServerCallback =
-            new BluetoothGattServerCallback() {
-                @Override
-                public void onConnectionStateChange(BluetoothDevice device, int status,
-                                                    int newState) {
-                    switch (newState) {
-                        case BluetoothProfile.STATE_CONNECTED:
-                            logd(TAG, "BLE Connection State Change: CONNECTED");
-                            BluetoothGattServer gattServer = mGattServer.get();
-                            if (gattServer == null) {
-                                return;
-                            }
-                            gattServer.connect(device, /* autoConnect= */ false);
-                            for (Callback callback : mCallbacks) {
-                                callback.onRemoteDeviceConnected(device);
-                            }
-                            break;
-                        case BluetoothProfile.STATE_DISCONNECTED:
-                            logd(TAG, "BLE Connection State Change: DISCONNECTED");
-                            for (Callback callback : mCallbacks) {
-                                callback.onRemoteDeviceDisconnected(device);
-                            }
-                            break;
-                        default:
-                            logw(TAG, "Connection state not connecting or disconnecting; ignoring: "
-                                    + newState);
-                    }
-                }
-
-                @Override
-                public void onServiceAdded(int status, BluetoothGattService service) {
-                    logd(TAG, "Service added status: " + status + " uuid: " + service.getUuid());
-                }
-
-                @Override
-                public void onCharacteristicWriteRequest(
-                        BluetoothDevice device,
-                        int requestId,
-                        BluetoothGattCharacteristic characteristic,
-                        boolean preparedWrite,
-                        boolean responseNeeded,
-                        int offset,
-                        byte[] value) {
-                    BluetoothGattServer gattServer = mGattServer.get();
-                    if (gattServer == null) {
-                        return;
-                    }
-                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset,
-                            value);
-                    for (OnCharacteristicWriteListener listener : mWriteListeners) {
-                        listener.onCharacteristicWrite(device, characteristic, value);
-                    }
-                }
-
-                @Override
-                public void onDescriptorWriteRequest(
-                        BluetoothDevice device,
-                        int requestId,
-                        BluetoothGattDescriptor descriptor,
-                        boolean preparedWrite,
-                        boolean responseNeeded,
-                        int offset,
-                        byte[] value) {
-                    logd(TAG, "Write request for descriptor: "
-                            + descriptor.getUuid()
-                            + "; value: "
-                            + ByteUtils.byteArrayToHexString(value));
-                    BluetoothGattServer gattServer = mGattServer.get();
-                    if (gattServer == null) {
-                        return;
-                    }
-                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset,
-                            value);
-                }
-
-                @Override
-                public void onMtuChanged(BluetoothDevice device, int mtu) {
-                    logd(TAG, "onMtuChanged: " + mtu + " for device " + device.getAddress());
-
-                    mMtuSize = mtu;
-
-                    for (Callback callback : mCallbacks) {
-                        callback.onMtuSizeChanged(mtu);
-                    }
-                }
-
-                @Override
-                public void onNotificationSent(BluetoothDevice device, int status) {
-                    super.onNotificationSent(device, status);
-                    if (status == BluetoothGatt.GATT_SUCCESS) {
-                        logd(TAG, "Notification sent successfully. Device: " + device.getAddress()
-                                + ", Status: " + status + ". Notifying all listeners.");
-                        for (OnCharacteristicReadListener listener : mReadListeners) {
-                            listener.onCharacteristicRead(device);
-                        }
-                    } else {
-                        loge(TAG, "Notification failed. Device: " + device + ", Status: "
-                                + status);
-                    }
-                }
-            };
-
-    private final BluetoothGattCallback mGattCallback =
-            new BluetoothGattCallback() {
-                @Override
-                public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
-                    logd(TAG, "Gatt Connection State Change: " + newState);
-                    switch (newState) {
-                        case BluetoothProfile.STATE_CONNECTED:
-                            logd(TAG, "Gatt connected");
-                            BluetoothGatt bluetoothGatt = mBluetoothGatt.get();
-                            if (bluetoothGatt == null) {
-                                break;
-                            }
-                            bluetoothGatt.discoverServices();
-                            break;
-                        case BluetoothProfile.STATE_DISCONNECTED:
-                            logd(TAG, "Gatt Disconnected");
-                            break;
-                        default:
-                            logd(TAG, "Connection state not connecting or disconnecting; ignoring: "
-                                    + newState);
-                    }
-                }
-
-                @Override
-                public void onServicesDiscovered(BluetoothGatt gatt, int status) {
-                    logd(TAG, "Gatt Services Discovered");
-                    BluetoothGatt bluetoothGatt = mBluetoothGatt.get();
-                    if (bluetoothGatt == null) {
-                        return;
-                    }
-                    BluetoothGattService gapService = bluetoothGatt.getService(
-                            GENERIC_ACCESS_PROFILE_UUID);
-                    if (gapService == null) {
-                        loge(TAG, "Generic Access Service is null.");
-                        return;
-                    }
-                    BluetoothGattCharacteristic deviceNameCharacteristic =
-                            gapService.getCharacteristic(DEVICE_NAME_UUID);
-                    if (deviceNameCharacteristic == null) {
-                        loge(TAG, "Device Name Characteristic is null.");
-                        return;
-                    }
-                    bluetoothGatt.readCharacteristic(deviceNameCharacteristic);
-                }
-
-                @Override
-                public void onCharacteristicRead(
-                        BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
-                        int status) {
-                    if (status == BluetoothGatt.GATT_SUCCESS) {
-                        String deviceName = characteristic.getStringValue(0);
-                        logd(TAG, "BLE Device Name: " + deviceName);
-
-                        for (Callback callback : mCallbacks) {
-                            callback.onDeviceNameRetrieved(deviceName);
-                        }
-                    } else {
-                        loge(TAG, "Reading GAP Failed: " + status);
-                    }
-                }
-            };
-
-    /**
-     * Interface to be notified of various events within the {@link BlePeripheralManager}.
-     */
-    interface Callback {
-        /**
-         * Triggered when the name of the remote device is retrieved.
-         *
-         * @param deviceName Name of the remote device.
-         */
-        void onDeviceNameRetrieved(@Nullable String deviceName);
-
-        /**
-         * Triggered if a remote client has requested to change the MTU for a given connection.
-         *
-         * @param size The new MTU size.
-         */
-        void onMtuSizeChanged(int size);
-
-        /**
-         * Triggered when a device (GATT client) connected.
-         *
-         * @param device Remote device that connected on BLE.
-         */
-        void onRemoteDeviceConnected(@NonNull BluetoothDevice device);
-
-        /**
-         * Triggered when a device (GATT client) disconnected.
-         *
-         * @param device Remote device that disconnected on BLE.
-         */
-        void onRemoteDeviceDisconnected(@NonNull BluetoothDevice device);
-    }
-
-    /**
-     * An interface for classes that wish to be notified of writes to a characteristic.
-     */
-    interface OnCharacteristicWriteListener {
-        /**
-         * Triggered when this BlePeripheralManager receives a write request from a remote device.
-         *
-         * @param device         The bluetooth device that holds the characteristic.
-         * @param characteristic The characteristic that was written to.
-         * @param value          The value that was written.
-         */
-        void onCharacteristicWrite(
-                @NonNull BluetoothDevice device,
-                @NonNull BluetoothGattCharacteristic characteristic,
-                @NonNull byte[] value);
-    }
-
-    /**
-     * An interface for classes that wish to be notified of reads on a characteristic.
-     */
-    interface OnCharacteristicReadListener {
-        /**
-         * Triggered when this BlePeripheralManager receives a read request from a remote device.
-         *
-         * @param device The bluetooth device that holds the characteristic.
-         */
-        void onCharacteristicRead(@NonNull BluetoothDevice device);
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleCentralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleCentralManager.java
deleted file mode 100644
index 21bec2b..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleCentralManager.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-import static com.android.car.connecteddevice.util.SafeLog.logw;
-import static com.android.car.connecteddevice.util.ScanDataAnalyzer.containsUuidsInOverflow;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCallback;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.BluetoothGattService;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanRecord;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.content.Context;
-import android.os.ParcelUuid;
-
-import androidx.annotation.NonNull;
-
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-
-import java.math.BigInteger;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-/**
- * Communication manager for a car that maintains continuous connections with all devices in the car
- * for the duration of a drive.
- */
-public class CarBleCentralManager extends CarBleManager {
-
-    private static final String TAG = "CarBleCentralManager";
-
-    // system/bt/internal_include/bt_target.h#GATT_MAX_PHY_CHANNEL
-    private static final int MAX_CONNECTIONS = 7;
-
-    private static final UUID CHARACTERISTIC_CONFIG =
-            UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
-
-    private static final int STATUS_FORCED_DISCONNECT = -1;
-
-    private final ScanSettings mScanSettings = new ScanSettings.Builder()
-            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
-            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
-            .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
-            .build();
-
-    private final CopyOnWriteArraySet<BleDevice> mIgnoredDevices = new CopyOnWriteArraySet<>();
-
-    private final Context mContext;
-
-    private final BleCentralManager mBleCentralManager;
-
-    private final UUID mServiceUuid;
-
-    private final UUID mWriteCharacteristicUuid;
-
-    private final UUID mReadCharacteristicUuid;
-
-    private final BigInteger mParsedBgServiceBitMask;
-
-    /**
-     * Create a new manager.
-     *
-     * @param context The caller's [Context].
-     * @param bleCentralManager [BleCentralManager] for establishing connections.
-     * @param connectedDeviceStorage Shared [ConnectedDeviceStorage] for companion features.
-     * @param serviceUuid [UUID] of peripheral's service.
-     * @param bgServiceMask iOS overflow bit mask for service UUID.
-     * @param writeCharacteristicUuid [UUID] of characteristic the car will write to.
-     * @param readCharacteristicUuid [UUID] of characteristic the device will write to.
-     */
-    public CarBleCentralManager(
-            @NonNull Context context,
-            @NonNull BleCentralManager bleCentralManager,
-            @NonNull ConnectedDeviceStorage connectedDeviceStorage,
-            @NonNull UUID serviceUuid,
-            @NonNull String bgServiceMask,
-            @NonNull UUID writeCharacteristicUuid,
-            @NonNull UUID readCharacteristicUuid) {
-        super(connectedDeviceStorage);
-        mContext = context;
-        mBleCentralManager = bleCentralManager;
-        mServiceUuid = serviceUuid;
-        mWriteCharacteristicUuid = writeCharacteristicUuid;
-        mReadCharacteristicUuid = readCharacteristicUuid;
-        mParsedBgServiceBitMask = new BigInteger(bgServiceMask, 16);
-    }
-
-    @Override
-    public void start() {
-        super.start();
-        mBleCentralManager.startScanning(/* filters= */ null, mScanSettings, mScanCallback);
-    }
-
-    @Override
-    public void stop() {
-        super.stop();
-        mBleCentralManager.stopScanning();
-    }
-
-    @Override
-    public void disconnectDevice(String deviceId) {
-        logd(TAG, "Request to disconnect from device " + deviceId + ".");
-        BleDevice device = getConnectedDevice(deviceId);
-        if (device == null) {
-            return;
-        }
-
-        deviceDisconnected(device, STATUS_FORCED_DISCONNECT);
-    }
-
-    private void ignoreDevice(@NonNull BleDevice device) {
-        mIgnoredDevices.add(device);
-    }
-
-    private boolean isDeviceIgnored(@NonNull BluetoothDevice device) {
-        for (BleDevice bleDevice : mIgnoredDevices) {
-            if (device.equals(bleDevice.mDevice)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean shouldAttemptConnection(@NonNull ScanResult result) {
-        // Ignore any results that are not connectable.
-        if (!result.isConnectable()) {
-            return false;
-        }
-
-        // Do not attempt to connect if we have already hit our max. This should rarely happen
-        // and is protecting against a race condition of scanning stopped and new results coming in.
-        if (getConnectedDevicesCount() >= MAX_CONNECTIONS) {
-            return false;
-        }
-
-        BluetoothDevice device = result.getDevice();
-
-        // Do not connect if device has already been ignored.
-        if (isDeviceIgnored(device)) {
-            return false;
-        }
-
-        // Check if already attempting to connect to this device.
-        if (getConnectedDevice(device) != null) {
-            return false;
-        }
-
-
-        // Ignore any device without a scan record.
-        ScanRecord scanRecord = result.getScanRecord();
-        if (scanRecord == null) {
-            return false;
-        }
-
-        // Connect to any device that is advertising our service UUID.
-        List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids();
-        if (serviceUuids != null) {
-            for (ParcelUuid serviceUuid : serviceUuids) {
-                if (serviceUuid.getUuid().equals(mServiceUuid)) {
-                    return true;
-                }
-            }
-        }
-        if (containsUuidsInOverflow(scanRecord.getBytes(), mParsedBgServiceBitMask)) {
-            return true;
-        }
-
-        // Can safely ignore devices advertising unrecognized service uuids.
-        if (serviceUuids != null && !serviceUuids.isEmpty()) {
-            return false;
-        }
-
-        // TODO(b/139066293): Current implementation quickly exhausts connections resulting in
-        // greatly reduced performance for connecting to devices we know we want to connect to.
-        // Return true once fixed.
-        return false;
-    }
-
-    private void startDeviceConnection(@NonNull BluetoothDevice device) {
-        BluetoothGatt gatt = device.connectGatt(mContext, /* autoConnect= */ false,
-                mConnectionCallback, BluetoothDevice.TRANSPORT_LE);
-        if (gatt == null) {
-            return;
-        }
-
-        BleDevice bleDevice = new BleDevice(device, gatt);
-        bleDevice.mState = BleDeviceState.CONNECTING;
-        addConnectedDevice(bleDevice);
-
-        // Stop scanning if we have reached the maximum number of connections.
-        if (getConnectedDevicesCount() >= MAX_CONNECTIONS) {
-            mBleCentralManager.stopScanning();
-        }
-    }
-
-    private void deviceConnected(@NonNull BleDevice device) {
-        if (device.mGatt == null) {
-            loge(TAG, "Device connected with null gatt. Disconnecting.");
-            deviceDisconnected(device, BluetoothProfile.STATE_DISCONNECTED);
-            return;
-        }
-        device.mState = BleDeviceState.PENDING_VERIFICATION;
-        device.mGatt.discoverServices();
-        logd(TAG, "New device connected: " + device.mGatt.getDevice().getAddress()
-                + ". Active connections: " + getConnectedDevicesCount() + ".");
-    }
-
-    private void deviceDisconnected(@NonNull BleDevice device, int status) {
-        removeConnectedDevice(device);
-        if (device.mGatt != null) {
-            device.mGatt.close();
-        }
-        if (device.mDeviceId != null) {
-            mCallbacks.invoke(callback -> callback.onDeviceDisconnected(device.mDeviceId));
-        }
-        logd(TAG, "Device with id " + device.mDeviceId + " disconnected with state " + status
-                + ". Remaining active connections: " + getConnectedDevicesCount() + ".");
-    }
-
-    private final ScanCallback mScanCallback = new ScanCallback() {
-        @Override
-        public void onScanResult(int callbackType, ScanResult result) {
-            super.onScanResult(callbackType, result);
-            if (shouldAttemptConnection(result)) {
-                startDeviceConnection(result.getDevice());
-            }
-        }
-
-        @Override
-        public void onScanFailed(int errorCode) {
-            super.onScanFailed(errorCode);
-            loge(TAG, "BLE scanning failed with error code: " + errorCode);
-        }
-    };
-
-    private final BluetoothGattCallback mConnectionCallback = new BluetoothGattCallback() {
-        @Override
-        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
-            super.onConnectionStateChange(gatt, status, newState);
-            if (gatt == null) {
-                logw(TAG, "Null gatt passed to onConnectionStateChange. Ignoring.");
-                return;
-            }
-
-            BleDevice connectedDevice = getConnectedDevice(gatt);
-            if (connectedDevice == null) {
-                return;
-            }
-
-            switch (newState) {
-                case BluetoothProfile.STATE_CONNECTED:
-                    deviceConnected(connectedDevice);
-                    break;
-                case BluetoothProfile.STATE_DISCONNECTED:
-                    deviceDisconnected(connectedDevice, status);
-                    break;
-                default:
-                    logd(TAG, "Connection state changed. New state: " + newState + " status: "
-                            + status);
-            }
-        }
-
-        @Override
-        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
-            super.onServicesDiscovered(gatt, status);
-            if (gatt == null) {
-                logw(TAG, "Null gatt passed to onServicesDiscovered. Ignoring.");
-                return;
-            }
-
-            BleDevice connectedDevice = getConnectedDevice(gatt);
-            if (connectedDevice == null) {
-                return;
-            }
-            BluetoothGattService service = gatt.getService(mServiceUuid);
-            if (service == null) {
-                ignoreDevice(connectedDevice);
-                gatt.disconnect();
-                return;
-            }
-
-            connectedDevice.mState = BleDeviceState.CONNECTED;
-            BluetoothGattCharacteristic writeCharacteristic =
-                    service.getCharacteristic(mWriteCharacteristicUuid);
-            BluetoothGattCharacteristic readCharacteristic =
-                    service.getCharacteristic(mReadCharacteristicUuid);
-            if (writeCharacteristic == null || readCharacteristic == null) {
-                logw(TAG, "Unable to find expected characteristics on peripheral.");
-                gatt.disconnect();
-                return;
-            }
-
-            // Turn on notifications for read characteristic.
-            BluetoothGattDescriptor descriptor =
-                    readCharacteristic.getDescriptor(CHARACTERISTIC_CONFIG);
-            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
-            if (!gatt.writeDescriptor(descriptor)) {
-                loge(TAG, "Write descriptor to read characteristic failed.");
-                gatt.disconnect();
-                return;
-            }
-
-            if (!gatt.setCharacteristicNotification(readCharacteristic, /* enable= */ true)) {
-                loge(TAG, "Set notifications to read characteristic failed.");
-                gatt.disconnect();
-                return;
-            }
-
-            logd(TAG, "Service and characteristics successfully discovered.");
-        }
-
-        @Override
-        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
-                int status) {
-            super.onDescriptorWrite(gatt, descriptor, status);
-            if (gatt == null) {
-                logw(TAG, "Null gatt passed to onDescriptorWrite. Ignoring.");
-                return;
-            }
-            // TODO(b/141312136): Create SecureBleChannel and assign to connectedDevice.
-        }
-    };
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleManager.java
deleted file mode 100644
index f63d591..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBleManager.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.logw;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-import com.android.car.connecteddevice.util.ThreadSafeCallbacks;
-
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.Executor;
-
-/**
- * Generic BLE manager for a car that keeps track of connected devices and their associated
- * callbacks.
- */
-public abstract class CarBleManager {
-
-    private static final String TAG = "CarBleManager";
-
-    final ConnectedDeviceStorage mStorage;
-
-    final CopyOnWriteArraySet<BleDevice> mConnectedDevices = new CopyOnWriteArraySet<>();
-
-    final ThreadSafeCallbacks<Callback> mCallbacks = new ThreadSafeCallbacks<>();
-
-    protected CarBleManager(@NonNull ConnectedDeviceStorage connectedDeviceStorage) {
-        mStorage = connectedDeviceStorage;
-    }
-
-    /**
-     * Initialize and start the manager.
-     */
-    public void start() {
-    }
-
-    /**
-     * Stop the manager and clean up.
-     */
-    public void stop() {
-        for (BleDevice device : mConnectedDevices) {
-            if (device.mGatt != null) {
-                device.mGatt.close();
-            }
-        }
-        mConnectedDevices.clear();
-    }
-
-    /**
-     * Register a {@link Callback} to be notified on the {@link Executor}.
-     */
-    public void registerCallback(@NonNull Callback callback, @NonNull Executor executor) {
-        mCallbacks.add(callback, executor);
-    }
-
-    /**
-     * Unregister a callback.
-     *
-     * @param callback The {@link Callback} to unregister.
-     */
-    public void unregisterCallback(@NonNull Callback callback) {
-        mCallbacks.remove(callback);
-    }
-
-    /**
-     * Send a message to a connected device.
-     *
-     * @param deviceId Id of connected device.
-     * @param message  {@link DeviceMessage} to send.
-     */
-    public void sendMessage(@NonNull String deviceId, @NonNull DeviceMessage message) {
-        BleDevice device = getConnectedDevice(deviceId);
-        if (device == null) {
-            logw(TAG, "Attempted to send message to unknown device $deviceId. Ignored.");
-            return;
-        }
-
-        sendMessage(device, message);
-    }
-
-    /**
-     * Send a message to a connected device.
-     *
-     * @param device  The connected {@link BleDevice}.
-     * @param message {@link DeviceMessage} to send.
-     */
-    public void sendMessage(@NonNull BleDevice device, @NonNull DeviceMessage message) {
-        String deviceId = device.mDeviceId;
-        if (deviceId == null) {
-            deviceId = "Unidentified device";
-        }
-
-        logd(TAG, "Writing " + message.getMessage().length + " bytes to " + deviceId + ".");
-        device.mSecureChannel.sendClientMessage(message);
-    }
-
-    /**
-     * Get the {@link BleDevice} with matching {@link BluetoothGatt} if available. Returns
-     * {@code null} if no matches are found.
-     */
-    @Nullable
-    BleDevice getConnectedDevice(@NonNull BluetoothGatt gatt) {
-        for (BleDevice device : mConnectedDevices) {
-            if (device.mGatt == gatt) {
-                return device;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the {@link BleDevice} with matching {@link BluetoothDevice} if available. Returns
-     * {@code null} if no matches are found.
-     */
-    @Nullable
-    BleDevice getConnectedDevice(@NonNull BluetoothDevice device) {
-        for (BleDevice connectedDevice : mConnectedDevices) {
-            if (device.equals(connectedDevice.mDevice)) {
-                return connectedDevice;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the {@link BleDevice} with matching device id if available. Returns {@code null} if
-     * no matches are found.
-     */
-    @Nullable
-    BleDevice getConnectedDevice(@NonNull String deviceId) {
-        for (BleDevice device : mConnectedDevices) {
-            if (deviceId.equals(device.mDeviceId)) {
-                return device;
-            }
-        }
-
-        return null;
-    }
-
-    /** Add the {@link BleDevice} that has connected. */
-    void addConnectedDevice(@NonNull BleDevice device) {
-        mConnectedDevices.add(device);
-    }
-
-    /** Return the number of devices currently connected. */
-    int getConnectedDevicesCount() {
-        return mConnectedDevices.size();
-    }
-
-    /** Remove [@link BleDevice} that has been disconnected. */
-    void removeConnectedDevice(@NonNull BleDevice device) {
-        mConnectedDevices.remove(device);
-    }
-
-    /** Disconnect the provided device from this manager. */
-    public abstract void disconnectDevice(@NonNull String deviceId);
-
-    /** State for a connected device. */
-    enum BleDeviceState {
-        CONNECTING,
-        PENDING_VERIFICATION,
-        CONNECTED,
-        UNKNOWN
-    }
-
-    /**
-     * Container class to hold information about a connected device.
-     */
-    static class BleDevice {
-
-        BluetoothDevice mDevice;
-        BluetoothGatt mGatt;
-        BleDeviceState mState;
-        String mDeviceId;
-        SecureBleChannel mSecureChannel;
-
-        BleDevice(@NonNull BluetoothDevice device, @Nullable BluetoothGatt gatt) {
-            mDevice = device;
-            mGatt = gatt;
-            mState = BleDeviceState.UNKNOWN;
-        }
-    }
-
-    /**
-     * Callback for triggered events from {@link CarBleManager}.
-     */
-    public interface Callback {
-        /**
-         * Triggered when device is connected and device id retrieved. Device is now ready to
-         * receive messages.
-         *
-         * @param deviceId Id of device that has connected.
-         */
-        void onDeviceConnected(@NonNull String deviceId);
-
-        /**
-         * Triggered when device is disconnected.
-         *
-         * @param deviceId Id of device that has disconnected.
-         */
-        void onDeviceDisconnected(@NonNull String deviceId);
-
-        /**
-         * Triggered when device has established encryption for secure communication.
-         *
-         * @param deviceId Id of device that has established encryption.
-         */
-        void onSecureChannelEstablished(@NonNull String deviceId);
-
-        /**
-         * Triggered when a new message is received.
-         *
-         * @param deviceId Id of the device that sent the message.
-         * @param message  {@link DeviceMessage} received.
-         */
-        void onMessageReceived(@NonNull String deviceId, @NonNull DeviceMessage message);
-
-        /**
-         * Triggered when an error when establishing the secure channel.
-         *
-         * @param deviceId Id of the device that experienced the error.
-         */
-        void onSecureChannelError(@NonNull String deviceId);
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
deleted file mode 100644
index 3819f0d..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/CarBlePeripheralManager.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.ConnectedDeviceManager.DEVICE_ERROR_INVALID_HANDSHAKE;
-import static com.android.car.connecteddevice.ConnectedDeviceManager.DEVICE_ERROR_UNEXPECTED_DISCONNECTION;
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-import static com.android.car.connecteddevice.util.SafeLog.logw;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.BluetoothGattService;
-import android.bluetooth.le.AdvertiseCallback;
-import android.bluetooth.le.AdvertiseData;
-import android.bluetooth.le.AdvertiseSettings;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.ParcelUuid;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.connecteddevice.AssociationCallback;
-import com.android.car.connecteddevice.model.AssociatedDevice;
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-import com.android.car.connecteddevice.util.ByteUtils;
-import com.android.car.connecteddevice.util.EventLog;
-
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.UUID;
-
-/**
- * Communication manager that allows for targeted connections to a specific device in the car.
- */
-public class CarBlePeripheralManager extends CarBleManager {
-
-    private static final String TAG = "CarBlePeripheralManager";
-
-    // Attribute protocol bytes attached to message. Available write size is MTU size minus att
-    // bytes.
-    private static final int ATT_PROTOCOL_BYTES = 3;
-
-    private static final UUID CLIENT_CHARACTERISTIC_CONFIG =
-            UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
-
-    private static final int SALT_BYTES = 8;
-
-    private static final int TOTAL_AD_DATA_BYTES = 16;
-
-    private static final int TRUNCATED_BYTES = 3;
-
-    private static final String TIMEOUT_HANDLER_THREAD_NAME = "peripheralThread";
-
-    private final BluetoothGattDescriptor mDescriptor =
-            new BluetoothGattDescriptor(CLIENT_CHARACTERISTIC_CONFIG,
-                    BluetoothGattDescriptor.PERMISSION_READ
-                            | BluetoothGattDescriptor.PERMISSION_WRITE);
-
-    private final BlePeripheralManager mBlePeripheralManager;
-
-    private final UUID mAssociationServiceUuid;
-
-    private final UUID mReconnectServiceUuid;
-
-    private final UUID mReconnectDataUuid;
-
-    private final BluetoothGattCharacteristic mWriteCharacteristic;
-
-    private final BluetoothGattCharacteristic mReadCharacteristic;
-
-    private HandlerThread mTimeoutHandlerThread;
-
-    private Handler mTimeoutHandler;
-
-    private final Duration mMaxReconnectAdvertisementDuration;
-
-    private final int mDefaultMtuSize;
-
-    private String mClientDeviceName;
-
-    private String mClientDeviceAddress;
-
-    private String mReconnectDeviceId;
-
-    private byte[] mReconnectChallenge;
-
-    private AssociationCallback mAssociationCallback;
-
-    private AdvertiseCallback mAdvertiseCallback;
-
-    /**
-     * Initialize a new instance of manager.
-     *
-     * @param blePeripheralManager    {@link BlePeripheralManager} for establishing connection.
-     * @param connectedDeviceStorage  Shared {@link ConnectedDeviceStorage} for companion features.
-     * @param associationServiceUuid  {@link UUID} of association service.
-     * @param reconnectServiceUuid    {@link UUID} of reconnect service.
-     * @param reconnectDataUuid       {@link UUID} key of reconnect advertisement data.
-     * @param writeCharacteristicUuid {@link UUID} of characteristic the car will write to.
-     * @param readCharacteristicUuid  {@link UUID} of characteristic the device will write to.
-     * @param maxReconnectAdvertisementDuration Maximum duration to advertise for reconnect before
-     *                                          restarting.
-     * @param defaultMtuSize          Default MTU size for new channels.
-     */
-    public CarBlePeripheralManager(@NonNull BlePeripheralManager blePeripheralManager,
-            @NonNull ConnectedDeviceStorage connectedDeviceStorage,
-            @NonNull UUID associationServiceUuid,
-            @NonNull UUID reconnectServiceUuid,
-            @NonNull UUID reconnectDataUuid,
-            @NonNull UUID writeCharacteristicUuid,
-            @NonNull UUID readCharacteristicUuid,
-            @NonNull Duration maxReconnectAdvertisementDuration,
-            int defaultMtuSize) {
-        super(connectedDeviceStorage);
-        mBlePeripheralManager = blePeripheralManager;
-        mAssociationServiceUuid = associationServiceUuid;
-        mReconnectServiceUuid = reconnectServiceUuid;
-        mReconnectDataUuid = reconnectDataUuid;
-        mDescriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
-        mWriteCharacteristic = new BluetoothGattCharacteristic(writeCharacteristicUuid,
-                BluetoothGattCharacteristic.PROPERTY_NOTIFY,
-                BluetoothGattCharacteristic.PROPERTY_READ);
-        mReadCharacteristic = new BluetoothGattCharacteristic(readCharacteristicUuid,
-                BluetoothGattCharacteristic.PROPERTY_WRITE
-                        | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
-                BluetoothGattCharacteristic.PERMISSION_WRITE);
-        mReadCharacteristic.addDescriptor(mDescriptor);
-        mMaxReconnectAdvertisementDuration = maxReconnectAdvertisementDuration;
-        mDefaultMtuSize = defaultMtuSize;
-    }
-
-    @Override
-    public void start() {
-        super.start();
-        mTimeoutHandlerThread = new HandlerThread(TIMEOUT_HANDLER_THREAD_NAME);
-        mTimeoutHandlerThread.start();
-        mTimeoutHandler = new Handler(mTimeoutHandlerThread.getLooper());
-    }
-
-    @Override
-    public void stop() {
-        super.stop();
-        mTimeoutHandlerThread.quit();
-        reset();
-    }
-
-    @Override
-    public void disconnectDevice(@NonNull String deviceId) {
-        if (deviceId.equals(mReconnectDeviceId)) {
-            logd(TAG, "Reconnection canceled for device " + deviceId + ".");
-            reset();
-            return;
-        }
-        BleDevice connectedDevice = getConnectedDevice();
-        if (connectedDevice == null || !deviceId.equals(connectedDevice.mDeviceId)) {
-            return;
-        }
-        reset();
-    }
-
-    private void reset() {
-        mClientDeviceAddress = null;
-        mClientDeviceName = null;
-        mAssociationCallback = null;
-        mBlePeripheralManager.cleanup();
-        mConnectedDevices.clear();
-        mReconnectDeviceId = null;
-        mReconnectChallenge = null;
-    }
-
-    /** Attempt to connect to device with provided id. */
-    public void connectToDevice(@NonNull UUID deviceId) {
-        for (BleDevice device : mConnectedDevices) {
-            if (UUID.fromString(device.mDeviceId).equals(deviceId)) {
-                logd(TAG, "Already connected to device " + deviceId + ".");
-                // Already connected to this device. Ignore requests to connect again.
-                return;
-            }
-        }
-
-        // Clear any previous session before starting a new one.
-        reset();
-        mReconnectDeviceId = deviceId.toString();
-        mAdvertiseCallback = new AdvertiseCallback() {
-            @Override
-            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
-                super.onStartSuccess(settingsInEffect);
-                mTimeoutHandler.postDelayed(mTimeoutRunnable,
-                        mMaxReconnectAdvertisementDuration.toMillis());
-                logd(TAG, "Successfully started advertising for device " + deviceId + ".");
-            }
-        };
-        mBlePeripheralManager.unregisterCallback(mAssociationPeripheralCallback);
-        mBlePeripheralManager.registerCallback(mReconnectPeripheralCallback);
-        mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
-        byte[] advertiseData = createReconnectData(mReconnectDeviceId);
-        if (advertiseData == null) {
-            loge(TAG, "Unable to create advertisement data. Aborting reconnect.");
-            return;
-        }
-        startAdvertising(mReconnectServiceUuid, mAdvertiseCallback, advertiseData,
-                mReconnectDataUuid, /* scanResponse= */null, /* scanResponseUuid */ null);
-    }
-
-    /**
-     * Create data for reconnection advertisement.
-     *
-     * <p></p><p>Process:</p>
-     * <ol>
-     * <li>Generate random {@value SALT_BYTES} byte salt and zero-pad to
-     * {@value TOTAL_AD_DATA_BYTES} bytes.
-     * <li>Hash with stored challenge secret and truncate to {@value TRUNCATED_BYTES} bytes.
-     * <li>Concatenate hashed {@value TRUNCATED_BYTES} bytes with salt and return.
-     * </ol>
-     */
-    @Nullable
-    private byte[] createReconnectData(String deviceId) {
-        byte[] salt = ByteUtils.randomBytes(SALT_BYTES);
-        byte[] zeroPadded = ByteUtils.concatByteArrays(salt,
-                new byte[TOTAL_AD_DATA_BYTES - SALT_BYTES]);
-        mReconnectChallenge = mStorage.hashWithChallengeSecret(deviceId, zeroPadded);
-        if (mReconnectChallenge == null) {
-            return null;
-        }
-        return ByteUtils.concatByteArrays(Arrays.copyOf(mReconnectChallenge, TRUNCATED_BYTES),
-                salt);
-
-    }
-
-    @Nullable
-    private BleDevice getConnectedDevice() {
-        if (mConnectedDevices.isEmpty()) {
-            return null;
-        }
-        return mConnectedDevices.iterator().next();
-    }
-
-    /** Start the association with a new device */
-    public void startAssociation(@NonNull String nameForAssociation,
-            @NonNull AssociationCallback callback) {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        if (adapter == null) {
-            loge(TAG, "Bluetooth is unavailable on this device. Unable to start associating.");
-            return;
-        }
-
-        reset();
-        mAssociationCallback = callback;
-        mBlePeripheralManager.unregisterCallback(mReconnectPeripheralCallback);
-        mBlePeripheralManager.registerCallback(mAssociationPeripheralCallback);
-        mAdvertiseCallback = new AdvertiseCallback() {
-            @Override
-            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
-                super.onStartSuccess(settingsInEffect);
-                callback.onAssociationStartSuccess(nameForAssociation);
-                logd(TAG, "Successfully started advertising for association.");
-            }
-
-            @Override
-            public void onStartFailure(int errorCode) {
-                super.onStartFailure(errorCode);
-                callback.onAssociationStartFailure();
-                logd(TAG, "Failed to start advertising for association. Error code: " + errorCode);
-            }
-        };
-        startAdvertising(mAssociationServiceUuid, mAdvertiseCallback, /* advertiseData= */ null,
-                /* advertiseDataUuid*/ null, nameForAssociation.getBytes(), mReconnectDataUuid);
-    }
-
-    /** Stop the association with any device. */
-    public void stopAssociation(@NonNull AssociationCallback callback) {
-        if (!isAssociating() || callback != mAssociationCallback) {
-            return;
-        }
-        reset();
-    }
-
-    private void startAdvertising(@NonNull UUID serviceUuid, @NonNull AdvertiseCallback callback,
-            @Nullable byte[] advertiseData, @Nullable UUID advertiseDataUuid,
-            @Nullable byte[] scanResponse, @Nullable UUID scanResponseUuid) {
-        BluetoothGattService gattService = new BluetoothGattService(serviceUuid,
-                BluetoothGattService.SERVICE_TYPE_PRIMARY);
-        gattService.addCharacteristic(mWriteCharacteristic);
-        gattService.addCharacteristic(mReadCharacteristic);
-
-        AdvertiseData.Builder advertisementBuilder = new AdvertiseData.Builder();
-        ParcelUuid uuid = new ParcelUuid(serviceUuid);
-        advertisementBuilder.addServiceUuid(uuid);
-        if (advertiseData != null) {
-            ParcelUuid dataUuid = uuid;
-            if (advertiseDataUuid != null) {
-                dataUuid = new ParcelUuid(advertiseDataUuid);
-            }
-            advertisementBuilder.addServiceData(dataUuid, advertiseData);
-        }
-
-        AdvertiseData.Builder scanResponseBuilder = new AdvertiseData.Builder();
-        if (scanResponse != null && scanResponseUuid != null) {
-            ParcelUuid scanResponseParcelUuid = new ParcelUuid(scanResponseUuid);
-            scanResponseBuilder.addServiceData(scanResponseParcelUuid, scanResponse);
-        }
-
-        mBlePeripheralManager.startAdvertising(gattService, advertisementBuilder.build(),
-                scanResponseBuilder.build(), callback);
-    }
-
-    /** Notify that the user has accepted a pairing code or other out-of-band confirmation. */
-    public void notifyOutOfBandAccepted() {
-        if (getConnectedDevice() == null) {
-            disconnectWithError("Null connected device found when out-of-band confirmation "
-                    + "received.");
-            return;
-        }
-
-        AssociationSecureChannel secureChannel =
-                (AssociationSecureChannel) getConnectedDevice().mSecureChannel;
-        if (secureChannel == null) {
-            disconnectWithError("Null SecureBleChannel found for the current connected device "
-                    + "when out-of-band confirmation received.");
-            return;
-        }
-
-        secureChannel.notifyOutOfBandAccepted();
-    }
-
-    @VisibleForTesting
-    @Nullable
-    SecureBleChannel getConnectedDeviceChannel() {
-        BleDevice connectedDevice = getConnectedDevice();
-        if (connectedDevice == null) {
-            return null;
-        }
-
-        return connectedDevice.mSecureChannel;
-    }
-
-    private void setDeviceId(@NonNull String deviceId) {
-        logd(TAG, "Setting device id: " + deviceId);
-        BleDevice connectedDevice = getConnectedDevice();
-        if (connectedDevice == null) {
-            disconnectWithError("Null connected device found when device id received.");
-            return;
-        }
-
-        connectedDevice.mDeviceId = deviceId;
-        mCallbacks.invoke(callback -> callback.onDeviceConnected(deviceId));
-    }
-
-    private void disconnectWithError(@NonNull String errorMessage) {
-        loge(TAG, errorMessage);
-        if (isAssociating()) {
-            mAssociationCallback.onAssociationError(DEVICE_ERROR_INVALID_HANDSHAKE);
-        }
-        reset();
-    }
-
-    private void addConnectedDevice(BluetoothDevice device, boolean isReconnect) {
-        EventLog.onDeviceConnected();
-        mBlePeripheralManager.stopAdvertising(mAdvertiseCallback);
-        mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
-        mClientDeviceAddress = device.getAddress();
-        mClientDeviceName = device.getName();
-        if (mClientDeviceName == null) {
-            logd(TAG, "Device connected, but name is null; issuing request to retrieve device "
-                    + "name.");
-            mBlePeripheralManager.retrieveDeviceName(device);
-        }
-
-        BleDeviceMessageStream secureStream = new BleDeviceMessageStream(mBlePeripheralManager,
-                device, mWriteCharacteristic, mReadCharacteristic,
-                mDefaultMtuSize - ATT_PROTOCOL_BYTES);
-        secureStream.setMessageReceivedErrorListener(
-                exception -> {
-                    disconnectWithError("Error occurred in stream: " + exception.getMessage());
-                });
-        SecureBleChannel secureChannel;
-        if (isReconnect) {
-            secureChannel = new ReconnectSecureChannel(secureStream, mStorage, mReconnectDeviceId,
-                    mReconnectChallenge);
-        } else {
-            secureChannel = new AssociationSecureChannel(secureStream, mStorage);
-        }
-        secureChannel.registerCallback(mSecureChannelCallback);
-        BleDevice bleDevice = new BleDevice(device, /* gatt= */ null);
-        bleDevice.mSecureChannel = secureChannel;
-        addConnectedDevice(bleDevice);
-        if (isReconnect) {
-            setDeviceId(mReconnectDeviceId);
-            mReconnectDeviceId = null;
-            mReconnectChallenge = null;
-        }
-    }
-
-    private void setMtuSize(int mtuSize) {
-        BleDevice connectedDevice = getConnectedDevice();
-        if (connectedDevice != null
-                && connectedDevice.mSecureChannel != null
-                && connectedDevice.mSecureChannel.getStream() != null) {
-            connectedDevice.mSecureChannel.getStream()
-                    .setMaxWriteSize(mtuSize - ATT_PROTOCOL_BYTES);
-        }
-    }
-
-    private boolean isAssociating() {
-        return mAssociationCallback != null;
-    }
-
-    private final BlePeripheralManager.Callback mReconnectPeripheralCallback =
-            new BlePeripheralManager.Callback() {
-
-                @Override
-                public void onDeviceNameRetrieved(String deviceName) {
-                    // Ignored.
-                }
-
-                @Override
-                public void onMtuSizeChanged(int size) {
-                    setMtuSize(size);
-                }
-
-                @Override
-                public void onRemoteDeviceConnected(BluetoothDevice device) {
-                    addConnectedDevice(device, /* isReconnect= */ true);
-                }
-
-                @Override
-                public void onRemoteDeviceDisconnected(BluetoothDevice device) {
-                    String deviceId = mReconnectDeviceId;
-                    BleDevice connectedDevice = getConnectedDevice(device);
-                    // Reset before invoking callbacks to avoid a race condition with reconnect
-                    // logic.
-                    reset();
-                    if (connectedDevice != null) {
-                        deviceId = connectedDevice.mDeviceId;
-                    }
-                    final String finalDeviceId = deviceId;
-                    if (finalDeviceId == null) {
-                        logw(TAG, "Callbacks were not issued for disconnect because the device id "
-                                + "was null.");
-                        return;
-                    }
-                    logd(TAG, "Connected device " + finalDeviceId + " disconnected.");
-                    mCallbacks.invoke(callback -> callback.onDeviceDisconnected(finalDeviceId));
-                }
-            };
-
-    private final BlePeripheralManager.Callback mAssociationPeripheralCallback =
-            new BlePeripheralManager.Callback() {
-                @Override
-                public void onDeviceNameRetrieved(String deviceName) {
-                    if (deviceName == null) {
-                        return;
-                    }
-                    mClientDeviceName = deviceName;
-                    BleDevice connectedDevice = getConnectedDevice();
-                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
-                        return;
-                    }
-                    mStorage.updateAssociatedDeviceName(connectedDevice.mDeviceId, deviceName);
-                }
-
-                @Override
-                public void onMtuSizeChanged(int size) {
-                    setMtuSize(size);
-                }
-
-                @Override
-                public void onRemoteDeviceConnected(BluetoothDevice device) {
-                    addConnectedDevice(device, /* isReconnect= */ false);
-                    BleDevice connectedDevice = getConnectedDevice();
-                    if (connectedDevice == null || connectedDevice.mSecureChannel == null) {
-                        return;
-                    }
-                    ((AssociationSecureChannel) connectedDevice.mSecureChannel)
-                            .setShowVerificationCodeListener(
-                                    code -> {
-                                        if (!isAssociating()) {
-                                            loge(TAG, "No valid callback for association.");
-                                            return;
-                                        }
-                                        mAssociationCallback.onVerificationCodeAvailable(code);
-                                    });
-                }
-
-                @Override
-                public void onRemoteDeviceDisconnected(BluetoothDevice device) {
-                    logd(TAG, "Remote device disconnected.");
-                    BleDevice connectedDevice = getConnectedDevice(device);
-                    if (isAssociating()) {
-                        mAssociationCallback.onAssociationError(
-                                DEVICE_ERROR_UNEXPECTED_DISCONNECTION);
-                    }
-                    // Reset before invoking callbacks to avoid a race condition with reconnect
-                    // logic.
-                    reset();
-                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
-                        logw(TAG, "Callbacks were not issued for disconnect.");
-                        return;
-                    }
-                    mCallbacks.invoke(callback -> callback.onDeviceDisconnected(
-                            connectedDevice.mDeviceId));
-                }
-            };
-
-    private final SecureBleChannel.Callback mSecureChannelCallback =
-            new SecureBleChannel.Callback() {
-                @Override
-                public void onSecureChannelEstablished() {
-                    BleDevice connectedDevice = getConnectedDevice();
-                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
-                        disconnectWithError("Null device id found when secure channel "
-                                + "established.");
-                        return;
-                    }
-                    String deviceId = connectedDevice.mDeviceId;
-                    if (mClientDeviceAddress == null) {
-                        disconnectWithError("Null device address found when secure channel "
-                                + "established.");
-                        return;
-                    }
-                    if (isAssociating()) {
-                        logd(TAG, "Secure channel established for un-associated device. Saving "
-                                + "association of that device for current user.");
-                        mStorage.addAssociatedDeviceForActiveUser(
-                                new AssociatedDevice(deviceId, mClientDeviceAddress,
-                                        mClientDeviceName, /* isConnectionEnabled= */ true));
-                        if (mAssociationCallback != null) {
-                            mAssociationCallback.onAssociationCompleted(deviceId);
-                            mAssociationCallback = null;
-                        }
-                    }
-                    mCallbacks.invoke(callback -> callback.onSecureChannelEstablished(deviceId));
-                }
-
-                @Override
-                public void onEstablishSecureChannelFailure(int error) {
-                    BleDevice connectedDevice = getConnectedDevice();
-                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
-                        disconnectWithError("Null device id found when secure channel failed to "
-                                + "establish.");
-                        return;
-                    }
-                    String deviceId = connectedDevice.mDeviceId;
-                    mCallbacks.invoke(callback -> callback.onSecureChannelError(deviceId));
-
-                    if (isAssociating()) {
-                        mAssociationCallback.onAssociationError(error);
-                    }
-
-                    disconnectWithError("Error while establishing secure connection.");
-                }
-
-                @Override
-                public void onMessageReceived(DeviceMessage deviceMessage) {
-                    BleDevice connectedDevice = getConnectedDevice();
-                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
-                        disconnectWithError("Null device id found when message received.");
-                        return;
-                    }
-
-                    logd(TAG, "Received new message from " + connectedDevice.mDeviceId
-                            + " with " + deviceMessage.getMessage().length + " bytes in its "
-                            + "payload. Notifying " + mCallbacks.size() + " callbacks.");
-                    mCallbacks.invoke(
-                            callback -> callback.onMessageReceived(connectedDevice.mDeviceId,
-                                    deviceMessage));
-                }
-
-                @Override
-                public void onMessageReceivedError(Exception exception) {
-                    // TODO(b/143879960) Extend the message error from here to continue up the
-                    // chain.
-                    disconnectWithError("Error while receiving message.");
-                }
-
-                @Override
-                public void onDeviceIdReceived(String deviceId) {
-                    if (deviceId == null) {
-                        loge(TAG, "Received a null device id. Ignoring.");
-                        return;
-                    }
-                    setDeviceId(deviceId);
-                }
-            };
-
-    private final Runnable mTimeoutRunnable = new Runnable() {
-        @Override
-        public void run() {
-            logd(TAG, "Timeout period expired without a connection. Restarting advertisement.");
-            mBlePeripheralManager.stopAdvertising(mAdvertiseCallback);
-            connectToDevice(UUID.fromString(mReconnectDeviceId));
-        }
-    };
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/DeviceMessage.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/DeviceMessage.java
deleted file mode 100644
index a746864..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/DeviceMessage.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.BleStreamProtos.BleDeviceMessageProto.BleDeviceMessage;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.UUID;
-
-/** Holds the needed data from a {@link BleDeviceMessage}. */
-public class DeviceMessage {
-
-    private static final String TAG = "DeviceMessage";
-
-    private final UUID mRecipient;
-
-    private final boolean mIsMessageEncrypted;
-
-    private byte[] mMessage;
-
-    public DeviceMessage(@Nullable UUID recipient, boolean isMessageEncrypted,
-            @NonNull byte[] message) {
-        mRecipient = recipient;
-        mIsMessageEncrypted = isMessageEncrypted;
-        mMessage = message;
-    }
-
-    /** Returns the recipient for this message. {@code null} if no recipient set. */
-    @Nullable
-    public UUID getRecipient() {
-        return mRecipient;
-    }
-
-    /** Returns whether this message is encrypted. */
-    public boolean isMessageEncrypted() {
-        return mIsMessageEncrypted;
-    }
-
-    /** Returns the message payload. */
-    @Nullable
-    public byte[] getMessage() {
-        return mMessage;
-    }
-
-    /** Set the message payload. */
-    public void setMessage(@NonNull byte[] message) {
-        mMessage = message;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-        if (!(obj instanceof DeviceMessage)) {
-            return false;
-        }
-        DeviceMessage deviceMessage = (DeviceMessage) obj;
-        return Objects.equals(mRecipient, deviceMessage.mRecipient)
-                && mIsMessageEncrypted == deviceMessage.mIsMessageEncrypted
-                && Arrays.equals(mMessage, deviceMessage.mMessage);
-    }
-
-    @Override
-    public int hashCode() {
-        return 31 * Objects.hash(mRecipient, mIsMessageEncrypted)
-                + Arrays.hashCode(mMessage);
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/ReconnectSecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/ReconnectSecureChannel.java
deleted file mode 100644
index 60eff1c..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/ReconnectSecureChannel.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-
-import android.car.encryptionrunner.EncryptionRunner;
-import android.car.encryptionrunner.EncryptionRunnerFactory;
-import android.car.encryptionrunner.HandshakeException;
-import android.car.encryptionrunner.HandshakeMessage;
-import android.car.encryptionrunner.HandshakeMessage.HandshakeState;
-import android.car.encryptionrunner.Key;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-import com.android.car.connecteddevice.util.ByteUtils;
-
-import java.util.Arrays;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * A secure channel established with the reconnection flow.
- */
-class ReconnectSecureChannel extends SecureBleChannel {
-
-    private static final String TAG = "ReconnectSecureChannel";
-
-    private final ConnectedDeviceStorage mStorage;
-
-    private final String mDeviceId;
-
-    private final byte[] mExpectedChallengeResponse;
-
-    @HandshakeState
-    private int mState = HandshakeState.UNKNOWN;
-
-    private AtomicBoolean mHasVerifiedDevice = new AtomicBoolean(false);
-
-    /**
-     * Create a new secure reconnection channel.
-     *
-     * @param stream The {@link BleDeviceMessageStream} for communication with the device.
-     * @param storage {@link ConnectedDeviceStorage} for secure storage.
-     * @param deviceId Id of the device being reconnected.
-     * @param expectedChallengeResponse Expected response to challenge issued in reconnect.
-     */
-    ReconnectSecureChannel(@NonNull BleDeviceMessageStream stream,
-            @NonNull ConnectedDeviceStorage storage, @NonNull String deviceId,
-            @NonNull byte[] expectedChallengeResponse) {
-        super(stream, newReconnectRunner());
-        mStorage = storage;
-        mDeviceId = deviceId;
-        mExpectedChallengeResponse = expectedChallengeResponse;
-    }
-
-    private static EncryptionRunner newReconnectRunner() {
-        EncryptionRunner encryptionRunner = EncryptionRunnerFactory.newRunner();
-        encryptionRunner.setIsReconnect(true);
-        return encryptionRunner;
-    }
-
-    @Override
-    void processHandshake(byte[] message) throws HandshakeException {
-        switch (mState) {
-            case HandshakeState.UNKNOWN:
-                if (!mHasVerifiedDevice.get()) {
-                    processHandshakeDeviceVerification(message);
-                } else {
-                    processHandshakeInitialization(message);
-                }
-                break;
-            case HandshakeState.IN_PROGRESS:
-                processHandshakeInProgress(message);
-                break;
-            case HandshakeState.RESUMING_SESSION:
-                processHandshakeResumingSession(message);
-                break;
-            default:
-                loge(TAG, "Encountered unexpected handshake state: " + mState + ".");
-                notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-        }
-    }
-
-    private void processHandshakeDeviceVerification(byte[] message) {
-        byte[] challengeResponse = Arrays.copyOf(message,
-                mExpectedChallengeResponse.length);
-        byte[] deviceChallenge = Arrays.copyOfRange(message,
-                mExpectedChallengeResponse.length, message.length);
-        if (!Arrays.equals(mExpectedChallengeResponse, challengeResponse)) {
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
-            return;
-        }
-        logd(TAG, "Responding to challenge " + ByteUtils.byteArrayToHexString(deviceChallenge)
-                + ".");
-        byte[] deviceChallengeResponse = mStorage.hashWithChallengeSecret(mDeviceId,
-                deviceChallenge);
-        if (deviceChallengeResponse == null) {
-            notifySecureChannelFailure(CHANNEL_ERROR_STORAGE_ERROR);
-        }
-        sendHandshakeMessage(deviceChallengeResponse, /* isEncrypted= */ false);
-        mHasVerifiedDevice.set(true);
-    }
-
-    private void processHandshakeInitialization(byte[] message) throws HandshakeException {
-        logd(TAG, "Responding to handshake init request.");
-        HandshakeMessage handshakeMessage = getEncryptionRunner().respondToInitRequest(message);
-        mState = handshakeMessage.getHandshakeState();
-        sendHandshakeMessage(handshakeMessage.getNextMessage(), /* isEncrypted= */ false);
-    }
-
-    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
-        logd(TAG, "Continuing handshake.");
-        HandshakeMessage handshakeMessage = getEncryptionRunner().continueHandshake(message);
-        mState = handshakeMessage.getHandshakeState();
-    }
-
-    private void processHandshakeResumingSession(@NonNull byte[] message)
-            throws HandshakeException {
-        logd(TAG, "Start reconnection authentication.");
-
-        byte[] previousKey = mStorage.getEncryptionKey(mDeviceId);
-        if (previousKey == null) {
-            loge(TAG, "Unable to resume session, previous key is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
-            return;
-        }
-
-        HandshakeMessage handshakeMessage = getEncryptionRunner().authenticateReconnection(message,
-                previousKey);
-        mState = handshakeMessage.getHandshakeState();
-        if (mState != HandshakeState.FINISHED) {
-            loge(TAG, "Unable to resume session, unexpected next handshake state: " + mState + ".");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
-            return;
-        }
-
-        Key newKey = handshakeMessage.getKey();
-        if (newKey == null) {
-            loge(TAG, "Unable to resume session, new key is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
-            return;
-        }
-
-        logd(TAG, "Saved new key for reconnection.");
-        mStorage.saveEncryptionKey(mDeviceId, newKey.asBytes());
-        setEncryptionKey(newKey);
-        sendServerAuthToClient(handshakeMessage.getNextMessage());
-        notifyCallback(Callback::onSecureChannelEstablished);
-    }
-
-    private void sendServerAuthToClient(@Nullable byte[] message) {
-        if (message == null) {
-            loge(TAG, "Unable to send server authentication message to client, message is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_MSG);
-            return;
-        }
-
-        sendHandshakeMessage(message, /* isEncrypted= */ false);
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
deleted file mode 100644
index c0012a0..0000000
--- a/connected-device-lib/src/com/android/car/connecteddevice/ble/SecureBleChannel.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.util.SafeLog.logd;
-import static com.android.car.connecteddevice.util.SafeLog.loge;
-
-import android.car.encryptionrunner.EncryptionRunner;
-import android.car.encryptionrunner.HandshakeException;
-import android.car.encryptionrunner.Key;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.security.SignatureException;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
-
-/**
- * Establishes a secure channel with {@link EncryptionRunner} over {@link BleDeviceMessageStream} as
- * server side, sends and receives messages securely after the secure channel has been established.
- */
-abstract class SecureBleChannel {
-
-    private static final String TAG = "SecureBleChannel";
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            CHANNEL_ERROR_INVALID_HANDSHAKE,
-            CHANNEL_ERROR_INVALID_MSG,
-            CHANNEL_ERROR_INVALID_DEVICE_ID,
-            CHANNEL_ERROR_INVALID_VERIFICATION,
-            CHANNEL_ERROR_INVALID_STATE,
-            CHANNEL_ERROR_INVALID_ENCRYPTION_KEY,
-            CHANNEL_ERROR_STORAGE_ERROR
-    })
-    @interface ChannelError { }
-
-    /** Indicates an error during a Handshake of EncryptionRunner. */
-    static final int CHANNEL_ERROR_INVALID_HANDSHAKE = 0;
-    /** Received an invalid handshake message or has an invalid handshake message to send. */
-    static final int CHANNEL_ERROR_INVALID_MSG = 1;
-    /** Unable to retrieve a valid id. */
-    static final int CHANNEL_ERROR_INVALID_DEVICE_ID = 2;
-    /** Unable to get verification code or there's a error during pin verification. */
-    static final int CHANNEL_ERROR_INVALID_VERIFICATION = 3;
-    /** Encountered an unexpected handshake state. */
-    static final int CHANNEL_ERROR_INVALID_STATE = 4;
-    /** Failed to get a valid previous/new encryption key. */
-    static final int CHANNEL_ERROR_INVALID_ENCRYPTION_KEY = 5;
-    /** Failed to save or retrieve security keys. */
-    static final int CHANNEL_ERROR_STORAGE_ERROR = 6;
-
-
-    private final BleDeviceMessageStream mStream;
-
-    private final EncryptionRunner mEncryptionRunner;
-
-    private final AtomicReference<Key> mEncryptionKey = new AtomicReference<>();
-
-    private Callback mCallback;
-
-    SecureBleChannel(@NonNull BleDeviceMessageStream stream,
-            @NonNull EncryptionRunner encryptionRunner) {
-        mStream = stream;
-        mEncryptionRunner = encryptionRunner;
-        mStream.setMessageReceivedListener(this::onMessageReceived);
-    }
-
-    /** Logic for processing a handshake message from device. */
-    abstract void processHandshake(byte[] message) throws HandshakeException;
-
-    void sendHandshakeMessage(@Nullable byte[] message, boolean isEncrypted) {
-        if (message == null) {
-            loge(TAG, "Unable to send next handshake message, message is null.");
-            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_MSG);
-            return;
-        }
-
-        logd(TAG, "Sending handshake message.");
-        DeviceMessage deviceMessage = new DeviceMessage(/* recipient= */ null,
-                isEncrypted, message);
-        if (deviceMessage.isMessageEncrypted()) {
-            encryptMessage(deviceMessage);
-        }
-        mStream.writeMessage(deviceMessage, OperationType.ENCRYPTION_HANDSHAKE);
-    }
-
-    /** Set the encryption key that secures this channel. */
-    void setEncryptionKey(@Nullable Key encryptionKey) {
-        mEncryptionKey.set(encryptionKey);
-    }
-
-    /**
-     * Send a client message.
-     * <p>Note: This should be called with an encrypted message only after the secure channel has
-     * been established.</p>
-     *
-     * @param deviceMessage The {@link DeviceMessage} to send.
-     */
-    void sendClientMessage(@NonNull DeviceMessage deviceMessage)
-            throws IllegalStateException {
-        if (deviceMessage.isMessageEncrypted()) {
-            encryptMessage(deviceMessage);
-        }
-        mStream.writeMessage(deviceMessage, OperationType.CLIENT_MESSAGE);
-    }
-
-    private void encryptMessage(@NonNull DeviceMessage deviceMessage) {
-        Key key = mEncryptionKey.get();
-        if (key == null) {
-            throw new IllegalStateException("Secure channel has not been established.");
-        }
-
-        byte[] encryptedMessage = key.encryptData(deviceMessage.getMessage());
-        deviceMessage.setMessage(encryptedMessage);
-    }
-
-    /** Get the BLE stream backing this channel. */
-    @NonNull
-    BleDeviceMessageStream getStream() {
-        return mStream;
-    }
-
-    /** Register a callback that notifies secure channel events. */
-    void registerCallback(Callback callback) {
-        mCallback = callback;
-    }
-
-    /** Unregister a callback. */
-    void unregisterCallback(Callback callback) {
-        if (callback == mCallback) {
-            mCallback = null;
-        }
-    }
-
-    @VisibleForTesting
-    @Nullable
-    Callback getCallback() {
-        return mCallback;
-    }
-
-    void notifyCallback(@NonNull Consumer<Callback> notification) {
-        if (mCallback != null) {
-            notification.accept(mCallback);
-        }
-    }
-
-    /** Notify callbacks that an error has occurred. */
-    void notifySecureChannelFailure(@ChannelError int error) {
-        loge(TAG, "Secure channel error: " + error);
-        notifyCallback(callback -> callback.onEstablishSecureChannelFailure(error));
-    }
-
-    /** Return the {@link EncryptionRunner} for this channel. */
-    @NonNull
-    EncryptionRunner getEncryptionRunner() {
-        return mEncryptionRunner;
-    }
-
-    /**
-     * Process the inner message and replace with decrypted value if necessary. If an error occurs
-     * the inner message will be replaced with {@code null} and call
-     * {@link Callback#onMessageReceivedError(Exception)} on the registered callback.
-     *
-     * @param deviceMessage The message to process.
-     * @return {@code true} if message was successfully processed. {@code false} if an error
-     * occurred.
-     */
-    @VisibleForTesting
-    boolean processMessage(@NonNull DeviceMessage deviceMessage) {
-        if (!deviceMessage.isMessageEncrypted()) {
-            logd(TAG, "Message was not decrypted. No further action necessary.");
-            return true;
-        }
-        Key key = mEncryptionKey.get();
-        if (key == null) {
-            loge(TAG, "Received encrypted message before secure channel has "
-                    + "been established.");
-            notifyCallback(callback -> callback.onMessageReceivedError(null));
-            deviceMessage.setMessage(null);
-            return false;
-        }
-        try {
-            byte[] decryptedMessage = key.decryptData(deviceMessage.getMessage());
-            deviceMessage.setMessage(decryptedMessage);
-            logd(TAG, "Decrypted secure message.");
-            return true;
-        } catch (SignatureException e) {
-            loge(TAG, "Could not decrypt client credentials.", e);
-            notifyCallback(callback -> callback.onMessageReceivedError(e));
-            deviceMessage.setMessage(null);
-
-            return false;
-        }
-    }
-
-    @VisibleForTesting
-    void onMessageReceived(@NonNull DeviceMessage deviceMessage, OperationType operationType) {
-        boolean success = processMessage(deviceMessage);
-        switch(operationType) {
-            case ENCRYPTION_HANDSHAKE:
-                if (!success) {
-                    notifyCallback(callback -> callback.onEstablishSecureChannelFailure(
-                            CHANNEL_ERROR_INVALID_HANDSHAKE));
-                    break;
-                }
-                logd(TAG, "Received handshake message.");
-                try {
-                    processHandshake(deviceMessage.getMessage());
-                } catch (HandshakeException e) {
-                    loge(TAG, "Handshake failed.", e);
-                    notifyCallback(callback -> callback.onEstablishSecureChannelFailure(
-                            CHANNEL_ERROR_INVALID_HANDSHAKE));
-                }
-                break;
-            case CLIENT_MESSAGE:
-                if (!success || deviceMessage.getMessage() == null) {
-                    break;
-                }
-                logd(TAG, "Received client message.");
-                notifyCallback(
-                        callback -> callback.onMessageReceived(deviceMessage));
-                break;
-            default:
-                loge(TAG, "Received unexpected operation type: " + operationType + ".");
-        }
-    }
-
-    /**
-     * Callbacks that will be invoked during establishing secure channel, sending and receiving
-     * messages securely.
-     */
-    interface Callback {
-        /**
-         * Invoked when secure channel has been established successfully.
-         */
-        default void onSecureChannelEstablished() { }
-
-        /**
-         * Invoked when a {@link ChannelError} has been encountered in attempting to establish
-         * a secure channel.
-         *
-         * @param error The failure indication.
-         */
-        default void onEstablishSecureChannelFailure(@SecureBleChannel.ChannelError int error) { }
-
-        /**
-         * Invoked when a complete message is received securely from the client and decrypted.
-         *
-         * @param deviceMessage The {@link DeviceMessage} with decrypted message.
-         */
-        default void onMessageReceived(@NonNull DeviceMessage deviceMessage) { }
-
-        /**
-         * Invoked when there was an error during a processing or decrypting of a client message.
-         *
-         * @param exception The error.
-         */
-        default void onMessageReceivedError(@Nullable Exception exception) { }
-
-        /**
-         * Invoked when the device id was received from the client.
-         *
-         * @param deviceId The unique device id of client.
-         */
-        default void onDeviceIdReceived(@NonNull String deviceId) { }
-    }
-}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/AssociationSecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/AssociationSecureChannel.java
new file mode 100644
index 0000000..65a05da
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/AssociationSecureChannel.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static android.car.encryptionrunner.EncryptionRunnerFactory.EncryptionRunnerType;
+import static android.car.encryptionrunner.EncryptionRunnerFactory.newRunner;
+import static android.car.encryptionrunner.HandshakeMessage.HandshakeState;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.HandshakeMessage;
+import android.car.encryptionrunner.Key;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.UUID;
+
+/**
+ * A secure channel established with the association flow.
+ */
+public class AssociationSecureChannel extends SecureChannel {
+
+    private static final String TAG = "AssociationSecureChannel";
+
+    private static final int DEVICE_ID_BYTES = 16;
+
+    private final ConnectedDeviceStorage mStorage;
+
+    private ShowVerificationCodeListener mShowVerificationCodeListener;
+
+    @HandshakeState
+    private int mState = HandshakeState.UNKNOWN;
+
+    private Key mPendingKey;
+
+    private String mDeviceId;
+
+    public AssociationSecureChannel(DeviceMessageStream stream, ConnectedDeviceStorage storage) {
+        this(stream, storage, newRunner(EncryptionRunnerType.UKEY2));
+    }
+
+    AssociationSecureChannel(DeviceMessageStream stream, ConnectedDeviceStorage storage,
+            EncryptionRunner encryptionRunner) {
+        super(stream, encryptionRunner);
+        encryptionRunner.setIsReconnect(false);
+        mStorage = storage;
+    }
+
+    @Override
+    void processHandshake(@NonNull byte[] message) throws HandshakeException {
+        switch (mState) {
+            case HandshakeState.UNKNOWN:
+                processHandshakeUnknown(message);
+                break;
+            case HandshakeState.IN_PROGRESS:
+                processHandshakeInProgress(message);
+                break;
+            case HandshakeState.FINISHED:
+                processHandshakeDeviceIdAndSecret(message);
+                break;
+            default:
+                loge(TAG, "Encountered unexpected handshake state: " + mState + ".");
+                notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+        }
+    }
+
+    private void processHandshakeUnknown(@NonNull byte[] message) throws HandshakeException {
+        logd(TAG, "Responding to handshake init request.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().respondToInitRequest(message);
+        mState = handshakeMessage.getHandshakeState();
+        sendHandshakeMessage(handshakeMessage.getNextMessage(), /* isEncrypted= */ false);
+    }
+
+    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
+        logd(TAG, "Continuing handshake.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().continueHandshake(message);
+        mState = handshakeMessage.getHandshakeState();
+        if (mState != HandshakeState.VERIFICATION_NEEDED) {
+            loge(TAG, "processHandshakeInProgress: Encountered unexpected handshake state: "
+                    + mState + ".");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        String code = handshakeMessage.getVerificationCode();
+        if (code == null) {
+            loge(TAG, "Unable to get verification code.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
+            return;
+        }
+        processVerificationCode(code);
+    }
+
+    private void processVerificationCode(@NonNull String code) {
+        if (mShowVerificationCodeListener == null) {
+            loge(TAG,
+                    "No verification code listener has been set. Unable to display "
+                            + "verification "
+                            + "code to user.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        logd(TAG, "Showing pairing code: " + code);
+        mShowVerificationCodeListener.showVerificationCode(code);
+    }
+
+    private void processHandshakeDeviceIdAndSecret(@NonNull byte[] message) {
+        UUID deviceId = ByteUtils.bytesToUUID(Arrays.copyOf(message, DEVICE_ID_BYTES));
+        if (deviceId == null) {
+            loge(TAG, "Received invalid device id. Aborting.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_DEVICE_ID);
+            return;
+        }
+        mDeviceId = deviceId.toString();
+        notifyCallback(callback -> callback.onDeviceIdReceived(mDeviceId));
+
+        mStorage.saveEncryptionKey(mDeviceId, mPendingKey.asBytes());
+        mPendingKey = null;
+        try {
+            mStorage.saveChallengeSecret(mDeviceId,
+                    Arrays.copyOfRange(message, DEVICE_ID_BYTES, message.length));
+        } catch (InvalidParameterException e) {
+            loge(TAG, "Error saving challenge secret.", e);
+            notifySecureChannelFailure(CHANNEL_ERROR_STORAGE_ERROR);
+            return;
+        }
+
+        notifyCallback(Callback::onSecureChannelEstablished);
+    }
+
+    /** Set the listener that notifies to show verification code. {@code null} to clear. */
+    public void setShowVerificationCodeListener(@Nullable ShowVerificationCodeListener listener) {
+        mShowVerificationCodeListener = listener;
+    }
+
+    @VisibleForTesting
+    @Nullable
+    public ShowVerificationCodeListener getShowVerificationCodeListener() {
+        return mShowVerificationCodeListener;
+    }
+
+    /**
+     * Called by the client to notify that the user has accepted a pairing code or any out-of-band
+     * confirmation, and send confirmation signals to remote bluetooth device.
+     */
+    public void notifyOutOfBandAccepted() {
+        HandshakeMessage message;
+        try {
+            message = getEncryptionRunner().verifyPin();
+        } catch (HandshakeException e) {
+            loge(TAG, "Error during PIN verification", e);
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
+            return;
+        }
+        if (message.getHandshakeState() != HandshakeState.FINISHED) {
+            loge(TAG, "Handshake not finished after calling verify PIN. Instead got "
+                    + "state: " + message.getHandshakeState() + ".");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        Key localKey = message.getKey();
+        if (localKey == null) {
+            loge(TAG, "Unable to finish association, generated key is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+        mState = message.getHandshakeState();
+        setEncryptionKey(localKey);
+        mPendingKey = localKey;
+        logd(TAG, "Pairing code successfully verified.");
+        sendUniqueIdToClient();
+    }
+
+    private void sendUniqueIdToClient() {
+        UUID uniqueId = mStorage.getUniqueId();
+        DeviceMessage deviceMessage = new DeviceMessage(/* recipient= */ null,
+                /* isMessageEncrypted= */ true, ByteUtils.uuidToBytes(uniqueId));
+        logd(TAG, "Sending car's device id of " + uniqueId + " to device.");
+        sendHandshakeMessage(ByteUtils.uuidToBytes(uniqueId), /* isEncrypted= */ true);
+    }
+
+    @HandshakeState
+    int getState() {
+        return mState;
+    }
+
+    void setState(@HandshakeState int state) {
+        mState = state;
+    }
+
+    /** Listener that will be invoked to display verification code. */
+    public interface ShowVerificationCodeListener {
+        /**
+         * Invoke when a verification need to be displayed during device association.
+         *
+         * @param code The verification code to show.
+         */
+        void showVerificationCode(@NonNull String code);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/CarBluetoothManager.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/CarBluetoothManager.java
new file mode 100644
index 0000000..9ca699b
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/CarBluetoothManager.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.ConnectedDeviceManager.DEVICE_ERROR_INVALID_HANDSHAKE;
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.connecteddevice.AssociationCallback;
+import com.android.car.connecteddevice.model.AssociatedDevice;
+import com.android.car.connecteddevice.oob.OobChannel;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ThreadSafeCallbacks;
+
+import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.Executor;
+
+/**
+ * Generic BLE manager for a car that keeps track of connected devices and their associated
+ * callbacks.
+ */
+public abstract class CarBluetoothManager {
+
+    private static final String TAG = "CarBluetoothManager";
+
+    protected final ConnectedDeviceStorage mStorage;
+
+    protected final CopyOnWriteArraySet<ConnectedRemoteDevice> mConnectedDevices =
+            new CopyOnWriteArraySet<>();
+
+    protected final ThreadSafeCallbacks<Callback> mCallbacks = new ThreadSafeCallbacks<>();
+
+    private String mClientDeviceName;
+
+    private String mClientDeviceAddress;
+
+    protected CarBluetoothManager(@NonNull ConnectedDeviceStorage connectedDeviceStorage) {
+        mStorage = connectedDeviceStorage;
+    }
+
+    /** Attempt to connect to device with provided id. */
+    public void connectToDevice(@NonNull UUID deviceId) {
+        for (ConnectedRemoteDevice device : mConnectedDevices) {
+            if (UUID.fromString(device.mDeviceId).equals(deviceId)) {
+                logd(TAG, "Already connected to device " + deviceId + ".");
+                // Already connected to this device. Ignore requests to connect again.
+                return;
+            }
+        }
+        // Clear any previous session before starting a new one.
+        reset();
+        initiateConnectionToDevice(deviceId);
+    }
+
+    /** Start to connect to associated devices */
+    public abstract void initiateConnectionToDevice(@NonNull UUID deviceId);
+
+    /** Start the association with a new device */
+    public abstract void startAssociation(@NonNull String nameForAssociation,
+            @NonNull AssociationCallback callback);
+
+    /** Start the association with a new device using out of band verification code exchange */
+    public abstract void startOutOfBandAssociation(
+            @NonNull String nameForAssociation,
+            @NonNull OobChannel oobChannel,
+            @NonNull AssociationCallback callback);
+
+    /** Disconnect the provided device from this manager. */
+    public abstract void disconnectDevice(@NonNull String deviceId);
+
+    /** Get current {@link AssociationCallback}. */
+    @Nullable
+    public abstract AssociationCallback getAssociationCallback();
+
+    /** Set current {@link AssociationCallback}. */
+    public abstract void setAssociationCallback(@Nullable AssociationCallback callback);
+
+    /** Set the value of the client device name */
+    public void setClientDeviceName(String deviceName) {
+        mClientDeviceName = deviceName;
+    }
+
+    /** Set the value of client device's mac address */
+    public void setClientDeviceAddress(String macAddress) {
+        mClientDeviceAddress = macAddress;
+    }
+
+    /**
+     * Initialize and start the manager.
+     */
+    @CallSuper
+    public void start() {}
+
+    /**
+     * Stop the manager and clean up.
+     */
+    public void stop() {
+        for (ConnectedRemoteDevice device : mConnectedDevices) {
+            if (device.mGatt != null) {
+                device.mGatt.close();
+            }
+        }
+        mConnectedDevices.clear();
+    }
+
+    /**
+     * Stop the association process with any device.
+     */
+    public void stopAssociation() {
+        if (!isAssociating()) {
+            return;
+        }
+        reset();
+    }
+
+    /**
+     * Register a {@link Callback} to be notified on the {@link Executor}.
+     */
+    public void registerCallback(@NonNull Callback callback, @NonNull Executor executor) {
+        mCallbacks.add(callback, executor);
+    }
+
+    /**
+     * Unregister a callback.
+     *
+     * @param callback The {@link Callback} to unregister.
+     */
+    public void unregisterCallback(@NonNull Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    /**
+     * Send a message to a connected device.
+     *
+     * @param deviceId Id of connected device.
+     * @param message  {@link DeviceMessage} to send.
+     */
+    public void sendMessage(@NonNull String deviceId, @NonNull DeviceMessage message) {
+        ConnectedRemoteDevice device = getConnectedDevice(deviceId);
+        if (device == null) {
+            logw(TAG, "Attempted to send message to unknown device $deviceId. Ignored.");
+            return;
+        }
+
+        sendMessage(device, message);
+    }
+
+    /**
+     * Send a message to a connected device.
+     *
+     * @param device  The connected {@link ConnectedRemoteDevice}.
+     * @param message {@link DeviceMessage} to send.
+     */
+    public void sendMessage(@NonNull ConnectedRemoteDevice device, @NonNull DeviceMessage message) {
+        String deviceId = device.mDeviceId;
+        if (deviceId == null) {
+            deviceId = "Unidentified device";
+        }
+
+        logd(TAG, "Writing " + message.getMessage().length + " bytes to " + deviceId + ".");
+        device.mSecureChannel.sendClientMessage(message);
+    }
+
+    /** Clean manager status and callbacks. */
+    @CallSuper
+    public void reset() {
+        mClientDeviceAddress = null;
+        mClientDeviceName = null;
+        mConnectedDevices.clear();
+    }
+
+    /** Notify that the user has accepted a pairing code or other out-of-band confirmation. */
+    public void notifyOutOfBandAccepted() {
+        if (getConnectedDevice() == null) {
+            disconnectWithError("Null connected device found when out-of-band confirmation "
+                    + "received.");
+            return;
+        }
+
+        AssociationSecureChannel secureChannel =
+                (AssociationSecureChannel) getConnectedDevice().mSecureChannel;
+        if (secureChannel == null) {
+            disconnectWithError("Null SecureBleChannel found for the current connected device "
+                    + "when out-of-band confirmation received.");
+            return;
+        }
+
+        secureChannel.notifyOutOfBandAccepted();
+    }
+
+    /** Returns the secure channel of current connected device. */
+    @Nullable
+    public SecureChannel getConnectedDeviceChannel() {
+        ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+        if (connectedDevice == null) {
+            return null;
+        }
+
+        return connectedDevice.mSecureChannel;
+    }
+
+    /**
+     * Get the {@link ConnectedRemoteDevice} with matching {@link BluetoothGatt} if available.
+     * Returns
+     * {@code null} if no matches are found.
+     */
+    @Nullable
+    protected final ConnectedRemoteDevice getConnectedDevice(@NonNull BluetoothGatt gatt) {
+        for (ConnectedRemoteDevice device : mConnectedDevices) {
+            if (device.mGatt == gatt) {
+                return device;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the {@link ConnectedRemoteDevice} with matching {@link BluetoothDevice} if available.
+     * Returns
+     * {@code null} if no matches are found.
+     */
+    @Nullable
+    protected final ConnectedRemoteDevice getConnectedDevice(@NonNull BluetoothDevice device) {
+        for (ConnectedRemoteDevice connectedDevice : mConnectedDevices) {
+            if (device.equals(connectedDevice.mDevice)) {
+                return connectedDevice;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the {@link ConnectedRemoteDevice} with matching device id if available. Returns {@code
+     * null} if no matches are found.
+     */
+    @Nullable
+    protected final ConnectedRemoteDevice getConnectedDevice(@NonNull String deviceId) {
+        for (ConnectedRemoteDevice device : mConnectedDevices) {
+            if (deviceId.equals(device.mDeviceId)) {
+                return device;
+            }
+        }
+
+        return null;
+    }
+
+    /** Add the {@link ConnectedRemoteDevice} that has connected. */
+    protected final void addConnectedDevice(@NonNull ConnectedRemoteDevice device) {
+        mConnectedDevices.add(device);
+    }
+
+    /** Return the number of devices currently connected. */
+    protected final int getConnectedDevicesCount() {
+        return mConnectedDevices.size();
+    }
+
+    /** Remove [@link BleDevice} that has been disconnected. */
+    protected final void removeConnectedDevice(@NonNull ConnectedRemoteDevice device) {
+        mConnectedDevices.remove(device);
+    }
+
+    /** Return [@code true} if the manager is currently in an association process. */
+    protected final boolean isAssociating() {
+        return getAssociationCallback() != null;
+    }
+
+    /**
+     * Set the device id of {@link ConnectedRemoteDevice} and then notify device connected callback.
+     *
+     * @param deviceId The device id received from remote device.
+     */
+    protected final void setDeviceIdAndNotifyCallbacks(@NonNull String deviceId) {
+        logd(TAG, "Setting device id: " + deviceId);
+        ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+        if (connectedDevice == null) {
+            disconnectWithError("Null connected device found when device id received.");
+            return;
+        }
+
+        connectedDevice.mDeviceId = deviceId;
+        mCallbacks.invoke(callback -> callback.onDeviceConnected(deviceId));
+    }
+
+    /** Log error which causes the disconnect with {@link Exception} and notify callbacks. */
+    protected final void disconnectWithError(@NonNull String errorMessage, @Nullable Exception e) {
+        loge(TAG, errorMessage, e);
+        if (isAssociating()) {
+            getAssociationCallback().onAssociationError(DEVICE_ERROR_INVALID_HANDSHAKE);
+        }
+        reset();
+    }
+
+    /** Log error which cause the disconnection and notify callbacks. */
+    protected final void disconnectWithError(@NonNull String errorMessage) {
+        disconnectWithError(errorMessage, null);
+    }
+
+    /** Return the current connected device. */
+    @Nullable
+    protected final ConnectedRemoteDevice getConnectedDevice() {
+        if (mConnectedDevices.isEmpty()) {
+            return null;
+        }
+        // Directly return the next because there will only be one device connected at one time.
+        return mConnectedDevices.iterator().next();
+    }
+
+    protected final SecureChannel.Callback mSecureChannelCallback =
+            new SecureChannel.Callback() {
+                @Override
+                public void onSecureChannelEstablished() {
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
+                        disconnectWithError("Null device id found when secure channel "
+                                + "established.");
+                        return;
+                    }
+                    String deviceId = connectedDevice.mDeviceId;
+                    if (mClientDeviceAddress == null) {
+                        disconnectWithError("Null device address found when secure channel "
+                                + "established.");
+                        return;
+                    }
+
+                    if (isAssociating()) {
+                        logd(TAG, "Secure channel established for un-associated device. Saving "
+                                + "association of that device for current user.");
+                        mStorage.addAssociatedDeviceForActiveUser(
+                                new AssociatedDevice(deviceId, mClientDeviceAddress,
+                                        mClientDeviceName, /* isConnectionEnabled= */ true));
+                        AssociationCallback callback = getAssociationCallback();
+                        if (callback != null) {
+                            callback.onAssociationCompleted(deviceId);
+                            setAssociationCallback(null);
+                        }
+                    }
+                    mCallbacks.invoke(callback -> callback.onSecureChannelEstablished(deviceId));
+                }
+
+                @Override
+                public void onEstablishSecureChannelFailure(int error) {
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
+                        disconnectWithError("Null device id found when secure channel "
+                                + "failed to establish.");
+                        return;
+                    }
+                    String deviceId = connectedDevice.mDeviceId;
+                    mCallbacks.invoke(callback -> callback.onSecureChannelError(deviceId));
+
+                    if (isAssociating()) {
+                        getAssociationCallback().onAssociationError(error);
+                    }
+
+                    disconnectWithError("Error while establishing secure connection.");
+                }
+
+                @Override
+                public void onMessageReceived(DeviceMessage deviceMessage) {
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
+                        disconnectWithError("Null device id found when message received.");
+                        return;
+                    }
+
+                    logd(TAG, "Received new message from " + connectedDevice.mDeviceId
+                            + " with " + deviceMessage.getMessage().length + " bytes in its "
+                            + "payload. Notifying " + mCallbacks.size() + " callbacks.");
+                    mCallbacks.invoke(
+                            callback -> callback.onMessageReceived(connectedDevice.mDeviceId,
+                                    deviceMessage));
+                }
+
+                @Override
+                public void onMessageReceivedError(Exception exception) {
+                    // TODO(b/143879960) Extend the message error from here to continue up the
+                    // chain.
+                    disconnectWithError("Error while receiving message.");
+                }
+
+                @Override
+                public void onDeviceIdReceived(String deviceId) {
+                    setDeviceIdAndNotifyCallbacks(deviceId);
+                }
+            };
+
+
+    /** State for a connected device. */
+    public enum ConnectedDeviceState {
+        CONNECTING,
+        PENDING_VERIFICATION,
+        CONNECTED,
+        UNKNOWN
+    }
+
+    /**
+     * Container class to hold information about a connected device.
+     */
+    public static class ConnectedRemoteDevice {
+        @NonNull
+        public BluetoothDevice mDevice;
+        @Nullable
+        public BluetoothGatt mGatt;
+        @NonNull
+        public ConnectedDeviceState mState;
+        @Nullable
+        public String mDeviceId;
+        @Nullable
+        public SecureChannel mSecureChannel;
+
+        public ConnectedRemoteDevice(@NonNull BluetoothDevice device,
+                @Nullable BluetoothGatt gatt) {
+            mDevice = device;
+            mGatt = gatt;
+            mState = ConnectedDeviceState.UNKNOWN;
+        }
+    }
+
+    /**
+     * Callback for triggered events from {@link CarBluetoothManager}.
+     */
+    public interface Callback {
+        /**
+         * Triggered when device is connected and device id retrieved. Device is now ready to
+         * receive messages.
+         *
+         * @param deviceId Id of device that has connected.
+         */
+        void onDeviceConnected(@NonNull String deviceId);
+
+        /**
+         * Triggered when device is disconnected.
+         *
+         * @param deviceId Id of device that has disconnected.
+         */
+        void onDeviceDisconnected(@NonNull String deviceId);
+
+        /**
+         * Triggered when device has established encryption for secure communication.
+         *
+         * @param deviceId Id of device that has established encryption.
+         */
+        void onSecureChannelEstablished(@NonNull String deviceId);
+
+        /**
+         * Triggered when a new message is received.
+         *
+         * @param deviceId Id of the device that sent the message.
+         * @param message  {@link DeviceMessage} received.
+         */
+        void onMessageReceived(@NonNull String deviceId, @NonNull DeviceMessage message);
+
+        /**
+         * Triggered when an error when establishing the secure channel.
+         *
+         * @param deviceId Id of the device that experienced the error.
+         */
+        void onSecureChannelError(@NonNull String deviceId);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/DeviceMessage.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/DeviceMessage.java
new file mode 100644
index 0000000..128decb
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/DeviceMessage.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.StreamProtos.DeviceMessageProto.Message;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.UUID;
+
+/** Holds the needed data from a {@link Message}. */
+public class DeviceMessage {
+
+    private static final String TAG = "DeviceMessage";
+
+    private final UUID mRecipient;
+
+    private final boolean mIsMessageEncrypted;
+
+    private byte[] mMessage;
+
+    public DeviceMessage(@Nullable UUID recipient, boolean isMessageEncrypted,
+            @NonNull byte[] message) {
+        mRecipient = recipient;
+        mIsMessageEncrypted = isMessageEncrypted;
+        mMessage = message;
+    }
+
+    /** Returns the recipient for this message. {@code null} if no recipient set. */
+    @Nullable
+    public UUID getRecipient() {
+        return mRecipient;
+    }
+
+    /** Returns whether this message is encrypted. */
+    public boolean isMessageEncrypted() {
+        return mIsMessageEncrypted;
+    }
+
+    /** Returns the message payload. */
+    @Nullable
+    public byte[] getMessage() {
+        return mMessage;
+    }
+
+    /** Set the message payload. */
+    public void setMessage(@NonNull byte[] message) {
+        mMessage = message;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof DeviceMessage)) {
+            return false;
+        }
+        DeviceMessage deviceMessage = (DeviceMessage) obj;
+        return Objects.equals(mRecipient, deviceMessage.mRecipient)
+                && mIsMessageEncrypted == deviceMessage.mIsMessageEncrypted
+                && Arrays.equals(mMessage, deviceMessage.mMessage);
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 * Objects.hash(mRecipient, mIsMessageEncrypted)
+                + Arrays.hashCode(mMessage);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/DeviceMessageStream.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/DeviceMessageStream.java
new file mode 100644
index 0000000..c23618a
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/DeviceMessageStream.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.connecteddevice.StreamProtos.DeviceMessageProto.Message;
+import com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType;
+import com.android.car.connecteddevice.StreamProtos.PacketProto.Packet;
+import com.android.car.connecteddevice.StreamProtos.VersionExchangeProto.VersionExchange;
+import com.android.car.connecteddevice.util.ByteUtils;
+import com.android.car.protobuf.ByteString;
+import com.android.car.protobuf.InvalidProtocolBufferException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Abstract class which includes common logic of different types of {@link DeviceMessageStream}.
+ */
+public abstract class DeviceMessageStream {
+
+    private static final String TAG = "DeviceMessageStream";
+
+    // Only version 2 of the messaging and version 2 of the security supported.
+    @VisibleForTesting
+    public static final int MESSAGING_VERSION = 2;
+    @VisibleForTesting
+    public static final int SECURITY_VERSION = 2;
+
+    private final ArrayDeque<Packet> mPacketQueue = new ArrayDeque<>();
+
+    private final Map<Integer, ByteArrayOutputStream> mPendingData = new HashMap<>();
+
+    // messageId -> nextExpectedPacketNumber
+    private final Map<Integer, Integer> mPendingPacketNumber = new HashMap<>();
+
+    private final MessageIdGenerator mMessageIdGenerator = new MessageIdGenerator();
+
+    private final AtomicBoolean mIsVersionExchanged = new AtomicBoolean(false);
+
+    private final AtomicBoolean mIsSendingInProgress = new AtomicBoolean(false);
+
+    private int mMaxWriteSize;
+
+    /** Listener which will be notified when there is new {@link DeviceMessage} received. */
+    private MessageReceivedListener mMessageReceivedListener;
+
+    /** Listener which will be notified when there is error parsing the received message. */
+    private MessageReceivedErrorListener mMessageReceivedErrorListener;
+
+    public DeviceMessageStream(int defaultMaxWriteSize) {
+        mMaxWriteSize = defaultMaxWriteSize;
+    }
+
+    /**
+     * Send data to the connected device. Note: {@link #sendCompleted()} must be called when the
+     * bytes have successfully been sent to indicate the stream is ready to send more data.
+     */
+    protected abstract void send(byte[] data);
+
+    /**
+     * Set the given listener to be notified when a new message was received from the client. If
+     * listener is {@code null}, clear.
+     */
+    public final void setMessageReceivedListener(@Nullable MessageReceivedListener listener) {
+        mMessageReceivedListener = listener;
+    }
+
+    /**
+     * Set the given listener to be notified when there was an error during receiving message from
+     * the client. If listener is {@code null}, clear.
+     */
+    public final void setMessageReceivedErrorListener(
+            @Nullable MessageReceivedErrorListener listener) {
+        mMessageReceivedErrorListener = listener;
+    }
+
+    /**
+     * Notify the {@code mMessageReceivedListener} about the message received if it is  not {@code
+     * null}.
+     *
+     * @param deviceMessage The message received.
+     * @param operationType The operation type of the message.
+     */
+    protected final void notifyMessageReceivedListener(@NonNull DeviceMessage deviceMessage,
+            OperationType operationType) {
+        if (mMessageReceivedListener != null) {
+            mMessageReceivedListener.onMessageReceived(deviceMessage, operationType);
+        }
+    }
+
+    /**
+     * Notify the {@code mMessageReceivedErrorListener} about the message received if it is  not
+     * {@code null}.
+     *
+     * @param e The exception happened when parsing the received message.
+     */
+    protected final void notifyMessageReceivedErrorListener(Exception e) {
+        if (mMessageReceivedErrorListener != null) {
+            mMessageReceivedErrorListener.onMessageReceivedError(e);
+        }
+    }
+
+    /**
+     * Writes the given message to the write characteristic of this stream with operation type
+     * {@code CLIENT_MESSAGE}.
+     *
+     * This method will handle the chunking of messages based on the max write size.
+     *
+     * @param deviceMessage The data object contains recipient, isPayloadEncrypted and message.
+     */
+    public final void writeMessage(@NonNull DeviceMessage deviceMessage) {
+        writeMessage(deviceMessage, OperationType.CLIENT_MESSAGE);
+    }
+
+    /**
+     * Send {@link DeviceMessage} to remote connected devices.
+     *
+     * @param deviceMessage The message which need to be sent
+     * @param operationType The operation type of current message
+     */
+    public final void writeMessage(@NonNull DeviceMessage deviceMessage,
+            OperationType operationType) {
+        Message.Builder builder = Message.newBuilder()
+                .setOperation(operationType)
+                .setIsPayloadEncrypted(deviceMessage.isMessageEncrypted())
+                .setPayload(ByteString.copyFrom(deviceMessage.getMessage()));
+
+        UUID recipient = deviceMessage.getRecipient();
+        if (recipient != null) {
+            builder.setRecipient(ByteString.copyFrom(ByteUtils.uuidToBytes(recipient)));
+        }
+
+        Message message = builder.build();
+        byte[] rawBytes = message.toByteArray();
+        List<Packet> packets;
+        try {
+            packets = PacketFactory.makePackets(rawBytes, mMessageIdGenerator.next(),
+                    mMaxWriteSize);
+        } catch (PacketFactoryException e) {
+            loge(TAG, "Error while creating message packets.", e);
+            return;
+        }
+        mPacketQueue.addAll(packets);
+        writeNextMessageInQueue();
+    }
+
+    private void writeNextMessageInQueue() {
+        if (mPacketQueue.isEmpty()) {
+            logd(TAG, "No more packets to send.");
+            return;
+        }
+        boolean isLockAcquired = mIsSendingInProgress.compareAndSet(false, true);
+        if (!isLockAcquired) {
+            logd(TAG, "Unable to send packet at this time.");
+            return;
+        }
+
+        Packet packet = mPacketQueue.remove();
+        logd(TAG, "Writing packet " + packet.getPacketNumber() + " of "
+                + packet.getTotalPackets() + " for " + packet.getMessageId() + ".");
+        send(packet.toByteArray());
+    }
+
+    /** Process incoming data from stream. */
+    protected final void onDataReceived(byte[] data) {
+        if (!hasVersionBeenExchanged()) {
+            processVersionExchange(data);
+            return;
+        }
+
+        Packet packet;
+        try {
+            packet = Packet.parseFrom(data);
+        } catch (InvalidProtocolBufferException e) {
+            loge(TAG, "Can not parse packet from client.", e);
+            notifyMessageReceivedErrorListener(e);
+            return;
+        }
+        processPacket(packet);
+    }
+
+    protected final void processPacket(@NonNull Packet packet) {
+        int messageId = packet.getMessageId();
+        int packetNumber = packet.getPacketNumber();
+        int expectedPacket = mPendingPacketNumber.getOrDefault(messageId, 1);
+        if (packetNumber == expectedPacket - 1) {
+            logw(TAG, "Received duplicate packet " + packet.getPacketNumber() + " for message "
+                    + messageId + ". Ignoring.");
+            return;
+        }
+        if (packetNumber != expectedPacket) {
+            loge(TAG, "Received unexpected packet " + packetNumber + " for message "
+                    + messageId + ".");
+            notifyMessageReceivedErrorListener(
+                    new IllegalStateException("Packet received out of order."));
+            return;
+        }
+        mPendingPacketNumber.put(messageId, packetNumber + 1);
+
+        ByteArrayOutputStream currentPayloadStream =
+                mPendingData.getOrDefault(messageId, new ByteArrayOutputStream());
+        mPendingData.putIfAbsent(messageId, currentPayloadStream);
+
+        byte[] payload = packet.getPayload().toByteArray();
+        try {
+            currentPayloadStream.write(payload);
+        } catch (IOException e) {
+            loge(TAG, "Error writing packet to stream.", e);
+            notifyMessageReceivedErrorListener(e);
+            return;
+        }
+        logd(TAG, "Parsed packet " + packet.getPacketNumber() + " of "
+                + packet.getTotalPackets() + " for message " + messageId + ". Writing "
+                + payload.length + ".");
+
+        if (packet.getPacketNumber() != packet.getTotalPackets()) {
+            return;
+        }
+
+        byte[] messageBytes = currentPayloadStream.toByteArray();
+        mPendingData.remove(messageId);
+
+        logd(TAG, "Received complete device message " + messageId + " of " + messageBytes.length
+                + " bytes.");
+        Message message;
+        try {
+            message = Message.parseFrom(messageBytes);
+        } catch (InvalidProtocolBufferException e) {
+            loge(TAG, "Cannot parse device message from client.", e);
+            notifyMessageReceivedErrorListener(e);
+            return;
+        }
+
+        DeviceMessage deviceMessage = new DeviceMessage(
+                ByteUtils.bytesToUUID(message.getRecipient().toByteArray()),
+                message.getIsPayloadEncrypted(), message.getPayload().toByteArray());
+        notifyMessageReceivedListener(deviceMessage, message.getOperation());
+    }
+
+    /** The maximum amount of bytes that can be written in a single packet. */
+    public final void setMaxWriteSize(@IntRange(from = 1) int maxWriteSize) {
+        if (maxWriteSize <= 0) {
+            return;
+        }
+        mMaxWriteSize = maxWriteSize;
+    }
+
+    private boolean hasVersionBeenExchanged() {
+        return mIsVersionExchanged.get();
+    }
+
+    /** Indicate current send operation has completed. */
+    @VisibleForTesting
+    public final void sendCompleted() {
+        mIsSendingInProgress.set(false);
+        writeNextMessageInQueue();
+    }
+
+    private void processVersionExchange(@NonNull byte[] value) {
+        VersionExchange versionExchange;
+        try {
+            versionExchange = VersionExchange.parseFrom(value);
+        } catch (InvalidProtocolBufferException e) {
+            loge(TAG, "Could not parse version exchange message", e);
+            notifyMessageReceivedErrorListener(e);
+
+            return;
+        }
+        int minMessagingVersion = versionExchange.getMinSupportedMessagingVersion();
+        int maxMessagingVersion = versionExchange.getMaxSupportedMessagingVersion();
+        int minSecurityVersion = versionExchange.getMinSupportedSecurityVersion();
+        int maxSecurityVersion = versionExchange.getMaxSupportedSecurityVersion();
+        if (minMessagingVersion > MESSAGING_VERSION || maxMessagingVersion < MESSAGING_VERSION
+                || minSecurityVersion > SECURITY_VERSION || maxSecurityVersion < SECURITY_VERSION) {
+            loge(TAG, "Unsupported message version for min " + minMessagingVersion + " and max "
+                    + maxMessagingVersion + " or security version for " + minSecurityVersion
+                    + " and max " + maxSecurityVersion + ".");
+            notifyMessageReceivedErrorListener(new IllegalStateException("Unsupported version."));
+            return;
+        }
+
+        VersionExchange headunitVersion = VersionExchange.newBuilder()
+                .setMinSupportedMessagingVersion(MESSAGING_VERSION)
+                .setMaxSupportedMessagingVersion(MESSAGING_VERSION)
+                .setMinSupportedSecurityVersion(SECURITY_VERSION)
+                .setMaxSupportedSecurityVersion(SECURITY_VERSION)
+                .build();
+
+        send(headunitVersion.toByteArray());
+        mIsVersionExchanged.set(true);
+        logd(TAG, "Sent supported version to the phone.");
+    }
+
+
+    /** A generator of unique IDs for messages. */
+    private static class MessageIdGenerator {
+        private final AtomicInteger mMessageId = new AtomicInteger(0);
+
+        int next() {
+            int current = mMessageId.getAndIncrement();
+            mMessageId.compareAndSet(Integer.MAX_VALUE, 0);
+            return current;
+        }
+    }
+
+    /**
+     * Listener to be invoked when a complete message is received from the client.
+     */
+    public interface MessageReceivedListener {
+
+        /**
+         * Called when a complete message is received from the client.
+         *
+         * @param deviceMessage The message received from the client.
+         * @param operationType The {@link OperationType} of the received message.
+         */
+        void onMessageReceived(@NonNull DeviceMessage deviceMessage,
+                OperationType operationType);
+    }
+
+    /**
+     * Listener to be invoked when there was an error during receiving message from the client.
+     */
+    public interface MessageReceivedErrorListener {
+        /**
+         * Called when there was an error during receiving message from the client.
+         *
+         * @param exception The error.
+         */
+        void onMessageReceivedError(@NonNull Exception exception);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/OobAssociationSecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/OobAssociationSecureChannel.java
new file mode 100644
index 0000000..c6b0a7d
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/OobAssociationSecureChannel.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static android.car.encryptionrunner.HandshakeMessage.HandshakeState;
+
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.EncryptionRunnerFactory;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.HandshakeMessage;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.connecteddevice.oob.OobConnectionManager;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.util.Arrays;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+/**
+ * A secure channel established with the association flow with an out-of-band verification.
+ */
+public class OobAssociationSecureChannel extends AssociationSecureChannel {
+
+    private static final String TAG = "OobAssociationSecureChannel";
+
+    private final OobConnectionManager mOobConnectionManager;
+
+    private byte[] mOobCode;
+
+    public OobAssociationSecureChannel(
+            DeviceMessageStream stream,
+            ConnectedDeviceStorage storage,
+            OobConnectionManager oobConnectionManager) {
+        this(stream, storage, oobConnectionManager, EncryptionRunnerFactory.newRunner(
+                EncryptionRunnerFactory.EncryptionRunnerType.OOB_UKEY2));
+    }
+
+    OobAssociationSecureChannel(
+            DeviceMessageStream stream,
+            ConnectedDeviceStorage storage,
+            OobConnectionManager oobConnectionManager,
+            EncryptionRunner encryptionRunner) {
+        super(stream, storage, encryptionRunner);
+        mOobConnectionManager = oobConnectionManager;
+    }
+
+    @Override
+    void processHandshake(@NonNull byte[] message) throws HandshakeException {
+        switch (getState()) {
+            case HandshakeState.IN_PROGRESS:
+                processHandshakeInProgress(message);
+                break;
+            case HandshakeState.OOB_VERIFICATION_NEEDED:
+                processHandshakeOobVerificationNeeded(message);
+                break;
+            default:
+                super.processHandshake(message);
+        }
+    }
+
+    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
+        HandshakeMessage handshakeMessage = getEncryptionRunner().continueHandshake(message);
+        setState(handshakeMessage.getHandshakeState());
+        int state = getState();
+        if (state != HandshakeState.OOB_VERIFICATION_NEEDED) {
+            loge(TAG, "processHandshakeInProgress: Encountered unexpected handshake state: "
+                    + state + ".");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        mOobCode = handshakeMessage.getOobVerificationCode();
+        if (mOobCode == null) {
+            loge(TAG, "Unable to get out of band verification code.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
+            return;
+        }
+
+        byte[] encryptedCode;
+        try {
+            encryptedCode = mOobConnectionManager.encryptVerificationCode(mOobCode);
+        } catch (InvalidKeyException | InvalidAlgorithmParameterException
+                | IllegalBlockSizeException | BadPaddingException e) {
+            loge(TAG, "Encryption failed for verification code exchange.", e);
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_HANDSHAKE);
+            return;
+        }
+
+        sendHandshakeMessage(encryptedCode, /* isEncrypted= */ false);
+    }
+
+    private void processHandshakeOobVerificationNeeded(@NonNull byte[] message) {
+        byte[] decryptedCode;
+        try {
+            decryptedCode = mOobConnectionManager.decryptVerificationCode(message);
+        } catch (InvalidKeyException | InvalidAlgorithmParameterException
+                | IllegalBlockSizeException | BadPaddingException e) {
+            loge(TAG, "Decryption failed for verification code exchange", e);
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_HANDSHAKE);
+            return;
+        }
+
+        if (!Arrays.equals(mOobCode, decryptedCode)) {
+            loge(TAG, "Exchanged verification codes do not match. Aborting secure channel.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_VERIFICATION);
+            return;
+        }
+
+        notifyOutOfBandAccepted();
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/PacketFactory.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/PacketFactory.java
new file mode 100644
index 0000000..5036a18
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/PacketFactory.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.connecteddevice.StreamProtos.PacketProto.Packet;
+import com.android.car.protobuf.ByteString;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Factory for creating {@link Packet} protos.
+ */
+class PacketFactory {
+    private static final String TAG = "PacketFactory";
+
+    /**
+     * The size in bytes of a {@code fixed32} field in the proto.
+     */
+    private static final int FIXED_32_SIZE = 4;
+
+    /**
+     * The bytes needed to encode the field number in the proto.
+     *
+     * <p>Since the {@link Packet} only has 4 fields, it will only take 1 additional byte to
+     * encode.
+     */
+    private static final int FIELD_NUMBER_ENCODING_SIZE = 1;
+
+    /**
+     * The size in bytes of field {@code packet_number}. The proto field is a {@code fixed32}.
+     */
+    private static final int PACKET_NUMBER_ENCODING_SIZE =
+            FIXED_32_SIZE + FIELD_NUMBER_ENCODING_SIZE;
+
+    /**
+     * Split given data if necessary to fit within the given {@code maxSize}.
+     *
+     * @param payload The payload to potentially split across multiple {@link Packet}s.
+     * @param messageId The unique id for identifying message.
+     * @param maxSize The maximum size of each chunk.
+     * @return A list of {@link Packet}s.
+     * @throws PacketFactoryException if an error occurred during the splitting of data.
+     */
+    static List<Packet> makePackets(byte[] payload, int messageId, int maxSize)
+            throws PacketFactoryException {
+        List<Packet> blePackets = new ArrayList<>();
+        int payloadSize = payload.length;
+        int totalPackets = getTotalPacketNumber(messageId, payloadSize, maxSize);
+        int maxPayloadSize = maxSize
+                - getPacketHeaderSize(totalPackets, messageId, Math.min(payloadSize, maxSize));
+
+        int start = 0;
+        int end = Math.min(payloadSize, maxPayloadSize);
+        for (int packetNum = 1; packetNum <= totalPackets; packetNum++) {
+            blePackets.add(Packet.newBuilder()
+                    .setPacketNumber(packetNum)
+                    .setTotalPackets(totalPackets)
+                    .setMessageId(messageId)
+                    .setPayload(ByteString.copyFrom(Arrays.copyOfRange(payload, start, end)))
+                    .build());
+            start = end;
+            end = Math.min(start + maxPayloadSize, payloadSize);
+        }
+        return blePackets;
+    }
+
+    /**
+     * Compute the header size for the {@link Packet} proto in bytes. This method assumes that
+     * the proto contains a payload.
+     */
+    @VisibleForTesting
+    static int getPacketHeaderSize(int totalPackets, int messageId, int payloadSize) {
+        return FIXED_32_SIZE + FIELD_NUMBER_ENCODING_SIZE
+                + getEncodedSize(totalPackets) + FIELD_NUMBER_ENCODING_SIZE
+                + getEncodedSize(messageId) + FIELD_NUMBER_ENCODING_SIZE
+                + getEncodedSize(payloadSize) + FIELD_NUMBER_ENCODING_SIZE;
+    }
+
+    /**
+     * Compute the total packets required to encode a payload of the given size.
+     */
+    @VisibleForTesting
+    static int getTotalPacketNumber(int messageId, int payloadSize, int maxSize)
+            throws PacketFactoryException {
+        int headerSizeWithoutTotalPackets = FIXED_32_SIZE + FIELD_NUMBER_ENCODING_SIZE
+                + getEncodedSize(messageId) + FIELD_NUMBER_ENCODING_SIZE
+                + getEncodedSize(Math.min(payloadSize, maxSize)) + FIELD_NUMBER_ENCODING_SIZE;
+
+        for (int value = 1; value <= PACKET_NUMBER_ENCODING_SIZE; value++) {
+            int packetHeaderSize = headerSizeWithoutTotalPackets + value
+                    + FIELD_NUMBER_ENCODING_SIZE;
+            int maxPayloadSize = maxSize - packetHeaderSize;
+            if (maxPayloadSize < 0) {
+                throw new PacketFactoryException("Packet header size too large.");
+            }
+            int totalPackets = (int) Math.ceil(payloadSize / (double) maxPayloadSize);
+            if (getEncodedSize(totalPackets) == value) {
+                return totalPackets;
+            }
+        }
+
+        loge(TAG, "Cannot get valid total packet number for message: messageId: "
+                + messageId + ", payloadSize: " + payloadSize + ", maxSize: " + maxSize);
+        throw new PacketFactoryException("No valid total packet number.");
+    }
+
+    /**
+     * This method implements Protocol Buffers encoding algorithm.
+     *
+     * <p>Computes the number of bytes that would be needed to store a 32-bit variant.
+     *
+     * @param value the data that need to be encoded
+     * @return the size of the encoded data
+     * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding#varints">
+     *     Protocol Buffers Encoding</a>
+     */
+    private static int getEncodedSize(int value) {
+        if (value < 0) {
+            return 10;
+        }
+        if ((value & (~0 << 7)) == 0) {
+            return 1;
+        }
+        if ((value & (~0 << 14)) == 0) {
+            return 2;
+        }
+        if ((value & (~0 << 21)) == 0) {
+            return 3;
+        }
+        if ((value & (~0 << 28)) == 0) {
+            return 4;
+        }
+        return 5;
+    }
+
+    private PacketFactory() {}
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/PacketFactoryException.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/PacketFactoryException.java
new file mode 100644
index 0000000..41c11fc
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/PacketFactoryException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+/**
+ * Exception for signaling {@link PacketFactory} errors.
+ */
+class PacketFactoryException extends Exception {
+    PacketFactoryException(String message) {
+        super(message);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/ReconnectSecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/ReconnectSecureChannel.java
new file mode 100644
index 0000000..71c879a
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/ReconnectSecureChannel.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.EncryptionRunnerFactory;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.HandshakeMessage;
+import android.car.encryptionrunner.HandshakeMessage.HandshakeState;
+import android.car.encryptionrunner.Key;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * A secure channel established with the reconnection flow.
+ */
+public class ReconnectSecureChannel extends SecureChannel {
+
+    private static final String TAG = "ReconnectSecureChannel";
+
+    private final ConnectedDeviceStorage mStorage;
+
+    private final String mDeviceId;
+
+    private final byte[] mExpectedChallengeResponse;
+
+    @HandshakeState
+    private int mState = HandshakeState.UNKNOWN;
+
+    private AtomicBoolean mHasVerifiedDevice = new AtomicBoolean(false);
+
+    /**
+     * Create a new secure reconnection channel.
+     *
+     * @param stream The {@link DeviceMessageStream} for communication with the device.
+     * @param storage {@link ConnectedDeviceStorage} for secure storage.
+     * @param deviceId Id of the device being reconnected.
+     * @param expectedChallengeResponse Expected response to challenge issued in reconnect. Should
+     *                                  pass {@code null} when device verification is not needed
+     *                                  during the reconnection process.
+     */
+    public ReconnectSecureChannel(@NonNull DeviceMessageStream stream,
+            @NonNull ConnectedDeviceStorage storage, @NonNull String deviceId,
+            @Nullable byte[] expectedChallengeResponse) {
+        super(stream, newReconnectRunner());
+        mStorage = storage;
+        mDeviceId = deviceId;
+        if (expectedChallengeResponse == null) {
+            // Skip the device verification step for spp reconnection
+            mHasVerifiedDevice.set(true);
+        }
+        mExpectedChallengeResponse = expectedChallengeResponse;
+    }
+
+    private static EncryptionRunner newReconnectRunner() {
+        EncryptionRunner encryptionRunner = EncryptionRunnerFactory.newRunner();
+        encryptionRunner.setIsReconnect(true);
+        return encryptionRunner;
+    }
+
+    @Override
+    void processHandshake(byte[] message) throws HandshakeException {
+        switch (mState) {
+            case HandshakeState.UNKNOWN:
+                if (!mHasVerifiedDevice.get()) {
+                    processHandshakeDeviceVerification(message);
+                } else {
+                    processHandshakeInitialization(message);
+                }
+                break;
+            case HandshakeState.IN_PROGRESS:
+                processHandshakeInProgress(message);
+                break;
+            case HandshakeState.RESUMING_SESSION:
+                processHandshakeResumingSession(message);
+                break;
+            default:
+                loge(TAG, "Encountered unexpected handshake state: " + mState + ".");
+                notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+        }
+    }
+
+    private void processHandshakeDeviceVerification(byte[] message) {
+        byte[] challengeResponse = Arrays.copyOf(message,
+                mExpectedChallengeResponse.length);
+        byte[] deviceChallenge = Arrays.copyOfRange(message,
+                mExpectedChallengeResponse.length, message.length);
+        if (!Arrays.equals(mExpectedChallengeResponse, challengeResponse)) {
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+        logd(TAG, "Responding to challenge " + ByteUtils.byteArrayToHexString(deviceChallenge)
+                + ".");
+        byte[] deviceChallengeResponse = mStorage.hashWithChallengeSecret(mDeviceId,
+                deviceChallenge);
+        if (deviceChallengeResponse == null) {
+            notifySecureChannelFailure(CHANNEL_ERROR_STORAGE_ERROR);
+        }
+        sendHandshakeMessage(deviceChallengeResponse, /* isEncrypted= */ false);
+        mHasVerifiedDevice.set(true);
+    }
+
+    private void processHandshakeInitialization(byte[] message) throws HandshakeException {
+        logd(TAG, "Responding to handshake init request.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().respondToInitRequest(message);
+        mState = handshakeMessage.getHandshakeState();
+        sendHandshakeMessage(handshakeMessage.getNextMessage(), /* isEncrypted= */ false);
+    }
+
+    private void processHandshakeInProgress(@NonNull byte[] message) throws HandshakeException {
+        logd(TAG, "Continuing handshake.");
+        HandshakeMessage handshakeMessage = getEncryptionRunner().continueHandshake(message);
+        mState = handshakeMessage.getHandshakeState();
+    }
+
+    private void processHandshakeResumingSession(@NonNull byte[] message)
+            throws HandshakeException {
+        logd(TAG, "Start reconnection authentication.");
+
+        byte[] previousKey = mStorage.getEncryptionKey(mDeviceId);
+        if (previousKey == null) {
+            loge(TAG, "Unable to resume session, previous key is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+
+        HandshakeMessage handshakeMessage = getEncryptionRunner().authenticateReconnection(message,
+                previousKey);
+        mState = handshakeMessage.getHandshakeState();
+        if (mState != HandshakeState.FINISHED) {
+            loge(TAG, "Unable to resume session, unexpected next handshake state: " + mState + ".");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_STATE);
+            return;
+        }
+
+        Key newKey = handshakeMessage.getKey();
+        if (newKey == null) {
+            loge(TAG, "Unable to resume session, new key is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_ENCRYPTION_KEY);
+            return;
+        }
+
+        logd(TAG, "Saved new key for reconnection.");
+        mStorage.saveEncryptionKey(mDeviceId, newKey.asBytes());
+        setEncryptionKey(newKey);
+        sendServerAuthToClient(handshakeMessage.getNextMessage());
+        notifyCallback(Callback::onSecureChannelEstablished);
+    }
+
+    private void sendServerAuthToClient(@Nullable byte[] message) {
+        if (message == null) {
+            loge(TAG, "Unable to send server authentication message to client, message is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_MSG);
+            return;
+        }
+
+        sendHandshakeMessage(message, /* isEncrypted= */ false);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/SecureChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/SecureChannel.java
new file mode 100644
index 0000000..e6ad290
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/SecureChannel.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.Key;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.security.SignatureException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+/**
+ * Establishes a secure channel with {@link EncryptionRunner} over {@link DeviceMessageStream} as
+ * server side, sends and receives messages securely after the secure channel has been established.
+ */
+public abstract class SecureChannel {
+
+    private static final String TAG = "SecureChannel";
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            CHANNEL_ERROR_INVALID_HANDSHAKE,
+            CHANNEL_ERROR_INVALID_MSG,
+            CHANNEL_ERROR_INVALID_DEVICE_ID,
+            CHANNEL_ERROR_INVALID_VERIFICATION,
+            CHANNEL_ERROR_INVALID_STATE,
+            CHANNEL_ERROR_INVALID_ENCRYPTION_KEY,
+            CHANNEL_ERROR_STORAGE_ERROR
+    })
+    @interface ChannelError { }
+
+    /** Indicates an error during a Handshake of EncryptionRunner. */
+    static final int CHANNEL_ERROR_INVALID_HANDSHAKE = 0;
+    /** Received an invalid handshake message or has an invalid handshake message to send. */
+    static final int CHANNEL_ERROR_INVALID_MSG = 1;
+    /** Unable to retrieve a valid id. */
+    static final int CHANNEL_ERROR_INVALID_DEVICE_ID = 2;
+    /** Unable to get verification code or there's a error during pin verification. */
+    static final int CHANNEL_ERROR_INVALID_VERIFICATION = 3;
+    /** Encountered an unexpected handshake state. */
+    static final int CHANNEL_ERROR_INVALID_STATE = 4;
+    /** Failed to get a valid previous/new encryption key. */
+    static final int CHANNEL_ERROR_INVALID_ENCRYPTION_KEY = 5;
+    /** Failed to save or retrieve security keys. */
+    static final int CHANNEL_ERROR_STORAGE_ERROR = 6;
+
+
+    private final DeviceMessageStream mStream;
+
+    private final EncryptionRunner mEncryptionRunner;
+
+    private final AtomicReference<Key> mEncryptionKey = new AtomicReference<>();
+
+    private Callback mCallback;
+
+    SecureChannel(@NonNull DeviceMessageStream stream,
+            @NonNull EncryptionRunner encryptionRunner) {
+        mStream = stream;
+        mEncryptionRunner = encryptionRunner;
+        mStream.setMessageReceivedListener(this::onMessageReceived);
+    }
+
+    /** Logic for processing a handshake message from device. */
+    abstract void processHandshake(byte[] message) throws HandshakeException;
+
+    void sendHandshakeMessage(@Nullable byte[] message, boolean isEncrypted) {
+        if (message == null) {
+            loge(TAG, "Unable to send next handshake message, message is null.");
+            notifySecureChannelFailure(CHANNEL_ERROR_INVALID_MSG);
+            return;
+        }
+
+        logd(TAG, "Sending handshake message.");
+        DeviceMessage deviceMessage = new DeviceMessage(/* recipient= */ null,
+                isEncrypted, message);
+        if (deviceMessage.isMessageEncrypted()) {
+            encryptMessage(deviceMessage);
+        }
+        mStream.writeMessage(deviceMessage, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    /** Set the encryption key that secures this channel. */
+    void setEncryptionKey(@Nullable Key encryptionKey) {
+        mEncryptionKey.set(encryptionKey);
+    }
+
+    /**
+     * Send a client message.
+     * <p>Note: This should be called with an encrypted message only after the secure channel has
+     * been established.</p>
+     *
+     * @param deviceMessage The {@link DeviceMessage} to send.
+     */
+    public void sendClientMessage(@NonNull DeviceMessage deviceMessage)
+            throws IllegalStateException {
+        if (deviceMessage.isMessageEncrypted()) {
+            encryptMessage(deviceMessage);
+        }
+        mStream.writeMessage(deviceMessage, OperationType.CLIENT_MESSAGE);
+    }
+
+    private void encryptMessage(@NonNull DeviceMessage deviceMessage) {
+        Key key = mEncryptionKey.get();
+        if (key == null) {
+            throw new IllegalStateException("Secure channel has not been established.");
+        }
+
+        byte[] encryptedMessage = key.encryptData(deviceMessage.getMessage());
+        deviceMessage.setMessage(encryptedMessage);
+    }
+
+    /** Get the BLE stream backing this channel. */
+    @NonNull
+    public DeviceMessageStream getStream() {
+        return mStream;
+    }
+
+    /** Register a callback that notifies secure channel events. */
+    public void registerCallback(Callback callback) {
+        mCallback = callback;
+    }
+
+    /** Unregister a callback. */
+    void unregisterCallback(Callback callback) {
+        if (callback == mCallback) {
+            mCallback = null;
+        }
+    }
+
+    @VisibleForTesting
+    @Nullable
+    public Callback getCallback() {
+        return mCallback;
+    }
+
+    void notifyCallback(@NonNull Consumer<Callback> notification) {
+        if (mCallback != null) {
+            notification.accept(mCallback);
+        }
+    }
+
+    /** Notify callbacks that an error has occurred. */
+    void notifySecureChannelFailure(@ChannelError int error) {
+        loge(TAG, "Secure channel error: " + error);
+        notifyCallback(callback -> callback.onEstablishSecureChannelFailure(error));
+    }
+
+    /** Return the {@link EncryptionRunner} for this channel. */
+    @NonNull
+    EncryptionRunner getEncryptionRunner() {
+        return mEncryptionRunner;
+    }
+
+    /**
+     * Process the inner message and replace with decrypted value if necessary. If an error occurs
+     * the inner message will be replaced with {@code null} and call
+     * {@link Callback#onMessageReceivedError(Exception)} on the registered callback.
+     *
+     * @param deviceMessage The message to process.
+     * @return {@code true} if message was successfully processed. {@code false} if an error
+     * occurred.
+     */
+    @VisibleForTesting
+    boolean processMessage(@NonNull DeviceMessage deviceMessage) {
+        if (!deviceMessage.isMessageEncrypted()) {
+            logd(TAG, "Message was not decrypted. No further action necessary.");
+            return true;
+        }
+        Key key = mEncryptionKey.get();
+        if (key == null) {
+            loge(TAG, "Received encrypted message before secure channel has "
+                    + "been established.");
+            notifyCallback(callback -> callback.onMessageReceivedError(null));
+            deviceMessage.setMessage(null);
+            return false;
+        }
+        try {
+            byte[] decryptedMessage = key.decryptData(deviceMessage.getMessage());
+            deviceMessage.setMessage(decryptedMessage);
+            logd(TAG, "Decrypted secure message.");
+            return true;
+        } catch (SignatureException e) {
+            loge(TAG, "Could not decrypt client credentials.", e);
+            notifyCallback(callback -> callback.onMessageReceivedError(e));
+            deviceMessage.setMessage(null);
+
+            return false;
+        }
+    }
+
+    @VisibleForTesting
+    void onMessageReceived(@NonNull DeviceMessage deviceMessage, OperationType operationType) {
+        boolean success = processMessage(deviceMessage);
+        switch(operationType) {
+            case ENCRYPTION_HANDSHAKE:
+                if (!success) {
+                    notifyCallback(callback -> callback.onEstablishSecureChannelFailure(
+                            CHANNEL_ERROR_INVALID_HANDSHAKE));
+                    break;
+                }
+                logd(TAG, "Received handshake message.");
+                try {
+                    processHandshake(deviceMessage.getMessage());
+                } catch (HandshakeException e) {
+                    loge(TAG, "Handshake failed.", e);
+                    notifyCallback(callback -> callback.onEstablishSecureChannelFailure(
+                            CHANNEL_ERROR_INVALID_HANDSHAKE));
+                }
+                break;
+            case CLIENT_MESSAGE:
+                if (!success || deviceMessage.getMessage() == null) {
+                    break;
+                }
+                logd(TAG, "Received client message.");
+                notifyCallback(
+                        callback -> callback.onMessageReceived(deviceMessage));
+                break;
+            default:
+                loge(TAG, "Received unexpected operation type: " + operationType + ".");
+        }
+    }
+
+    /**
+     * Callbacks that will be invoked during establishing secure channel, sending and receiving
+     * messages securely.
+     */
+    public interface Callback {
+        /**
+         * Invoked when secure channel has been established successfully.
+         */
+        default void onSecureChannelEstablished() { }
+
+        /**
+         * Invoked when a {@link ChannelError} has been encountered in attempting to establish
+         * a secure channel.
+         *
+         * @param error The failure indication.
+         */
+        default void onEstablishSecureChannelFailure(@SecureChannel.ChannelError int error) { }
+
+        /**
+         * Invoked when a complete message is received securely from the client and decrypted.
+         *
+         * @param deviceMessage The {@link DeviceMessage} with decrypted message.
+         */
+        default void onMessageReceived(@NonNull DeviceMessage deviceMessage) { }
+
+        /**
+         * Invoked when there was an error during a processing or decrypting of a client message.
+         *
+         * @param exception The error.
+         */
+        default void onMessageReceivedError(@Nullable Exception exception) { }
+
+        /**
+         * Invoked when the device id was received from the client.
+         *
+         * @param deviceId The unique device id of client.
+         */
+        default void onDeviceIdReceived(@NonNull String deviceId) { }
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BleCentralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BleCentralManager.java
new file mode 100644
index 0000000..7a663f7
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BleCentralManager.java
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+package com.android.car.connecteddevice.connection.ble;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Class that manages BLE scanning operations.
+ */
+public class BleCentralManager {
+
+    private static final String TAG = "BleCentralManager";
+
+    private static final int RETRY_LIMIT = 5;
+
+    private static final int RETRY_INTERVAL_MS = 1000;
+
+    private final Context mContext;
+
+    private final Handler mHandler;
+
+    private List<ScanFilter> mScanFilters;
+
+    private ScanSettings mScanSettings;
+
+    private ScanCallback mScanCallback;
+
+    private BluetoothLeScanner mScanner;
+
+    private int mScannerStartCount = 0;
+
+    private AtomicInteger mScannerState = new AtomicInteger(STOPPED);
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            STOPPED,
+            STARTED,
+            SCANNING
+    })
+    private @interface ScannerState {}
+    private static final int STOPPED = 0;
+    private static final int STARTED = 1;
+    private static final int SCANNING = 2;
+
+    public BleCentralManager(@NonNull Context context) {
+        mContext = context;
+        mHandler = new Handler(context.getMainLooper());
+    }
+
+    /**
+     * Start the BLE scanning process.
+     *
+     * @param filters Optional list of {@link ScanFilter}s to apply to scan results.
+     * @param settings {@link ScanSettings} to apply to scanner.
+     * @param callback {@link ScanCallback} for scan events.
+     */
+    public void startScanning(@Nullable List<ScanFilter> filters, @NonNull ScanSettings settings,
+            @NonNull ScanCallback callback) {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+            loge(TAG, "Attempted start scanning, but system does not support BLE. Ignoring");
+            return;
+        }
+        logd(TAG, "Request received to start scanning.");
+        mScannerStartCount = 0;
+        mScanFilters = filters;
+        mScanSettings = settings;
+        mScanCallback = callback;
+        updateScannerState(STARTED);
+        startScanningInternally();
+    }
+
+    /** Stop the scanner */
+    public void stopScanning() {
+        logd(TAG, "Attempting to stop scanning");
+        if (mScanner != null) {
+            mScanner.stopScan(mInternalScanCallback);
+        }
+        mScanCallback = null;
+        updateScannerState(STOPPED);
+    }
+
+    /** Returns {@code true} if currently scanning, {@code false} otherwise. */
+    public boolean isScanning() {
+        return mScannerState.get() == SCANNING;
+    }
+
+    /** Clean up the scanning process. */
+    public void cleanup() {
+        if (isScanning()) {
+            stopScanning();
+        }
+    }
+
+    private void startScanningInternally() {
+        logd(TAG, "Attempting to start scanning");
+        if (mScanner == null && BluetoothAdapter.getDefaultAdapter() != null) {
+            mScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
+        }
+        if (mScanner != null) {
+            mScanner.startScan(mScanFilters, mScanSettings, mInternalScanCallback);
+            updateScannerState(SCANNING);
+        } else {
+            mHandler.postDelayed(() -> {
+                // Keep trying
+                logd(TAG, "Scanner unavailable. Trying again.");
+                startScanningInternally();
+            }, RETRY_INTERVAL_MS);
+        }
+    }
+
+    private void updateScannerState(@ScannerState int newState) {
+        mScannerState.set(newState);
+    }
+
+    private final ScanCallback mInternalScanCallback = new ScanCallback() {
+        @Override
+        public void onScanResult(int callbackType, ScanResult result) {
+            if (mScanCallback != null) {
+                mScanCallback.onScanResult(callbackType, result);
+            }
+        }
+
+        @Override
+        public void onBatchScanResults(List<ScanResult> results) {
+            logd(TAG, "Batch scan found " + results.size() + " results.");
+            if (mScanCallback != null) {
+                mScanCallback.onBatchScanResults(results);
+            }
+        }
+
+        @Override
+        public void onScanFailed(int errorCode) {
+            if (mScannerStartCount >= RETRY_LIMIT) {
+                loge(TAG, "Cannot start BLE Scanner. Scanning Retry count: "
+                        + mScannerStartCount);
+                if (mScanCallback != null) {
+                    mScanCallback.onScanFailed(errorCode);
+                }
+                return;
+            }
+
+            mScannerStartCount++;
+            logw(TAG, "BLE Scanner failed to start. Error: "
+                    + errorCode
+                    + " Retry: "
+                    + mScannerStartCount);
+            switch(errorCode) {
+                case SCAN_FAILED_ALREADY_STARTED:
+                    // Scanner already started. Do nothing.
+                    break;
+                case SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
+                case SCAN_FAILED_INTERNAL_ERROR:
+                    mHandler.postDelayed(BleCentralManager.this::startScanningInternally,
+                            RETRY_INTERVAL_MS);
+                    break;
+                default:
+                    // Ignore other codes.
+            }
+        }
+    };
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BleDeviceMessageStream.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BleDeviceMessageStream.java
new file mode 100644
index 0000000..864475f
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BleDeviceMessageStream.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.ble;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.os.Handler;
+import android.os.Looper;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.connecteddevice.connection.DeviceMessageStream;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/** BLE message stream to a device. */
+public class BleDeviceMessageStream extends DeviceMessageStream {
+
+    private static final String TAG = "BleDeviceMessageStream";
+
+    /*
+     * During bandwidth testing, it was discovered that allowing the stream to send as fast as it
+     * can blocked outgoing notifications from being received by the connected device. Adding a
+     * throttle to the outgoing messages alleviated this block and allowed both sides to
+     * send/receive in parallel successfully.
+     */
+    private static final long THROTTLE_DEFAULT_MS = 10L;
+    private static final long THROTTLE_WAIT_MS = 75L;
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    private final AtomicLong mThrottleDelay = new AtomicLong(THROTTLE_DEFAULT_MS);
+
+    private final BlePeripheralManager mBlePeripheralManager;
+
+    private final BluetoothDevice mDevice;
+
+    private final BluetoothGattCharacteristic mWriteCharacteristic;
+
+    private final BluetoothGattCharacteristic mReadCharacteristic;
+
+    BleDeviceMessageStream(@NonNull BlePeripheralManager blePeripheralManager,
+            @NonNull BluetoothDevice device,
+            @NonNull BluetoothGattCharacteristic writeCharacteristic,
+            @NonNull BluetoothGattCharacteristic readCharacteristic,
+            int defaultMaxWriteSize) {
+        super(defaultMaxWriteSize);
+        mBlePeripheralManager = blePeripheralManager;
+        mDevice = device;
+        mWriteCharacteristic = writeCharacteristic;
+        mReadCharacteristic = readCharacteristic;
+        mBlePeripheralManager.addOnCharacteristicWriteListener(this::onCharacteristicWrite);
+        mBlePeripheralManager.addOnCharacteristicReadListener(this::onCharacteristicRead);
+    }
+
+    @Override
+    protected void send(byte[] data) {
+        mWriteCharacteristic.setValue(data);
+        mBlePeripheralManager.notifyCharacteristicChanged(mDevice, mWriteCharacteristic,
+                /* confirm= */ false);
+    }
+
+    private void onCharacteristicRead(@NonNull BluetoothDevice device) {
+        if (!mDevice.equals(device)) {
+            logw(TAG, "Received a read notification from a device (" + device.getAddress()
+                    + ") that is not the expected device (" + mDevice.getAddress() + ") registered "
+                    + "to this stream. Ignoring.");
+            return;
+        }
+
+        logd(TAG, "Releasing lock on characteristic.");
+        sendCompleted();
+    }
+
+    private void onCharacteristicWrite(@NonNull BluetoothDevice device,
+            @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
+        logd(TAG, "Received a message from a device (" + device.getAddress() + ").");
+        if (!mDevice.equals(device)) {
+            logw(TAG, "Received a message from a device (" + device.getAddress() + ") that is not "
+                    + "the expected device (" + mDevice.getAddress() + ") registered to this "
+                    + "stream. Ignoring.");
+            return;
+        }
+
+        if (!characteristic.getUuid().equals(mReadCharacteristic.getUuid())) {
+            logw(TAG, "Received a write to a characteristic (" + characteristic.getUuid() + ") that"
+                    + " is not the expected UUID (" + mReadCharacteristic.getUuid() + "). "
+                    + "Ignoring.");
+            return;
+        }
+        onDataReceived(value);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BlePeripheralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BlePeripheralManager.java
new file mode 100644
index 0000000..645cecb
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/BlePeripheralManager.java
@@ -0,0 +1,534 @@
+/*
+ * 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.
+ */
+
+package com.android.car.connecteddevice.connection.ble;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattServer;
+import android.bluetooth.BluetoothGattServerCallback;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * A generic class that manages BLE peripheral operations like start/stop advertising, notifying
+ * connects/disconnects and reading/writing values to GATT characteristics.
+ */
+// TODO(b/123248433) This could move to a separate comms library.
+public class BlePeripheralManager {
+    private static final String TAG = "BlePeripheralManager";
+
+    private static final int BLE_RETRY_LIMIT = 5;
+    private static final int BLE_RETRY_INTERVAL_MS = 1000;
+
+    private static final int GATT_SERVER_RETRY_LIMIT = 20;
+    private static final int GATT_SERVER_RETRY_DELAY_MS = 200;
+
+    // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth
+    // .service.generic_access.xml
+    private static final UUID GENERIC_ACCESS_PROFILE_UUID =
+            UUID.fromString("00001800-0000-1000-8000-00805f9b34fb");
+    // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth
+    // .characteristic.gap.device_name.xml
+    private static final UUID DEVICE_NAME_UUID =
+            UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb");
+
+    private final Handler mHandler;
+
+    private final Context mContext;
+    private final Set<Callback> mCallbacks = new CopyOnWriteArraySet<>();
+    private final Set<OnCharacteristicWriteListener> mWriteListeners = new HashSet<>();
+    private final Set<OnCharacteristicReadListener> mReadListeners = new HashSet<>();
+    private final AtomicReference<BluetoothGattServer> mGattServer = new AtomicReference<>();
+    private final AtomicReference<BluetoothGatt> mBluetoothGatt = new AtomicReference<>();
+
+    private int mMtuSize = 20;
+
+    private BluetoothManager mBluetoothManager;
+    private AtomicReference<BluetoothLeAdvertiser> mAdvertiser = new AtomicReference<>();
+    private int mAdvertiserStartCount;
+    private int mGattServerRetryStartCount;
+    private BluetoothGattService mBluetoothGattService;
+    private AdvertiseCallback mAdvertiseCallback;
+    private AdvertiseData mAdvertiseData;
+    private AdvertiseData mScanResponse;
+
+    public BlePeripheralManager(Context context) {
+        mContext = context;
+        mHandler = new Handler(mContext.getMainLooper());
+    }
+
+    /**
+     * Registers the given callback to be notified of various events within the {@link
+     * BlePeripheralManager}.
+     *
+     * @param callback The callback to be notified.
+     */
+    void registerCallback(@NonNull Callback callback) {
+        mCallbacks.add(callback);
+    }
+
+    /**
+     * Unregisters a previously registered callback.
+     *
+     * @param callback The callback to unregister.
+     */
+    void unregisterCallback(@NonNull Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    /**
+     * Adds a listener to be notified of a write to characteristics.
+     *
+     * @param listener The listener to invoke.
+     */
+    void addOnCharacteristicWriteListener(@NonNull OnCharacteristicWriteListener listener) {
+        mWriteListeners.add(listener);
+    }
+
+    /**
+     * Removes the given listener from being notified of characteristic writes.
+     *
+     * @param listener The listener to remove.
+     */
+    void removeOnCharacteristicWriteListener(@NonNull OnCharacteristicWriteListener listener) {
+        mWriteListeners.remove(listener);
+    }
+
+    /**
+     * Adds a listener to be notified of reads to characteristics.
+     *
+     * @param listener The listener to invoke.
+     */
+    void addOnCharacteristicReadListener(@NonNull OnCharacteristicReadListener listener) {
+        mReadListeners.add(listener);
+    }
+
+    /**
+     * Removes the given listener from being notified of characteristic reads.
+     *
+     * @param listener The listener to remove.
+     */
+    void removeOnCharacteristicReadistener(@NonNull OnCharacteristicReadListener listener) {
+        mReadListeners.remove(listener);
+    }
+
+    /**
+     * Returns the current MTU size.
+     *
+     * @return The size of the MTU in bytes.
+     */
+    int getMtuSize() {
+        return mMtuSize;
+    }
+
+    /**
+     * Starts the GATT server with the given {@link BluetoothGattService} and begins advertising.
+     *
+     * <p>It is possible that BLE service is still in TURNING_ON state when this method is invoked.
+     * Therefore, several retries will be made to ensure advertising is started.
+     *
+     * @param service           {@link BluetoothGattService} that will be discovered by clients
+     * @param data              {@link AdvertiseData} data to advertise
+     * @param scanResponse      {@link AdvertiseData} scan response
+     * @param advertiseCallback {@link AdvertiseCallback} callback for advertiser
+     */
+    void startAdvertising(
+            BluetoothGattService service, AdvertiseData data,
+            AdvertiseData scanResponse, AdvertiseCallback advertiseCallback) {
+        logd(TAG, "Request to start advertising with service " + service.getUuid() + ".");
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+            loge(TAG, "Attempted start advertising, but system does not support BLE. Ignoring.");
+            return;
+        }
+        // Clears previous session before starting advertising.
+        cleanup();
+        mBluetoothGattService = service;
+        mAdvertiseCallback = advertiseCallback;
+        mAdvertiseData = data;
+        mScanResponse = scanResponse;
+        mGattServerRetryStartCount = 0;
+        mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+        mGattServer.set(mBluetoothManager.openGattServer(mContext, mGattServerCallback));
+        openGattServer();
+    }
+
+    /**
+     * Stops the GATT server from advertising.
+     *
+     * @param advertiseCallback The callback that is associated with the advertisement.
+     */
+    void stopAdvertising(AdvertiseCallback advertiseCallback) {
+        BluetoothLeAdvertiser advertiser = mAdvertiser.getAndSet(null);
+        if (advertiser != null) {
+            advertiser.stopAdvertising(advertiseCallback);
+            logd(TAG, "Advertising stopped.");
+        }
+    }
+
+    /**
+     * Notifies the characteristic change via {@link BluetoothGattServer}
+     */
+    void notifyCharacteristicChanged(
+            @NonNull BluetoothDevice device,
+            @NonNull BluetoothGattCharacteristic characteristic,
+            boolean confirm) {
+        BluetoothGattServer gattServer = mGattServer.get();
+        if (gattServer == null) {
+            return;
+        }
+
+        if (!gattServer.notifyCharacteristicChanged(device, characteristic, confirm)) {
+            loge(TAG, "notifyCharacteristicChanged failed");
+        }
+    }
+
+    /**
+     * Connect the Gatt server of the remote device to retrieve device name.
+     */
+    final void retrieveDeviceName(BluetoothDevice device) {
+        mBluetoothGatt.compareAndSet(null, device.connectGatt(mContext, false, mGattCallback));
+    }
+
+    /**
+     * Cleans up the BLE GATT server state.
+     */
+    void cleanup() {
+        logd(TAG, "Cleaning up manager.");
+        // Stops the advertiser, scanner and GATT server. This needs to be done to avoid leaks.
+        stopAdvertising(mAdvertiseCallback);
+        // Clears all registered listeners. IHU only supports single connection in peripheral role.
+        mReadListeners.clear();
+        mWriteListeners.clear();
+
+        BluetoothGattServer gattServer = mGattServer.getAndSet(null);
+        if (gattServer == null) {
+            return;
+        }
+
+        logd(TAG, "Stopping gatt server.");
+        BluetoothGatt bluetoothGatt = mBluetoothGatt.getAndSet(null);
+        if (bluetoothGatt != null) {
+            gattServer.cancelConnection(bluetoothGatt.getDevice());
+            logd(TAG, "Disconnecting gatt.");
+            bluetoothGatt.disconnect();
+            bluetoothGatt.close();
+        }
+        gattServer.clearServices();
+        gattServer.close();
+    }
+
+    private void openGattServer() {
+        // Only open one Gatt server.
+        BluetoothGattServer gattServer = mGattServer.get();
+        if (gattServer != null) {
+            logd(TAG, "Gatt Server created, retry count: " + mGattServerRetryStartCount);
+            gattServer.clearServices();
+            gattServer.addService(mBluetoothGattService);
+            AdvertiseSettings settings =
+                    new AdvertiseSettings.Builder()
+                            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
+                            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
+                            .setConnectable(true)
+                            .build();
+            mAdvertiserStartCount = 0;
+            startAdvertisingInternally(settings, mAdvertiseData, mScanResponse, mAdvertiseCallback);
+            mGattServerRetryStartCount = 0;
+        } else if (mGattServerRetryStartCount < GATT_SERVER_RETRY_LIMIT) {
+            mGattServer.set(mBluetoothManager.openGattServer(mContext, mGattServerCallback));
+            mGattServerRetryStartCount++;
+            mHandler.postDelayed(() -> openGattServer(), GATT_SERVER_RETRY_DELAY_MS);
+        } else {
+            loge(TAG, "Gatt server not created - exceeded retry limit.");
+        }
+    }
+
+    private void startAdvertisingInternally(
+            AdvertiseSettings settings, AdvertiseData advertisement,
+            AdvertiseData scanResponse, AdvertiseCallback advertiseCallback) {
+        if (BluetoothAdapter.getDefaultAdapter() != null) {
+            mAdvertiser.compareAndSet(null,
+                    BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser());
+        }
+        BluetoothLeAdvertiser advertiser = mAdvertiser.get();
+        if (advertiser != null) {
+            logd(TAG, "Advertiser created, retry count: " + mAdvertiserStartCount);
+            advertiser.startAdvertising(settings, advertisement, scanResponse, advertiseCallback);
+            mAdvertiserStartCount = 0;
+        } else if (mAdvertiserStartCount < BLE_RETRY_LIMIT) {
+            mHandler.postDelayed(
+                    () -> startAdvertisingInternally(settings, advertisement, scanResponse,
+                            advertiseCallback), BLE_RETRY_INTERVAL_MS);
+            mAdvertiserStartCount += 1;
+        } else {
+            loge(TAG, "Cannot start BLE Advertisement. Advertise Retry count: "
+                            + mAdvertiserStartCount);
+        }
+    }
+
+    private final BluetoothGattServerCallback mGattServerCallback =
+            new BluetoothGattServerCallback() {
+                @Override
+                public void onConnectionStateChange(BluetoothDevice device, int status,
+                                                    int newState) {
+                    switch (newState) {
+                        case BluetoothProfile.STATE_CONNECTED:
+                            logd(TAG, "BLE Connection State Change: CONNECTED");
+                            BluetoothGattServer gattServer = mGattServer.get();
+                            if (gattServer == null) {
+                                return;
+                            }
+                            gattServer.connect(device, /* autoConnect= */ false);
+                            for (Callback callback : mCallbacks) {
+                                callback.onRemoteDeviceConnected(device);
+                            }
+                            break;
+                        case BluetoothProfile.STATE_DISCONNECTED:
+                            logd(TAG, "BLE Connection State Change: DISCONNECTED");
+                            for (Callback callback : mCallbacks) {
+                                callback.onRemoteDeviceDisconnected(device);
+                            }
+                            break;
+                        default:
+                            logw(TAG, "Connection state not connecting or disconnecting; ignoring: "
+                                    + newState);
+                    }
+                }
+
+                @Override
+                public void onServiceAdded(int status, BluetoothGattService service) {
+                    logd(TAG, "Service added status: " + status + " uuid: " + service.getUuid());
+                }
+
+                @Override
+                public void onCharacteristicWriteRequest(
+                        BluetoothDevice device,
+                        int requestId,
+                        BluetoothGattCharacteristic characteristic,
+                        boolean preparedWrite,
+                        boolean responseNeeded,
+                        int offset,
+                        byte[] value) {
+                    BluetoothGattServer gattServer = mGattServer.get();
+                    if (gattServer == null) {
+                        return;
+                    }
+                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset,
+                            value);
+                    for (OnCharacteristicWriteListener listener : mWriteListeners) {
+                        listener.onCharacteristicWrite(device, characteristic, value);
+                    }
+                }
+
+                @Override
+                public void onDescriptorWriteRequest(
+                        BluetoothDevice device,
+                        int requestId,
+                        BluetoothGattDescriptor descriptor,
+                        boolean preparedWrite,
+                        boolean responseNeeded,
+                        int offset,
+                        byte[] value) {
+                    logd(TAG, "Write request for descriptor: "
+                            + descriptor.getUuid()
+                            + "; value: "
+                            + ByteUtils.byteArrayToHexString(value));
+                    BluetoothGattServer gattServer = mGattServer.get();
+                    if (gattServer == null) {
+                        return;
+                    }
+                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset,
+                            value);
+                }
+
+                @Override
+                public void onMtuChanged(BluetoothDevice device, int mtu) {
+                    logd(TAG, "onMtuChanged: " + mtu + " for device " + device.getAddress());
+
+                    mMtuSize = mtu;
+
+                    for (Callback callback : mCallbacks) {
+                        callback.onMtuSizeChanged(mtu);
+                    }
+                }
+
+                @Override
+                public void onNotificationSent(BluetoothDevice device, int status) {
+                    super.onNotificationSent(device, status);
+                    if (status == BluetoothGatt.GATT_SUCCESS) {
+                        logd(TAG, "Notification sent successfully. Device: " + device.getAddress()
+                                + ", Status: " + status + ". Notifying all listeners.");
+                        for (OnCharacteristicReadListener listener : mReadListeners) {
+                            listener.onCharacteristicRead(device);
+                        }
+                    } else {
+                        loge(TAG, "Notification failed. Device: " + device + ", Status: "
+                                + status);
+                    }
+                }
+            };
+
+    private final BluetoothGattCallback mGattCallback =
+            new BluetoothGattCallback() {
+                @Override
+                public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+                    logd(TAG, "Gatt Connection State Change: " + newState);
+                    switch (newState) {
+                        case BluetoothProfile.STATE_CONNECTED:
+                            logd(TAG, "Gatt connected");
+                            BluetoothGatt bluetoothGatt = mBluetoothGatt.get();
+                            if (bluetoothGatt == null) {
+                                break;
+                            }
+                            bluetoothGatt.discoverServices();
+                            break;
+                        case BluetoothProfile.STATE_DISCONNECTED:
+                            logd(TAG, "Gatt Disconnected");
+                            break;
+                        default:
+                            logd(TAG, "Connection state not connecting or disconnecting; ignoring: "
+                                    + newState);
+                    }
+                }
+
+                @Override
+                public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+                    logd(TAG, "Gatt Services Discovered");
+                    BluetoothGatt bluetoothGatt = mBluetoothGatt.get();
+                    if (bluetoothGatt == null) {
+                        return;
+                    }
+                    BluetoothGattService gapService = bluetoothGatt.getService(
+                            GENERIC_ACCESS_PROFILE_UUID);
+                    if (gapService == null) {
+                        loge(TAG, "Generic Access Service is null.");
+                        return;
+                    }
+                    BluetoothGattCharacteristic deviceNameCharacteristic =
+                            gapService.getCharacteristic(DEVICE_NAME_UUID);
+                    if (deviceNameCharacteristic == null) {
+                        loge(TAG, "Device Name Characteristic is null.");
+                        return;
+                    }
+                    bluetoothGatt.readCharacteristic(deviceNameCharacteristic);
+                }
+
+                @Override
+                public void onCharacteristicRead(
+                        BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
+                        int status) {
+                    if (status == BluetoothGatt.GATT_SUCCESS) {
+                        String deviceName = characteristic.getStringValue(0);
+                        logd(TAG, "BLE Device Name: " + deviceName);
+
+                        for (Callback callback : mCallbacks) {
+                            callback.onDeviceNameRetrieved(deviceName);
+                        }
+                    } else {
+                        loge(TAG, "Reading GAP Failed: " + status);
+                    }
+                }
+            };
+
+    /**
+     * Interface to be notified of various events within the {@link BlePeripheralManager}.
+     */
+    interface Callback {
+        /**
+         * Triggered when the name of the remote device is retrieved.
+         *
+         * @param deviceName Name of the remote device.
+         */
+        void onDeviceNameRetrieved(@Nullable String deviceName);
+
+        /**
+         * Triggered if a remote client has requested to change the MTU for a given connection.
+         *
+         * @param size The new MTU size.
+         */
+        void onMtuSizeChanged(int size);
+
+        /**
+         * Triggered when a device (GATT client) connected.
+         *
+         * @param device Remote device that connected on BLE.
+         */
+        void onRemoteDeviceConnected(@NonNull BluetoothDevice device);
+
+        /**
+         * Triggered when a device (GATT client) disconnected.
+         *
+         * @param device Remote device that disconnected on BLE.
+         */
+        void onRemoteDeviceDisconnected(@NonNull BluetoothDevice device);
+    }
+
+    /**
+     * An interface for classes that wish to be notified of writes to a characteristic.
+     */
+    interface OnCharacteristicWriteListener {
+        /**
+         * Triggered when this BlePeripheralManager receives a write request from a remote device.
+         *
+         * @param device         The bluetooth device that holds the characteristic.
+         * @param characteristic The characteristic that was written to.
+         * @param value          The value that was written.
+         */
+        void onCharacteristicWrite(
+                @NonNull BluetoothDevice device,
+                @NonNull BluetoothGattCharacteristic characteristic,
+                @NonNull byte[] value);
+    }
+
+    /**
+     * An interface for classes that wish to be notified of reads on a characteristic.
+     */
+    interface OnCharacteristicReadListener {
+        /**
+         * Triggered when this BlePeripheralManager receives a read request from a remote device.
+         *
+         * @param device The bluetooth device that holds the characteristic.
+         */
+        void onCharacteristicRead(@NonNull BluetoothDevice device);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/CarBleCentralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/CarBleCentralManager.java
new file mode 100644
index 0000000..e8d17e5
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/CarBleCentralManager.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.ble;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+import static com.android.car.connecteddevice.util.ScanDataAnalyzer.containsUuidsInOverflow;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanRecord;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
+import android.content.Context;
+import android.os.ParcelUuid;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.connecteddevice.AssociationCallback;
+import com.android.car.connecteddevice.connection.CarBluetoothManager;
+import com.android.car.connecteddevice.oob.OobChannel;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * Communication manager for a car that maintains continuous connections with all devices in the car
+ * for the duration of a drive.
+ */
+public class CarBleCentralManager extends CarBluetoothManager {
+
+    private static final String TAG = "CarBleCentralManager";
+
+    // system/bt/internal_include/bt_target.h#GATT_MAX_PHY_CHANNEL
+    private static final int MAX_CONNECTIONS = 7;
+
+    private static final UUID CHARACTERISTIC_CONFIG =
+            UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
+
+    private static final int STATUS_FORCED_DISCONNECT = -1;
+
+    private final ScanSettings mScanSettings = new ScanSettings.Builder()
+            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
+            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
+            .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
+            .build();
+
+    private final CopyOnWriteArraySet<ConnectedRemoteDevice> mIgnoredDevices =
+            new CopyOnWriteArraySet<>();
+
+    private final Context mContext;
+
+    private final BleCentralManager mBleCentralManager;
+
+    private final UUID mServiceUuid;
+
+    private final UUID mWriteCharacteristicUuid;
+
+    private final UUID mReadCharacteristicUuid;
+
+    private final BigInteger mParsedBgServiceBitMask;
+
+    /**
+     * Create a new manager.
+     *
+     * @param context The caller's [Context].
+     * @param bleCentralManager [BleCentralManager] for establishing connections.
+     * @param connectedDeviceStorage Shared [ConnectedDeviceStorage] for companion features.
+     * @param serviceUuid [UUID] of peripheral's service.
+     * @param bgServiceMask iOS overflow bit mask for service UUID.
+     * @param writeCharacteristicUuid [UUID] of characteristic the car will write to.
+     * @param readCharacteristicUuid [UUID] of characteristic the device will write to.
+     */
+    public CarBleCentralManager(
+            @NonNull Context context,
+            @NonNull BleCentralManager bleCentralManager,
+            @NonNull ConnectedDeviceStorage connectedDeviceStorage,
+            @NonNull UUID serviceUuid,
+            @NonNull String bgServiceMask,
+            @NonNull UUID writeCharacteristicUuid,
+            @NonNull UUID readCharacteristicUuid) {
+        super(connectedDeviceStorage);
+        mContext = context;
+        mBleCentralManager = bleCentralManager;
+        mServiceUuid = serviceUuid;
+        mWriteCharacteristicUuid = writeCharacteristicUuid;
+        mReadCharacteristicUuid = readCharacteristicUuid;
+        mParsedBgServiceBitMask = new BigInteger(bgServiceMask, 16);
+    }
+
+    @Override
+    public void start() {
+        super.start();
+        mBleCentralManager.startScanning(/* filters= */ null, mScanSettings, mScanCallback);
+    }
+
+    @Override
+    public void stop() {
+        super.stop();
+        mBleCentralManager.stopScanning();
+    }
+
+    @Override
+    public void disconnectDevice(String deviceId) {
+        logd(TAG, "Request to disconnect from device " + deviceId + ".");
+        ConnectedRemoteDevice device = getConnectedDevice(deviceId);
+        if (device == null) {
+            return;
+        }
+
+        deviceDisconnected(device, STATUS_FORCED_DISCONNECT);
+    }
+
+    //TODO(b/141312136): Support car central role
+    @Override
+    public AssociationCallback getAssociationCallback() {
+        return null;
+    }
+
+    @Override
+    public void setAssociationCallback(AssociationCallback callback) {
+
+    }
+
+    @Override
+    public void connectToDevice(UUID deviceId) {
+
+    }
+
+    @Override
+    public void initiateConnectionToDevice(UUID deviceId) {
+
+    }
+
+    @Override
+    public void startAssociation(String nameForAssociation, AssociationCallback callback) {
+
+    }
+
+    @Override
+    public void startOutOfBandAssociation(String nameForAssociation, OobChannel oobChannel,
+            AssociationCallback callback) {
+
+    }
+
+    private void ignoreDevice(@NonNull ConnectedRemoteDevice device) {
+        mIgnoredDevices.add(device);
+    }
+
+    private boolean isDeviceIgnored(@NonNull BluetoothDevice device) {
+        for (ConnectedRemoteDevice connectedDevice : mIgnoredDevices) {
+            if (device.equals(connectedDevice.mDevice)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean shouldAttemptConnection(@NonNull ScanResult result) {
+        // Ignore any results that are not connectable.
+        if (!result.isConnectable()) {
+            return false;
+        }
+
+        // Do not attempt to connect if we have already hit our max. This should rarely happen
+        // and is protecting against a race condition of scanning stopped and new results coming in.
+        if (getConnectedDevicesCount() >= MAX_CONNECTIONS) {
+            return false;
+        }
+
+        BluetoothDevice device = result.getDevice();
+
+        // Do not connect if device has already been ignored.
+        if (isDeviceIgnored(device)) {
+            return false;
+        }
+
+        // Check if already attempting to connect to this device.
+        if (getConnectedDevice(device) != null) {
+            return false;
+        }
+
+
+        // Ignore any device without a scan record.
+        ScanRecord scanRecord = result.getScanRecord();
+        if (scanRecord == null) {
+            return false;
+        }
+
+        // Connect to any device that is advertising our service UUID.
+        List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids();
+        if (serviceUuids != null) {
+            for (ParcelUuid serviceUuid : serviceUuids) {
+                if (serviceUuid.getUuid().equals(mServiceUuid)) {
+                    return true;
+                }
+            }
+        }
+        if (containsUuidsInOverflow(scanRecord.getBytes(), mParsedBgServiceBitMask)) {
+            return true;
+        }
+
+        // Can safely ignore devices advertising unrecognized service uuids.
+        if (serviceUuids != null && !serviceUuids.isEmpty()) {
+            return false;
+        }
+
+        // TODO(b/139066293): Current implementation quickly exhausts connections resulting in
+        // greatly reduced performance for connecting to devices we know we want to connect to.
+        // Return true once fixed.
+        return false;
+    }
+
+    private void startDeviceConnection(@NonNull BluetoothDevice device) {
+        BluetoothGatt gatt = device.connectGatt(mContext, /* autoConnect= */ false,
+                mConnectionCallback, BluetoothDevice.TRANSPORT_LE);
+        if (gatt == null) {
+            return;
+        }
+
+        ConnectedRemoteDevice bleDevice = new ConnectedRemoteDevice(device, gatt);
+        bleDevice.mState = ConnectedDeviceState.CONNECTING;
+        addConnectedDevice(bleDevice);
+
+        // Stop scanning if we have reached the maximum number of connections.
+        if (getConnectedDevicesCount() >= MAX_CONNECTIONS) {
+            mBleCentralManager.stopScanning();
+        }
+    }
+
+    private void deviceConnected(@NonNull ConnectedRemoteDevice device) {
+        if (device.mGatt == null) {
+            loge(TAG, "Device connected with null gatt. Disconnecting.");
+            deviceDisconnected(device, BluetoothProfile.STATE_DISCONNECTED);
+            return;
+        }
+        device.mState = ConnectedDeviceState.PENDING_VERIFICATION;
+        device.mGatt.discoverServices();
+        logd(TAG, "New device connected: " + device.mGatt.getDevice().getAddress()
+                + ". Active connections: " + getConnectedDevicesCount() + ".");
+    }
+
+    private void deviceDisconnected(@NonNull ConnectedRemoteDevice device, int status) {
+        removeConnectedDevice(device);
+        if (device.mGatt != null) {
+            device.mGatt.close();
+        }
+        if (device.mDeviceId != null) {
+            mCallbacks.invoke(callback -> callback.onDeviceDisconnected(device.mDeviceId));
+        }
+        logd(TAG, "Device with id " + device.mDeviceId + " disconnected with state " + status
+                + ". Remaining active connections: " + getConnectedDevicesCount() + ".");
+    }
+
+    private final ScanCallback mScanCallback = new ScanCallback() {
+        @Override
+        public void onScanResult(int callbackType, ScanResult result) {
+            super.onScanResult(callbackType, result);
+            if (shouldAttemptConnection(result)) {
+                startDeviceConnection(result.getDevice());
+            }
+        }
+
+        @Override
+        public void onScanFailed(int errorCode) {
+            super.onScanFailed(errorCode);
+            loge(TAG, "BLE scanning failed with error code: " + errorCode);
+        }
+    };
+
+    private final BluetoothGattCallback mConnectionCallback = new BluetoothGattCallback() {
+        @Override
+        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+            super.onConnectionStateChange(gatt, status, newState);
+            if (gatt == null) {
+                logw(TAG, "Null gatt passed to onConnectionStateChange. Ignoring.");
+                return;
+            }
+
+            ConnectedRemoteDevice connectedDevice = getConnectedDevice(gatt);
+            if (connectedDevice == null) {
+                return;
+            }
+
+            switch (newState) {
+                case BluetoothProfile.STATE_CONNECTED:
+                    deviceConnected(connectedDevice);
+                    break;
+                case BluetoothProfile.STATE_DISCONNECTED:
+                    deviceDisconnected(connectedDevice, status);
+                    break;
+                default:
+                    logd(TAG, "Connection state changed. New state: " + newState + " status: "
+                            + status);
+            }
+        }
+
+        @Override
+        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+            super.onServicesDiscovered(gatt, status);
+            if (gatt == null) {
+                logw(TAG, "Null gatt passed to onServicesDiscovered. Ignoring.");
+                return;
+            }
+
+            ConnectedRemoteDevice connectedDevice = getConnectedDevice(gatt);
+            if (connectedDevice == null) {
+                return;
+            }
+            BluetoothGattService service = gatt.getService(mServiceUuid);
+            if (service == null) {
+                ignoreDevice(connectedDevice);
+                gatt.disconnect();
+                return;
+            }
+
+            connectedDevice.mState = ConnectedDeviceState.CONNECTED;
+            BluetoothGattCharacteristic writeCharacteristic =
+                    service.getCharacteristic(mWriteCharacteristicUuid);
+            BluetoothGattCharacteristic readCharacteristic =
+                    service.getCharacteristic(mReadCharacteristicUuid);
+            if (writeCharacteristic == null || readCharacteristic == null) {
+                logw(TAG, "Unable to find expected characteristics on peripheral.");
+                gatt.disconnect();
+                return;
+            }
+
+            // Turn on notifications for read characteristic.
+            BluetoothGattDescriptor descriptor =
+                    readCharacteristic.getDescriptor(CHARACTERISTIC_CONFIG);
+            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
+            if (!gatt.writeDescriptor(descriptor)) {
+                loge(TAG, "Write descriptor to read characteristic failed.");
+                gatt.disconnect();
+                return;
+            }
+
+            if (!gatt.setCharacteristicNotification(readCharacteristic, /* enable= */ true)) {
+                loge(TAG, "Set notifications to read characteristic failed.");
+                gatt.disconnect();
+                return;
+            }
+
+            logd(TAG, "Service and characteristics successfully discovered.");
+        }
+
+        @Override
+        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+                int status) {
+            super.onDescriptorWrite(gatt, descriptor, status);
+            if (gatt == null) {
+                logw(TAG, "Null gatt passed to onDescriptorWrite. Ignoring.");
+                return;
+            }
+            // TODO(b/141312136): Create SecureBleChannel and assign to connectedDevice.
+        }
+    };
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/CarBlePeripheralManager.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/CarBlePeripheralManager.java
new file mode 100644
index 0000000..a05b5f7
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/ble/CarBlePeripheralManager.java
@@ -0,0 +1,510 @@
+/*
+ * 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.
+ */
+
+package com.android.car.connecteddevice.connection.ble;
+
+import static com.android.car.connecteddevice.ConnectedDeviceManager.DEVICE_ERROR_UNEXPECTED_DISCONNECTION;
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.ParcelUuid;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.connecteddevice.AssociationCallback;
+import com.android.car.connecteddevice.connection.AssociationSecureChannel;
+import com.android.car.connecteddevice.connection.CarBluetoothManager;
+import com.android.car.connecteddevice.connection.OobAssociationSecureChannel;
+import com.android.car.connecteddevice.connection.ReconnectSecureChannel;
+import com.android.car.connecteddevice.connection.SecureChannel;
+import com.android.car.connecteddevice.oob.OobChannel;
+import com.android.car.connecteddevice.oob.OobConnectionManager;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+import com.android.car.connecteddevice.util.EventLog;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.UUID;
+
+/**
+ * Communication manager that allows for targeted connections to a specific device in the car.
+ */
+public class CarBlePeripheralManager extends CarBluetoothManager {
+
+    private static final String TAG = "CarBlePeripheralManager";
+
+    // Attribute protocol bytes attached to message. Available write size is MTU size minus att
+    // bytes.
+    private static final int ATT_PROTOCOL_BYTES = 3;
+
+    private static final UUID CLIENT_CHARACTERISTIC_CONFIG =
+            UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
+
+    private static final int SALT_BYTES = 8;
+
+    private static final int TOTAL_AD_DATA_BYTES = 16;
+
+    private static final int TRUNCATED_BYTES = 3;
+
+    private static final String TIMEOUT_HANDLER_THREAD_NAME = "peripheralThread";
+
+    private final BluetoothGattDescriptor mDescriptor =
+            new BluetoothGattDescriptor(CLIENT_CHARACTERISTIC_CONFIG,
+                    BluetoothGattDescriptor.PERMISSION_READ
+                            | BluetoothGattDescriptor.PERMISSION_WRITE);
+
+    private final BlePeripheralManager mBlePeripheralManager;
+
+    private final UUID mAssociationServiceUuid;
+
+    private final UUID mReconnectServiceUuid;
+
+    private final UUID mReconnectDataUuid;
+
+    private final BluetoothGattCharacteristic mWriteCharacteristic;
+
+    private final BluetoothGattCharacteristic mReadCharacteristic;
+
+    private HandlerThread mTimeoutHandlerThread;
+
+    private Handler mTimeoutHandler;
+
+    private final Duration mMaxReconnectAdvertisementDuration;
+
+    private final int mDefaultMtuSize;
+
+    private String mReconnectDeviceId;
+
+    private byte[] mReconnectChallenge;
+
+    private AdvertiseCallback mAdvertiseCallback;
+
+    private OobConnectionManager mOobConnectionManager;
+
+    private AssociationCallback mAssociationCallback;
+
+    /**
+     * Initialize a new instance of manager.
+     *
+     * @param blePeripheralManager    {@link BlePeripheralManager} for establishing connection.
+     * @param connectedDeviceStorage  Shared {@link ConnectedDeviceStorage} for companion features.
+     * @param associationServiceUuid  {@link UUID} of association service.
+     * @param reconnectServiceUuid    {@link UUID} of reconnect service.
+     * @param reconnectDataUuid       {@link UUID} key of reconnect advertisement data.
+     * @param writeCharacteristicUuid {@link UUID} of characteristic the car will write to.
+     * @param readCharacteristicUuid  {@link UUID} of characteristic the device will write to.
+     * @param maxReconnectAdvertisementDuration Maximum duration to advertise for reconnect before
+     *                                          restarting.
+     * @param defaultMtuSize          Default MTU size for new channels.
+     */
+    public CarBlePeripheralManager(@NonNull BlePeripheralManager blePeripheralManager,
+            @NonNull ConnectedDeviceStorage connectedDeviceStorage,
+            @NonNull UUID associationServiceUuid,
+            @NonNull UUID reconnectServiceUuid,
+            @NonNull UUID reconnectDataUuid,
+            @NonNull UUID writeCharacteristicUuid,
+            @NonNull UUID readCharacteristicUuid,
+            @NonNull Duration maxReconnectAdvertisementDuration,
+            int defaultMtuSize) {
+        super(connectedDeviceStorage);
+        mBlePeripheralManager = blePeripheralManager;
+        mAssociationServiceUuid = associationServiceUuid;
+        mReconnectServiceUuid = reconnectServiceUuid;
+        mReconnectDataUuid = reconnectDataUuid;
+        mDescriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
+        mWriteCharacteristic = new BluetoothGattCharacteristic(writeCharacteristicUuid,
+                BluetoothGattCharacteristic.PROPERTY_NOTIFY,
+                BluetoothGattCharacteristic.PROPERTY_READ);
+        mReadCharacteristic = new BluetoothGattCharacteristic(readCharacteristicUuid,
+                BluetoothGattCharacteristic.PROPERTY_WRITE
+                        | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
+                BluetoothGattCharacteristic.PERMISSION_WRITE);
+        mReadCharacteristic.addDescriptor(mDescriptor);
+        mMaxReconnectAdvertisementDuration = maxReconnectAdvertisementDuration;
+        mDefaultMtuSize = defaultMtuSize;
+    }
+
+    @Override
+    public void start() {
+        super.start();
+        mTimeoutHandlerThread = new HandlerThread(TIMEOUT_HANDLER_THREAD_NAME);
+        mTimeoutHandlerThread.start();
+        mTimeoutHandler = new Handler(mTimeoutHandlerThread.getLooper());
+    }
+
+    @Override
+    public void stop() {
+        super.stop();
+        if (mTimeoutHandlerThread != null) {
+            mTimeoutHandlerThread.quit();
+        }
+        reset();
+    }
+
+    @Override
+    public void disconnectDevice(@NonNull String deviceId) {
+        if (deviceId.equals(mReconnectDeviceId)) {
+            logd(TAG, "Reconnection canceled for device " + deviceId + ".");
+            reset();
+            return;
+        }
+        ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+        if (connectedDevice == null || !deviceId.equals(connectedDevice.mDeviceId)) {
+            return;
+        }
+        reset();
+    }
+
+    @Override
+    public AssociationCallback getAssociationCallback() {
+        return mAssociationCallback;
+    }
+
+    @Override
+    public void setAssociationCallback(AssociationCallback callback) {
+        mAssociationCallback = callback;
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        logd(TAG, "Resetting state.");
+        mBlePeripheralManager.cleanup();
+        mReconnectDeviceId = null;
+        mReconnectChallenge = null;
+        mOobConnectionManager = null;
+        mAssociationCallback = null;
+    }
+
+    @Override
+    public void initiateConnectionToDevice(@NonNull UUID deviceId) {
+        mReconnectDeviceId = deviceId.toString();
+        mAdvertiseCallback = new AdvertiseCallback() {
+            @Override
+            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
+                super.onStartSuccess(settingsInEffect);
+                mTimeoutHandler.postDelayed(mTimeoutRunnable,
+                        mMaxReconnectAdvertisementDuration.toMillis());
+                logd(TAG, "Successfully started advertising for device " + deviceId + ".");
+            }
+        };
+        mBlePeripheralManager.unregisterCallback(mAssociationPeripheralCallback);
+        mBlePeripheralManager.registerCallback(mReconnectPeripheralCallback);
+        mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
+        byte[] advertiseData = createReconnectData(mReconnectDeviceId);
+        if (advertiseData == null) {
+            loge(TAG, "Unable to create advertisement data. Aborting reconnect.");
+            return;
+        }
+        startAdvertising(mReconnectServiceUuid, mAdvertiseCallback, advertiseData,
+                mReconnectDataUuid, /* scanResponse= */ null, /* scanResponseUuid= */ null);
+    }
+
+    /**
+     * Create data for reconnection advertisement.
+     *
+     * <p></p><p>Process:</p>
+     * <ol>
+     * <li>Generate random {@value SALT_BYTES} byte salt and zero-pad to
+     * {@value TOTAL_AD_DATA_BYTES} bytes.
+     * <li>Hash with stored challenge secret and truncate to {@value TRUNCATED_BYTES} bytes.
+     * <li>Concatenate hashed {@value TRUNCATED_BYTES} bytes with salt and return.
+     * </ol>
+     */
+    @Nullable
+    private byte[] createReconnectData(String deviceId) {
+        byte[] salt = ByteUtils.randomBytes(SALT_BYTES);
+        byte[] zeroPadded = ByteUtils.concatByteArrays(salt,
+                new byte[TOTAL_AD_DATA_BYTES - SALT_BYTES]);
+        mReconnectChallenge = mStorage.hashWithChallengeSecret(deviceId, zeroPadded);
+        if (mReconnectChallenge == null) {
+            return null;
+        }
+        return ByteUtils.concatByteArrays(Arrays.copyOf(mReconnectChallenge, TRUNCATED_BYTES),
+                salt);
+
+    }
+
+    @Override
+    public void startAssociation(@NonNull String nameForAssociation,
+            @NonNull AssociationCallback callback) {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter == null) {
+            loge(TAG, "Bluetooth is unavailable on this device. Unable to start associating.");
+            return;
+        }
+
+        reset();
+        mAssociationCallback = callback;
+        mBlePeripheralManager.unregisterCallback(mReconnectPeripheralCallback);
+        mBlePeripheralManager.registerCallback(mAssociationPeripheralCallback);
+        mAdvertiseCallback = new AdvertiseCallback() {
+            @Override
+            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
+                super.onStartSuccess(settingsInEffect);
+                callback.onAssociationStartSuccess(nameForAssociation);
+                logd(TAG, "Successfully started advertising for association.");
+            }
+
+            @Override
+            public void onStartFailure(int errorCode) {
+                super.onStartFailure(errorCode);
+                callback.onAssociationStartFailure();
+                logd(TAG, "Failed to start advertising for association. Error code: " + errorCode);
+            }
+        };
+        startAdvertising(mAssociationServiceUuid, mAdvertiseCallback, /* advertiseData= */null,
+                /* advertiseDataUuid= */ null, nameForAssociation.getBytes(), mReconnectDataUuid);
+    }
+
+    /** Start the association with a new device using out of band verification code exchange */
+    @Override
+    public void startOutOfBandAssociation(
+            @NonNull String nameForAssociation,
+            @NonNull OobChannel oobChannel,
+            @NonNull AssociationCallback callback) {
+
+        logd(TAG, "Starting out of band association.");
+        startAssociation(nameForAssociation, new AssociationCallback() {
+            @Override
+            public void onAssociationStartSuccess(String deviceName) {
+                mAssociationCallback = callback;
+                boolean success = mOobConnectionManager.startOobExchange(oobChannel);
+                if (!success) {
+                    callback.onAssociationStartFailure();
+                    return;
+                }
+                callback.onAssociationStartSuccess(deviceName);
+            }
+
+            @Override
+            public void onAssociationStartFailure() {
+                callback.onAssociationStartFailure();
+            }
+        });
+        mOobConnectionManager = new OobConnectionManager();
+    }
+
+    private void startAdvertising(@NonNull UUID serviceUuid, @NonNull AdvertiseCallback callback,
+            @Nullable byte[] advertiseData,
+            @Nullable UUID advertiseDataUuid, @Nullable byte[] scanResponse,
+            @Nullable UUID scanResponseUuid) {
+        BluetoothGattService gattService = new BluetoothGattService(serviceUuid,
+                BluetoothGattService.SERVICE_TYPE_PRIMARY);
+        gattService.addCharacteristic(mWriteCharacteristic);
+        gattService.addCharacteristic(mReadCharacteristic);
+
+        AdvertiseData.Builder advertisementBuilder =
+                new AdvertiseData.Builder();
+        ParcelUuid uuid = new ParcelUuid(serviceUuid);
+        advertisementBuilder.addServiceUuid(uuid);
+        if (advertiseData != null) {
+            ParcelUuid dataUuid = uuid;
+            if (advertiseDataUuid != null) {
+                dataUuid = new ParcelUuid(advertiseDataUuid);
+            }
+            advertisementBuilder.addServiceData(dataUuid, advertiseData);
+        }
+
+        AdvertiseData.Builder scanResponseBuilder =
+                new AdvertiseData.Builder();
+        if (scanResponse != null && scanResponseUuid != null) {
+            ParcelUuid scanResponseParcelUuid = new ParcelUuid(scanResponseUuid);
+            scanResponseBuilder.addServiceData(scanResponseParcelUuid, scanResponse);
+        }
+
+        mBlePeripheralManager.startAdvertising(gattService, advertisementBuilder.build(),
+                scanResponseBuilder.build(), callback);
+    }
+
+    private void addConnectedDevice(BluetoothDevice device, boolean isReconnect) {
+        addConnectedDevice(device, isReconnect, /* oobConnectionManager= */ null);
+    }
+
+    private void addConnectedDevice(@NonNull BluetoothDevice device, boolean isReconnect,
+            @Nullable OobConnectionManager oobConnectionManager) {
+        EventLog.onDeviceConnected();
+        mBlePeripheralManager.stopAdvertising(mAdvertiseCallback);
+        if (mTimeoutHandler != null) {
+            mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
+        }
+
+        if (device.getName() == null) {
+            logd(TAG, "Device connected, but name is null; issuing request to retrieve device "
+                    + "name.");
+            mBlePeripheralManager.retrieveDeviceName(device);
+        } else {
+            setClientDeviceName(device.getName());
+        }
+        setClientDeviceAddress(device.getAddress());
+
+        BleDeviceMessageStream secureStream = new BleDeviceMessageStream(mBlePeripheralManager,
+                device, mWriteCharacteristic, mReadCharacteristic,
+                mDefaultMtuSize - ATT_PROTOCOL_BYTES);
+        secureStream.setMessageReceivedErrorListener(
+                exception -> {
+                    disconnectWithError("Error occurred in stream: " + exception.getMessage());
+                });
+        SecureChannel secureChannel;
+        if (isReconnect) {
+            secureChannel = new ReconnectSecureChannel(secureStream, mStorage, mReconnectDeviceId,
+                    mReconnectChallenge);
+        } else if (oobConnectionManager != null) {
+            secureChannel = new OobAssociationSecureChannel(secureStream, mStorage,
+                    oobConnectionManager);
+        } else {
+            secureChannel = new AssociationSecureChannel(secureStream, mStorage);
+        }
+        secureChannel.registerCallback(mSecureChannelCallback);
+        ConnectedRemoteDevice connectedDevice = new ConnectedRemoteDevice(device, /* gatt= */ null);
+        connectedDevice.mSecureChannel = secureChannel;
+        addConnectedDevice(connectedDevice);
+        if (isReconnect) {
+            setDeviceIdAndNotifyCallbacks(mReconnectDeviceId);
+            mReconnectDeviceId = null;
+            mReconnectChallenge = null;
+        }
+    }
+
+    private void setMtuSize(int mtuSize) {
+        ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+        if (connectedDevice != null
+                && connectedDevice.mSecureChannel != null
+                && connectedDevice.mSecureChannel.getStream() != null) {
+            ((BleDeviceMessageStream) connectedDevice.mSecureChannel.getStream())
+                    .setMaxWriteSize(mtuSize - ATT_PROTOCOL_BYTES);
+        }
+    }
+
+    private final BlePeripheralManager.Callback mReconnectPeripheralCallback =
+            new BlePeripheralManager.Callback() {
+
+                @Override
+                public void onDeviceNameRetrieved(String deviceName) {
+                    // Ignored.
+                }
+
+                @Override
+                public void onMtuSizeChanged(int size) {
+                    setMtuSize(size);
+                }
+
+                @Override
+                public void onRemoteDeviceConnected(BluetoothDevice device) {
+                    addConnectedDevice(device, /* isReconnect= */ true);
+                }
+
+                @Override
+                public void onRemoteDeviceDisconnected(BluetoothDevice device) {
+                    String deviceId = mReconnectDeviceId;
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice(device);
+                    // Reset before invoking callbacks to avoid a race condition with reconnect
+                    // logic.
+                    reset();
+                    if (connectedDevice != null) {
+                        deviceId = connectedDevice.mDeviceId;
+                    }
+                    final String finalDeviceId = deviceId;
+                    if (finalDeviceId == null) {
+                        logw(TAG, "Callbacks were not issued for disconnect because the device id "
+                                + "was null.");
+                        return;
+                    }
+                    logd(TAG, "Connected device " + finalDeviceId + " disconnected.");
+                    mCallbacks.invoke(callback -> callback.onDeviceDisconnected(finalDeviceId));
+                }
+            };
+
+    private final BlePeripheralManager.Callback mAssociationPeripheralCallback =
+            new BlePeripheralManager.Callback() {
+                @Override
+                public void onDeviceNameRetrieved(String deviceName) {
+                    if (deviceName == null) {
+                        return;
+                    }
+                    setClientDeviceName(deviceName);
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
+                        return;
+                    }
+                    mStorage.updateAssociatedDeviceName(connectedDevice.mDeviceId, deviceName);
+                }
+
+                @Override
+                public void onMtuSizeChanged(int size) {
+                    setMtuSize(size);
+                }
+
+                @Override
+                public void onRemoteDeviceConnected(BluetoothDevice device) {
+                    addConnectedDevice(device, /* isReconnect= */ false, mOobConnectionManager);
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+                    if (connectedDevice == null || connectedDevice.mSecureChannel == null) {
+                        return;
+                    }
+                    ((AssociationSecureChannel) connectedDevice.mSecureChannel)
+                            .setShowVerificationCodeListener(
+                                    code -> {
+                                        if (!isAssociating()) {
+                                            loge(TAG, "No valid callback for association.");
+                                            return;
+                                        }
+                                        mAssociationCallback.onVerificationCodeAvailable(code);
+                                    });
+                }
+
+                @Override
+                public void onRemoteDeviceDisconnected(BluetoothDevice device) {
+                    logd(TAG, "Remote device disconnected.");
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice(device);
+                    if (isAssociating()) {
+                        mAssociationCallback.onAssociationError(
+                                DEVICE_ERROR_UNEXPECTED_DISCONNECTION);
+                    }
+                    // Reset before invoking callbacks to avoid a race condition with reconnect
+                    // logic.
+                    reset();
+                    if (connectedDevice == null || connectedDevice.mDeviceId == null) {
+                        logw(TAG, "Callbacks were not issued for disconnect.");
+                        return;
+                    }
+                    mCallbacks.invoke(callback -> callback.onDeviceDisconnected(
+                            connectedDevice.mDeviceId));
+                }
+            };
+
+    private final Runnable mTimeoutRunnable = new Runnable() {
+        @Override
+        public void run() {
+            logd(TAG, "Timeout period expired without a connection. Restarting advertisement.");
+            mBlePeripheralManager.stopAdvertising(mAdvertiseCallback);
+            connectToDevice(UUID.fromString(mReconnectDeviceId));
+        }
+    };
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/AcceptTask.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/AcceptTask.java
new file mode 100644
index 0000000..2ada256
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/AcceptTask.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothServerSocket;
+import android.bluetooth.BluetoothSocket;
+
+import androidx.annotation.Nullable;
+
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * This task runs while listening for incoming connections. It behaves like a server. It runs until
+ * a connection is accepted (or until cancelled).
+ */
+public class AcceptTask implements Runnable {
+    private static final String TAG = "AcceptTask";
+    private static final String SERVICE_NAME_SECURE = "NAME_SECURE";
+    private static final String SERVICE_NAME_INSECURE = "NAME_INSECURE";
+    private final UUID mServiceUuid;
+    private final boolean mIsSecure;
+    private final OnTaskCompletedListener mListener;
+    private final BluetoothAdapter mAdapter;
+    private BluetoothServerSocket mServerSocket;
+
+    AcceptTask(BluetoothAdapter adapter, boolean isSecure, UUID serviceUuid,
+            OnTaskCompletedListener listener) {
+        mListener = listener;
+        mAdapter = adapter;
+        mServiceUuid = serviceUuid;
+        mIsSecure = isSecure;
+    }
+
+    /**
+     * Start the socket to listen to any incoming connection request.
+     *
+     * @return {@code true} if listening is started successfully.
+     */
+    boolean startListening() {
+        // Create a new listening server socket
+        try {
+            if (mIsSecure) {
+                mServerSocket = mAdapter.listenUsingRfcommWithServiceRecord(SERVICE_NAME_SECURE,
+                        mServiceUuid);
+            } else {
+                mServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
+                        SERVICE_NAME_INSECURE, mServiceUuid);
+            }
+        } catch (IOException e) {
+            loge(TAG, "Socket listen() failed", e);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void run() {
+        logd(TAG, "BEGIN AcceptTask: " + this);
+        BluetoothSocket socket = null;
+
+        // Listen to the server socket if we're not connected
+        while (true) {
+            try {
+                socket = mServerSocket.accept();
+            } catch (IOException e) {
+                loge(TAG, "accept() failed", e);
+                break;
+            }
+            if (socket != null) {
+                break;
+            }
+        }
+
+        mListener.onTaskCompleted(socket, mIsSecure);
+    }
+
+    void cancel() {
+        logd(TAG, "CANCEL AcceptTask: " + this);
+        try {
+            if (mServerSocket != null) {
+                mServerSocket.close();
+            }
+        } catch (IOException e) {
+            loge(TAG, "close() of server failed", e);
+        }
+    }
+
+    interface OnTaskCompletedListener {
+        /**
+         * Will be called when the accept task is completed.
+         *
+         * @param socket   will be {@code null} if the task failed.
+         * @param isSecure is {@code true} when it is listening to a secure RFCOMM channel.
+         */
+        void onTaskCompleted(@Nullable BluetoothSocket socket, boolean isSecure);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/CarSppManager.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/CarSppManager.java
new file mode 100644
index 0000000..e9f0cc1
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/CarSppManager.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.android.car.connecteddevice.ConnectedDeviceManager.DEVICE_ERROR_UNEXPECTED_DISCONNECTION;
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.connecteddevice.AssociationCallback;
+import com.android.car.connecteddevice.connection.AssociationSecureChannel;
+import com.android.car.connecteddevice.connection.CarBluetoothManager;
+import com.android.car.connecteddevice.connection.DeviceMessageStream;
+import com.android.car.connecteddevice.connection.ReconnectSecureChannel;
+import com.android.car.connecteddevice.connection.SecureChannel;
+import com.android.car.connecteddevice.oob.OobChannel;
+import com.android.car.connecteddevice.oob.OobConnectionManager;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.EventLog;
+
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+
+/**
+ * Communication manager that allows for targeted connections to a specific device from the car
+ * using {@link SppManager} .
+ */
+public class CarSppManager extends CarBluetoothManager {
+
+    private static final String TAG = "CarSppManager";
+
+    private final SppManager mSppManager;
+
+    private final UUID mAssociationServiceUuid;
+
+    private final int mPacketMaxBytes;
+
+    private String mReconnectDeviceId;
+
+    private OobConnectionManager mOobConnectionManager;
+
+    private Executor mCallbackExecutor;
+
+    private AssociationCallback mAssociationCallback;
+
+    /**
+     * Initialize a new instance of manager.
+     *
+     * @param sppManager             {@link SppManager} for establishing connection.
+     * @param connectedDeviceStorage Shared {@link ConnectedDeviceStorage} for companion features.
+     * @param packetMaxBytes         Maximum size in bytes to write in one packet.
+     */
+    public CarSppManager(@NonNull SppManager sppManager,
+            @NonNull ConnectedDeviceStorage connectedDeviceStorage,
+            @NonNull UUID associationServiceUuid,
+            int packetMaxBytes) {
+        super(connectedDeviceStorage);
+        mSppManager = sppManager;
+        mCallbackExecutor = Executors.newSingleThreadExecutor();
+        mAssociationServiceUuid = associationServiceUuid;
+        mPacketMaxBytes = packetMaxBytes;
+    }
+
+    @Override
+    public void stop() {
+        super.stop();
+        reset();
+    }
+
+    @Override
+    public void disconnectDevice(@NonNull String deviceId) {
+        ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+        if (connectedDevice == null || !deviceId.equals(connectedDevice.mDeviceId)) {
+            return;
+        }
+        reset();
+    }
+
+    @Override
+    public AssociationCallback getAssociationCallback() {
+        return mAssociationCallback;
+    }
+
+    @Override
+    public void setAssociationCallback(AssociationCallback callback) {
+        mAssociationCallback = callback;
+    }
+
+    @Override
+    public void initiateConnectionToDevice(@NonNull UUID deviceId) {
+        logd(TAG, "Start spp reconnection listening for device with id: " + deviceId.toString());
+        mReconnectDeviceId = deviceId.toString();
+        mSppManager.unregisterCallback(mAssociationSppCallback);
+        mSppManager.registerCallback(mReconnectSppCallback, mCallbackExecutor);
+        mSppManager.startListening(deviceId);
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        mReconnectDeviceId = null;
+        mAssociationCallback = null;
+        mSppManager.cleanup();
+    }
+
+    /**
+     * Start the association by listening to incoming connect request.
+     */
+    @Override
+    public void startAssociation(@NonNull String nameForAssociation,
+            @NonNull AssociationCallback callback) {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter == null) {
+            loge(TAG, "Bluetooth is unavailable on this device. Unable to start associating.");
+            return;
+        }
+
+        reset();
+        mAssociationCallback = callback;
+        mSppManager.unregisterCallback(mReconnectSppCallback);
+        mSppManager.registerCallback(mAssociationSppCallback, mCallbackExecutor);
+        if (mSppManager.startListening(mAssociationServiceUuid)) {
+            callback.onAssociationStartSuccess(/* deviceName= */ null);
+        } else {
+            callback.onAssociationStartFailure();
+        }
+    }
+
+    /**
+     * Start the association with a new device using out of band verification code exchange
+     */
+    @Override
+    public void startOutOfBandAssociation(@NonNull String nameForAssociation,
+            @NonNull OobChannel oobChannel,
+            @NonNull AssociationCallback callback) {
+
+        logd(TAG, "Starting out of band association.");
+        startAssociation(nameForAssociation, new AssociationCallback() {
+            @Override
+            public void onAssociationStartSuccess(String deviceName) {
+                mAssociationCallback = callback;
+                boolean success = mOobConnectionManager.startOobExchange(oobChannel);
+                if (!success) {
+                    callback.onAssociationStartFailure();
+                    return;
+                }
+                callback.onAssociationStartSuccess(deviceName);
+            }
+
+            @Override
+            public void onAssociationStartFailure() {
+                callback.onAssociationStartFailure();
+            }
+        });
+        mOobConnectionManager = new OobConnectionManager();
+    }
+
+    private void onDeviceConnected(BluetoothDevice device, boolean isReconnect) {
+        onDeviceConnected(device, isReconnect, /* isOob= */ false);
+    }
+
+    private void onDeviceConnected(BluetoothDevice device, boolean isReconnect, boolean isOob) {
+        EventLog.onDeviceConnected();
+        setClientDeviceAddress(device.getAddress());
+        setClientDeviceName(device.getName());
+        DeviceMessageStream secureStream = new SppDeviceMessageStream(mSppManager, device,
+                mPacketMaxBytes);
+        secureStream.setMessageReceivedErrorListener(
+                exception -> {
+                    disconnectWithError("Error occurred in stream: " + exception.getMessage(),
+                            exception);
+                });
+        SecureChannel secureChannel;
+        // TODO(b/157492943): Define an out of band version of ReconnectSecureChannel
+        if (isReconnect) {
+            secureChannel = new ReconnectSecureChannel(secureStream, mStorage, mReconnectDeviceId,
+                    /* expectedChallengeResponse= */ null);
+        } else if (isOob) {
+            // TODO(b/160901821): Integrate Oob with Spp channel
+            loge(TAG, "Oob verification is currently not available for Spp");
+            return;
+        } else {
+            secureChannel = new AssociationSecureChannel(secureStream, mStorage);
+        }
+        secureChannel.registerCallback(mSecureChannelCallback);
+        ConnectedRemoteDevice connectedDevice = new ConnectedRemoteDevice(device, /* gatt= */ null);
+        connectedDevice.mSecureChannel = secureChannel;
+        addConnectedDevice(connectedDevice);
+        if (isReconnect) {
+            setDeviceIdAndNotifyCallbacks(mReconnectDeviceId);
+            mReconnectDeviceId = null;
+        }
+    }
+
+    private final SppManager.ConnectionCallback mReconnectSppCallback =
+            new SppManager.ConnectionCallback() {
+                @Override
+                public void onRemoteDeviceConnected(BluetoothDevice device) {
+                    onDeviceConnected(device, /* isReconnect= */ true);
+                }
+
+                @Override
+                public void onRemoteDeviceDisconnected(BluetoothDevice device) {
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice(device);
+                    // Reset before invoking callbacks to avoid a race condition with reconnect
+                    // logic.
+                    reset();
+                    String deviceId = connectedDevice == null ? mReconnectDeviceId
+                            : connectedDevice.mDeviceId;
+                    if (deviceId != null) {
+                        logd(TAG, "Connected device " + deviceId + " disconnected.");
+                        mCallbacks.invoke(callback -> callback.onDeviceDisconnected(deviceId));
+                    }
+                }
+            };
+
+    private final SppManager.ConnectionCallback mAssociationSppCallback =
+            new SppManager.ConnectionCallback() {
+                @Override
+                public void onRemoteDeviceConnected(BluetoothDevice device) {
+                    onDeviceConnected(device, /* isReconnect= */ false);
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice();
+                    if (connectedDevice == null || connectedDevice.mSecureChannel == null) {
+                        loge(TAG,
+                                "No connected device or secure channel found when try to "
+                                        + "associate.");
+                        return;
+                    }
+                    ((AssociationSecureChannel) connectedDevice.mSecureChannel)
+                            .setShowVerificationCodeListener(
+                                    code -> {
+                                        if (mAssociationCallback == null) {
+                                            loge(TAG, "No valid callback for association.");
+                                            return;
+                                        }
+                                        mAssociationCallback.onVerificationCodeAvailable(code);
+                                    });
+                }
+
+                @Override
+                public void onRemoteDeviceDisconnected(BluetoothDevice device) {
+                    ConnectedRemoteDevice connectedDevice = getConnectedDevice(device);
+                    if (isAssociating()) {
+                        mAssociationCallback.onAssociationError(
+                                DEVICE_ERROR_UNEXPECTED_DISCONNECTION);
+                    }
+                    // Reset before invoking callbacks to avoid a race condition with reconnect
+                    // logic.
+                    reset();
+                    if (connectedDevice != null && connectedDevice.mDeviceId != null) {
+                        mCallbacks.invoke(callback -> callback.onDeviceDisconnected(
+                                connectedDevice.mDeviceId));
+                    }
+                }
+            };
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/ConnectedTask.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/ConnectedTask.java
new file mode 100644
index 0000000..2318e69
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/ConnectedTask.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+import static com.android.car.connecteddevice.util.SafeLog.logi;
+
+import android.bluetooth.BluetoothSocket;
+
+import androidx.annotation.NonNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * This task runs during a connection with a remote device. It handles all incoming and outgoing
+ * data.
+ */
+public class ConnectedTask implements Runnable {
+    private static final String TAG = "ConnectedTask";
+    private final BluetoothSocket mSocket;
+    private final InputStream mInputStream;
+    private final OutputStream mOutputStream;
+    private Callback mCallback;
+
+    ConnectedTask(@NonNull InputStream inputStream, @NonNull OutputStream outputStream,
+            @NonNull BluetoothSocket socket,
+            @NonNull Callback callback) {
+        mInputStream = inputStream;
+        mOutputStream = outputStream;
+        mSocket = socket;
+        mCallback = callback;
+    }
+
+    @Override
+    public void run() {
+        logi(TAG, "Begin ConnectedTask: started to listen to incoming messages.");
+        // Keep listening to the InputStream when task started.
+        while (true) {
+            try {
+                int dataLength = mInputStream.available();
+                if (dataLength == 0) {
+                    continue;
+                }
+                byte[] buffer = new byte[dataLength];
+                // Read from the InputStream
+                mInputStream.read(buffer);
+                mCallback.onMessageReceived(buffer);
+                logd(TAG, "received raw bytes from remote device with length: " + dataLength);
+            } catch (IOException e) {
+                loge(TAG,
+                        "Encountered an exception when listening for incoming message, "
+                                + "disconnected", e);
+                mCallback.onDisconnected();
+                break;
+            }
+        }
+    }
+
+    /**
+     * Write to the connected OutputStream.
+     *
+     * @param buffer The bytes to write
+     */
+    void write(@NonNull byte[] buffer) {
+        try {
+            mOutputStream.write(buffer);
+            logd(TAG, "Sent buffer to remote device with length: " + buffer.length);
+        } catch (IOException e) {
+            loge(TAG, "Exception during write", e);
+        }
+    }
+
+    void cancel() {
+        logd(TAG, "cancel connected task: close connected socket.");
+        try {
+            mSocket.close();
+        } catch (IOException e) {
+            loge(TAG, "close() of connected socket failed", e);
+        }
+    }
+
+    interface Callback {
+        void onMessageReceived(@NonNull byte[] message);
+
+        void onDisconnected();
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppDeviceMessageStream.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppDeviceMessageStream.java
new file mode 100644
index 0000000..d92ddca
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppDeviceMessageStream.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.logw;
+
+import android.bluetooth.BluetoothDevice;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.connecteddevice.connection.DeviceMessageStream;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * Spp message stream to a device.
+ */
+class SppDeviceMessageStream extends DeviceMessageStream {
+
+    private static final String TAG = "SppDeviceMessageStream";
+
+    private final SppManager mSppManager;
+    private final BluetoothDevice mDevice;
+    private final Executor mCallbackExecutor = Executors.newSingleThreadExecutor();
+
+
+    SppDeviceMessageStream(@NonNull SppManager sppManager,
+            @NonNull BluetoothDevice device, int maxWriteSize) {
+        super(maxWriteSize);
+        mSppManager = sppManager;
+        mDevice = device;
+        mSppManager.addOnMessageReceivedListener(this::onMessageReceived, mCallbackExecutor);
+    }
+
+    @Override
+    protected void send(byte[] data) {
+        mSppManager.write(data);
+        sendCompleted();
+    }
+
+    @VisibleForTesting
+    void onMessageReceived(@NonNull BluetoothDevice device, @NonNull byte[] value) {
+        logd(TAG, "Received a message from a device (" + device.getAddress() + ").");
+        if (!mDevice.equals(device)) {
+            logw(TAG, "Received a message from a device (" + device.getAddress() + ") that is not "
+                    + "the expected device (" + mDevice.getAddress() + ") registered to this "
+                    + "stream. Ignoring.");
+            return;
+        }
+
+        onDataReceived(value);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppManager.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppManager.java
new file mode 100644
index 0000000..57a9c89
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppManager.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.connecteddevice.util.ThreadSafeCallbacks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * A generic class that handles all the Spp connection events including:
+ * <ol>
+ *     <li>listen and accept connection request from client.
+ *     <li>send a message through an established connection.
+ *     <li>notify any connection or message events happening during the connection.
+ * </ol>
+ */
+public class SppManager {
+    private static final String TAG = "SppManager";
+    // Service names and UUIDs of SDP(Service Discovery Protocol) record, need to keep it consistent
+    // among client and server.
+    private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
+    private final boolean mIsSecure;
+    private Object mLock = new Object();
+    /**
+     * Task to listen to secure RFCOMM channel.
+     */
+    @VisibleForTesting
+    AcceptTask mAcceptTask;
+    /**
+     * Task to start and maintain a connection.
+     */
+    @VisibleForTesting
+    ConnectedTask mConnectedTask;
+    @VisibleForTesting
+    ExecutorService mConnectionExecutor = Executors.newSingleThreadExecutor();
+    private BluetoothDevice mDevice;
+    @GuardedBy("mLock")
+    private final SppPayloadStream mPayloadStream = new SppPayloadStream();
+    @GuardedBy("mLock")
+    @VisibleForTesting
+    ConnectionState mState;
+    private final ThreadSafeCallbacks<ConnectionCallback> mCallbacks = new ThreadSafeCallbacks<>();
+    private final ThreadSafeCallbacks<OnMessageReceivedListener> mReceivedListeners =
+            new ThreadSafeCallbacks<>();
+
+    public SppManager(@NonNull boolean isSecure) {
+        mPayloadStream.setMessageCompletedListener(this::onMessageCompleted);
+        mIsSecure = isSecure;
+    }
+
+    @VisibleForTesting
+    enum ConnectionState {
+        NONE,
+        LISTEN,
+        CONNECTING,
+        CONNECTED,
+        DISCONNECTED,
+    }
+
+    /**
+     * Registers the given callback to be notified of various events within the {@link SppManager}.
+     *
+     * @param callback The callback to be notified.
+     */
+    void registerCallback(@NonNull ConnectionCallback callback, @NonNull Executor executor) {
+        mCallbacks.add(callback, executor);
+    }
+
+    /**
+     * Unregisters a previously registered callback.
+     *
+     * @param callback The callback to unregister.
+     */
+    void unregisterCallback(@NonNull ConnectionCallback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    /**
+     * Adds a listener to be notified of a write to characteristics.
+     *
+     * @param listener The listener to invoke.
+     */
+    void addOnMessageReceivedListener(@NonNull OnMessageReceivedListener listener,
+            @NonNull Executor executor) {
+        mReceivedListeners.add(listener, executor);
+    }
+
+    /**
+     * Removes the given listener from being notified of characteristic writes.
+     *
+     * @param listener The listener to remove.
+     */
+    void removeOnMessageReceivedListener(@NonNull OnMessageReceivedListener listener) {
+        mReceivedListeners.remove(listener);
+    }
+
+    /**
+     * Start listening to connection request from the client.
+     *
+     * @param serviceUuid The Uuid which the accept task is listening on.
+     * @return {@code true} if listening is started successfully
+     */
+    boolean startListening(@NonNull UUID serviceUuid) {
+        logd(TAG, "Start socket to listening to incoming connection request.");
+        if (mConnectedTask != null) {
+            mConnectedTask.cancel();
+            mConnectedTask = null;
+        }
+
+        // Start the task to listen on a BluetoothServerSocket
+        if (mAcceptTask != null) {
+            mAcceptTask.cancel();
+        }
+        mAcceptTask = new AcceptTask(mAdapter, mIsSecure, serviceUuid, mAcceptTaskListener);
+        if (!mAcceptTask.startListening()) {
+            // TODO(b/159376003): Handle listening error.
+            mAcceptTask.cancel();
+            mAcceptTask = null;
+            return false;
+        }
+        synchronized (mLock) {
+            mState = ConnectionState.LISTEN;
+        }
+        mConnectionExecutor.execute(mAcceptTask);
+        return true;
+    }
+
+    /**
+     * Send data to remote connected bluetooth device.
+     *
+     * @param data the raw data that wait to be sent
+     * @return {@code true} if the message is sent to client successfully.
+     */
+    boolean write(@NonNull byte[] data) {
+        ConnectedTask connectedTask;
+        // Synchronize a copy of the ConnectedTask
+        synchronized (mLock) {
+            if (mState != ConnectionState.CONNECTED) {
+                loge(TAG, "Try to send data when device is disconnected");
+                return false;
+            }
+            connectedTask = mConnectedTask;
+        }
+        byte[] dataReadyToSend = SppPayloadStream.wrapWithArrayLength(data);
+        if (dataReadyToSend == null) {
+            loge(TAG, "Wrapping data with array length failed.");
+            return false;
+        }
+        connectedTask.write(dataReadyToSend);
+        return true;
+    }
+
+    /**
+     * Cleans up the registered listeners.
+     */
+    void cleanup() {
+        // Clears all registered listeners. IHU only supports single connection.
+        mReceivedListeners.clear();
+    }
+
+    /**
+     * Start the ConnectedTask to begin and maintain a RFCOMM channel.
+     *
+     * @param socket   The BluetoothSocket on which the connection was made
+     * @param device   The BluetoothDevice that has been connected
+     * @param isSecure The type of current established channel
+     */
+    @GuardedBy("mLock")
+    private void startConnectionLocked(BluetoothSocket socket, BluetoothDevice device,
+            boolean isSecure) {
+        logd(TAG, "Get accepted bluetooth socket, start listening to incoming messages.");
+
+        // Cancel any task currently running a connection
+        if (mConnectedTask != null) {
+            mConnectedTask.cancel();
+            mConnectedTask = null;
+        }
+
+        // Cancel the accept task because we only want to connect to one device
+        if (mAcceptTask != null) {
+            mAcceptTask.cancel();
+            mAcceptTask = null;
+        }
+        logd(TAG, "Create ConnectedTask: is secure? " + isSecure);
+        InputStream inputStream;
+        OutputStream outputStream;
+        mDevice = device;
+
+        // Get the BluetoothSocket input and output streams
+        try {
+            inputStream = socket.getInputStream();
+            outputStream = socket.getOutputStream();
+        } catch (IOException e) {
+            loge(TAG, "Can not get stream from BluetoothSocket. Connection failed.", e);
+            return;
+        }
+        mState = ConnectionState.CONNECTED;
+        mCallbacks.invoke(callback -> callback.onRemoteDeviceConnected(device));
+
+        // Start the task to manage the connection and perform transmissions
+        mConnectedTask = new ConnectedTask(inputStream, outputStream, socket,
+                mConnectedTaskCallback);
+        mConnectionExecutor.execute(mConnectedTask);
+    }
+
+    private void onMessageCompleted(@NonNull byte[] message) {
+        mReceivedListeners.invoke(listener -> listener.onMessageReceived(mDevice, message));
+    }
+
+    @VisibleForTesting
+    final AcceptTask.OnTaskCompletedListener mAcceptTaskListener =
+            new AcceptTask.OnTaskCompletedListener() {
+                @Override
+                public void onTaskCompleted(BluetoothSocket socket, boolean isSecure) {
+                    if (socket == null) {
+                        loge(TAG, "AcceptTask failed getting the socket");
+                        return;
+                    }
+                    // Connection accepted
+                    synchronized (mLock) {
+                        switch (mState) {
+                            case LISTEN:
+                            case CONNECTING:
+                                startConnectionLocked(socket, socket.getRemoteDevice(), isSecure);
+                                break;
+                            case NONE:
+                                loge(TAG, "AcceptTask is done while in NONE state.");
+                                break;
+                            case CONNECTED:
+                                // Already connected. Terminate new socket.
+                                try {
+                                    socket.close();
+                                } catch (IOException e) {
+                                    loge(TAG, "Could not close unwanted socket", e);
+                                }
+                                break;
+                            case DISCONNECTED:
+                                loge(TAG, "AcceptTask is done while in DISCONNECTED state.");
+                                break;
+                        }
+                    }
+                }
+            };
+
+    @VisibleForTesting
+    final ConnectedTask.Callback mConnectedTaskCallback = new ConnectedTask.Callback() {
+        @Override
+        public void onMessageReceived(byte[] message) {
+            synchronized (mLock) {
+                try {
+                    mPayloadStream.write(message);
+                } catch (IOException e) {
+                    loge(TAG, "Error writes message to spp payload stream: " + e.getMessage());
+                }
+            }
+        }
+
+        @Override
+        public void onDisconnected() {
+            synchronized (mLock) {
+                mState = ConnectionState.DISCONNECTED;
+                mCallbacks.invoke(callback -> callback.onRemoteDeviceDisconnected(mDevice));
+            }
+        }
+    };
+
+    /**
+     * Interface to be notified of various events within the {@link SppManager}.
+     */
+    interface ConnectionCallback {
+
+        /**
+         * Triggered when a bluetooth device connected.
+         *
+         * @param device Remote device that connected on Spp.
+         */
+        void onRemoteDeviceConnected(@NonNull BluetoothDevice device);
+
+        /**
+         * Triggered when a bluetooth device disconnected.
+         *
+         * @param device Remote device that disconnected on Spp.
+         */
+        void onRemoteDeviceDisconnected(@NonNull BluetoothDevice device);
+    }
+
+    /**
+     * An interface for classes that wish to be notified of incoming messages.
+     */
+    interface OnMessageReceivedListener {
+        /**
+         * Triggered when this SppManager receives a write request from a remote device.
+         *
+         * @param device The bluetooth device that sending the message.
+         * @param value  The value that was written.
+         */
+        void onMessageReceived(@NonNull BluetoothDevice device, @NonNull byte[] value);
+    }
+
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppPayloadStream.java b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppPayloadStream.java
new file mode 100644
index 0000000..f05a76f
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/connection/spp/SppPayloadStream.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+/**
+ * For spp stream will be segmented to several parts, a completed message length need to be prepend
+ * to any message sent. This class will take care of the decode and encode of the incoming and
+ * outgoing message.
+ */
+class SppPayloadStream {
+    private static final String TAG = "SppPayloadStream";
+    // An int will take 4 bytes.
+    private static final int LENGTH_BYTES_SIZE = 4;
+    private final ByteArrayOutputStream mPendingStream = new ByteArrayOutputStream();
+    private OnMessageCompletedListener mOnMessageCompletedListener;
+    private int mCurrentMessageTotalLength;
+
+    /**
+     * Writes data to the {@code pendingStream}, inform the {@code messageCompletedListener} when
+     * the message is completed, otherwise store the data into {@code pendingStream} and waiting for
+     * the following parts.
+     *
+     * @param data Received byte array
+     * @throws IOException If there are some errors writing data to {@code pendingStream}
+     */
+    public void write(@NonNull byte[] data) throws IOException {
+        if (mPendingStream.size() == 0) {
+            int currentLength = data.length;
+            // Arbitrarily choose a byte order, need to use the same byte order for server and
+            // client.
+            mCurrentMessageTotalLength = ByteBuffer.wrap(
+                    Arrays.copyOf(data, LENGTH_BYTES_SIZE)).order(
+                    ByteOrder.LITTLE_ENDIAN).getInt();
+            byte[] payload = Arrays.copyOfRange(data, LENGTH_BYTES_SIZE, currentLength);
+            mPendingStream.write(payload);
+        } else {
+            mPendingStream.write(data);
+        }
+
+        if (mPendingStream.size() > mCurrentMessageTotalLength) {
+            // TODO(b/159712861): Handle this situation, e.g. disconnect.
+            loge(TAG, "Received invalid message: " + mPendingStream.toByteArray());
+            return;
+        }
+
+        if (mPendingStream.size() < mCurrentMessageTotalLength) {
+            return;
+        }
+        if (mOnMessageCompletedListener != null) {
+            mOnMessageCompletedListener.onMessageCompleted(mPendingStream.toByteArray());
+        }
+        mPendingStream.reset();
+
+    }
+
+    /**
+     * Register the given listener to be notified when a completed message is received.
+     *
+     * @param listener The listener to be notified
+     */
+    public void setMessageCompletedListener(@Nullable OnMessageCompletedListener listener) {
+        mOnMessageCompletedListener = listener;
+    }
+
+    /**
+     * Wrap the raw byte array with array length.
+     * <p>
+     * Should be called every time when server wants to send a message to client.
+     *
+     * @param rawData Original data
+     * @return The wrapped data
+     * @throws IOException If there are some errors writing data to {@code outputStream}
+     */
+    @Nullable
+    public static byte[] wrapWithArrayLength(@NonNull byte[] rawData) {
+        int length = rawData.length;
+        byte[] lengthBytes = ByteBuffer.allocate(LENGTH_BYTES_SIZE).order(
+                ByteOrder.LITTLE_ENDIAN).putInt(length).array();
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        try {
+            outputStream.write(lengthBytes);
+            outputStream.write(rawData);
+        } catch (IOException e) {
+            loge(TAG, "Error wrap data with array length");
+            return null;
+        }
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * Interface to be notified when a completed message has been received.
+     */
+    interface OnMessageCompletedListener {
+        void onMessageCompleted(@NonNull byte[] message);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/model/OobEligibleDevice.java b/connected-device-lib/src/com/android/car/connecteddevice/model/OobEligibleDevice.java
new file mode 100644
index 0000000..6e910d3
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/model/OobEligibleDevice.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.model;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.util.Objects;
+
+/** Device that may be used for an out-of-band channel. */
+public class OobEligibleDevice {
+
+    @Retention(SOURCE)
+    @IntDef(value = { OOB_TYPE_BLUETOOTH })
+    public @interface OobType {}
+    public static final int OOB_TYPE_BLUETOOTH = 0;
+
+    private final String mDeviceAddress;
+
+    @OobType
+    private final int mOobType;
+
+    public OobEligibleDevice(@NonNull String deviceAddress, @OobType int oobType) {
+        mDeviceAddress = deviceAddress;
+        mOobType = oobType;
+    }
+
+    @NonNull
+    public String getDeviceAddress() {
+        return mDeviceAddress;
+    }
+
+    @OobType
+    public int getOobType() {
+        return mOobType;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof OobEligibleDevice)) {
+            return false;
+        }
+        OobEligibleDevice device = (OobEligibleDevice) obj;
+        return Objects.equals(device.mDeviceAddress, mDeviceAddress)
+                && device.mOobType == mOobType;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mDeviceAddress, mOobType);
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/oob/BluetoothRfcommChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/oob/BluetoothRfcommChannel.java
new file mode 100644
index 0000000..1325f11
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/oob/BluetoothRfcommChannel.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.oob;
+
+import static com.android.car.connecteddevice.util.SafeLog.logd;
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.connecteddevice.model.OobEligibleDevice;
+
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.time.Duration;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Handles out of band data exchange over a secure RFCOMM channel.
+ */
+public class BluetoothRfcommChannel implements OobChannel {
+    private static final String TAG = "BluetoothRfcommChannel";
+    // TODO (b/159500330) Generate random UUID.
+    private static final UUID RFCOMM_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
+    private static final Duration CONNECT_RETRY_WAIT = Duration.ofSeconds(1);
+    private BluetoothSocket mBluetoothSocket;
+    private AtomicBoolean mIsInterrupted = new AtomicBoolean();
+    @VisibleForTesting
+    Callback mCallback;
+
+    @Override
+    public void completeOobDataExchange(@NonNull OobEligibleDevice device,
+            @NonNull Callback callback) {
+        completeOobDataExchange(device, callback, BluetoothAdapter.getDefaultAdapter());
+    }
+
+    @VisibleForTesting
+    void completeOobDataExchange(OobEligibleDevice device, Callback callback,
+            BluetoothAdapter bluetoothAdapter) {
+        mCallback = callback;
+
+        BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(device.getDeviceAddress());
+
+        try {
+            mBluetoothSocket = remoteDevice.createRfcommSocketToServiceRecord(RFCOMM_UUID);
+        } catch (IOException e) {
+            notifyFailure("Rfcomm socket creation with " + remoteDevice.getName() + " failed.", e);
+            return;
+        }
+
+        bluetoothAdapter.cancelDiscovery();
+
+        new Thread() {
+            @Override
+            public void run() {
+                while (!isInterrupted()) {
+                    try {
+                        mBluetoothSocket.connect();
+                        break;
+                    } catch (IOException e) {
+                        logd(TAG, "Unable to connect, trying again in "
+                                + CONNECT_RETRY_WAIT.toMillis() + " ms.");
+                    }
+                    try {
+                        Thread.sleep(CONNECT_RETRY_WAIT.toMillis());
+                    } catch (InterruptedException e) {
+                        loge(TAG, "Thread was interrupted before connection could be made.", e);
+                        Thread.currentThread().interrupt();
+                        return;
+                    }
+                }
+
+                notifySuccess();
+            }
+        }.start();
+    }
+
+    @Override
+    public void sendOobData(byte[] oobData) {
+        if (isInterrupted()) {
+            return;
+        }
+        if (mBluetoothSocket == null) {
+            notifyFailure("Bluetooth socket is null, oob data cannot be sent",
+                    /* exception= */ null);
+            return;
+        }
+        try {
+            OutputStream stream = mBluetoothSocket.getOutputStream();
+            stream.write(oobData);
+            stream.flush();
+            stream.close();
+        } catch (IOException e) {
+            notifyFailure("Sending oob data failed", e);
+        }
+    }
+
+    @Override
+    public void interrupt() {
+        logd(TAG, "Interrupt received.");
+        mIsInterrupted.set(true);
+    }
+
+    @VisibleForTesting
+    boolean isInterrupted() {
+        if (!mIsInterrupted.get()) {
+            return false;
+        }
+
+        if (mBluetoothSocket == null) {
+            return true;
+        }
+
+        try {
+            OutputStream stream = mBluetoothSocket.getOutputStream();
+            stream.flush();
+            stream.close();
+        } catch (IOException e) {
+            loge(TAG, "Unable to clean up bluetooth socket on interrupt.", e);
+        }
+
+        mBluetoothSocket = null;
+        return true;
+    }
+
+    private void notifyFailure(@NonNull String message, @Nullable Exception exception) {
+        loge(TAG, message, exception);
+        if (mCallback != null && !isInterrupted()) {
+            mCallback.onOobExchangeFailure();
+        }
+    }
+
+    private void notifySuccess() {
+        if (mCallback != null && !isInterrupted()) {
+            mCallback.onOobExchangeSuccess();
+        }
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/oob/OobChannel.java b/connected-device-lib/src/com/android/car/connecteddevice/oob/OobChannel.java
new file mode 100644
index 0000000..9be7941
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/oob/OobChannel.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.oob;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.connecteddevice.model.OobEligibleDevice;
+
+/**
+ * An interface for handling out of band data exchange. This interface should be implemented for
+ * every out of band channel that is supported in device association.
+ *
+ * Usage is:
+ * <pre>
+ *     1. Define success and failure responses in {@link Callback}
+ *     2. Call {@link OobChannel#completeOobDataExchange(OobEligibleDevice, Callback)}
+ * </pre>
+ */
+public interface OobChannel {
+    /**
+     * Exchange out of band data with a remote device. This must be done prior to the start of the
+     * association with that device.
+     *
+     * @param device The remote device to exchange out of band data with
+     */
+    void completeOobDataExchange(@NonNull OobEligibleDevice device, @NonNull Callback callback);
+
+    /**
+     * Send raw data over the out of band channel
+     *
+     * @param oobData to be sent
+     */
+    void sendOobData(@NonNull byte[] oobData);
+
+    /** Interrupt the current data exchange and prevent callbacks from being issued. */
+    void interrupt();
+
+    /**
+     * Callbacks for {@link OobChannel#completeOobDataExchange(OobEligibleDevice, Callback)}
+     */
+    interface Callback {
+        /**
+         * Called when {@link OobChannel#completeOobDataExchange(OobEligibleDevice, Callback)}
+         * finishes successfully.
+         */
+        void onOobExchangeSuccess();
+
+        /**
+         * Called when {@link OobChannel#completeOobDataExchange(OobEligibleDevice, Callback)}
+         * fails.
+         */
+        void onOobExchangeFailure();
+    }
+}
diff --git a/connected-device-lib/src/com/android/car/connecteddevice/oob/OobConnectionManager.java b/connected-device-lib/src/com/android/car/connecteddevice/oob/OobConnectionManager.java
new file mode 100644
index 0000000..f1564dd
--- /dev/null
+++ b/connected-device-lib/src/com/android/car/connecteddevice/oob/OobConnectionManager.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.oob;
+
+import static com.android.car.connecteddevice.util.SafeLog.loge;
+
+import android.security.keystore.KeyProperties;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.google.common.primitives.Bytes;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * This is a class that manages a token--{@link OobConnectionManager#mEncryptionKey}-- passed via
+ * an out of band {@link OobChannel} that is distinct from the channel that is currently being
+ * secured.
+ * <p>Intended usage:
+*  <pre>{@code
+ *  OobConnectionManager oobConncetionManager = new OobConnectionManager();
+ *  oobConnectionManager.startOobExchange(channel);
+ *  }</pre>
+ * <pre>{@code When a message is received:
+ *   verificationCode = OobConnectionManager#decryptVerificationCode(byte[])
+ *   check that verification code is valid
+ *   if it is:
+ *     encryptedMessage =  OobConnectionManager#encryptVerificationCode(byte[])
+ *     send encryptedMessage
+ *     verify handshake
+ *   otherwise:
+ *     fail handshake
+ * }</pre>
+ *
+ * <pre>{@code
+ * when oobData is received via the out of band channel:
+ *   OobConnectionManager#setOobData(byte[])
+ *
+ * encryptedMessage = OobConnectionManager#encryptVerificationCode(byte[])
+ * sendMessage
+ * when a message is received:
+ *   verificationCode = OobConnectionManager#decryptVerificationCode(byte[])
+ *   check that verification code is valid
+ *   if it is:
+ *     verify handshake
+ *   otherwise:
+ *     fail handshake
+ * }</pre>
+ */
+public class OobConnectionManager {
+    private static final String TAG = "OobConnectionManager";
+    private static final String ALGORITHM = "AES/GCM/NoPadding";
+    // The nonce length is chosen to be consistent with the standard specification:
+    // Section 8.2 of https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
+    @VisibleForTesting
+    static final int NONCE_LENGTH_BYTES = 12;
+
+    private final Cipher mCipher;
+    @VisibleForTesting
+    byte[] mEncryptionIv = new byte[NONCE_LENGTH_BYTES];
+    @VisibleForTesting
+    byte[] mDecryptionIv = new byte[NONCE_LENGTH_BYTES];
+    @VisibleForTesting
+    SecretKey mEncryptionKey;
+
+    public OobConnectionManager() {
+        try {
+            mCipher = Cipher.getInstance(ALGORITHM);
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+            loge(TAG, "Unable to create cipher with " + ALGORITHM + ".", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Encrypts {@param verificationCode} using {@link OobConnectionManager#mEncryptionKey}
+     */
+    @NonNull
+    public byte[] encryptVerificationCode(@NonNull byte[] verificationCode)
+            throws InvalidAlgorithmParameterException,
+            BadPaddingException, InvalidKeyException, IllegalBlockSizeException {
+        mCipher.init(Cipher.ENCRYPT_MODE, mEncryptionKey, new IvParameterSpec(mEncryptionIv));
+        return mCipher.doFinal(verificationCode);
+    }
+
+    /**
+     * Decrypts {@param encryptedMessage} using {@link OobConnectionManager#mEncryptionKey}
+     */
+    @NonNull
+    public byte[] decryptVerificationCode(@NonNull byte[] encryptedMessage)
+            throws InvalidAlgorithmParameterException, BadPaddingException, InvalidKeyException,
+            IllegalBlockSizeException {
+        mCipher.init(Cipher.DECRYPT_MODE, mEncryptionKey, new IvParameterSpec(mDecryptionIv));
+        return mCipher.doFinal(encryptedMessage);
+    }
+
+    void setOobData(@NonNull byte[] oobData) {
+        mEncryptionIv = Arrays.copyOfRange(oobData, 0, NONCE_LENGTH_BYTES);
+        mDecryptionIv = Arrays.copyOfRange(oobData, NONCE_LENGTH_BYTES,
+                NONCE_LENGTH_BYTES * 2);
+        mEncryptionKey = new SecretKeySpec(
+                Arrays.copyOfRange(oobData, NONCE_LENGTH_BYTES * 2, oobData.length),
+                KeyProperties.KEY_ALGORITHM_AES);
+    }
+
+    /**
+     * Start the out of band exchange with a given {@link OobChannel}.
+     *
+     * @param oobChannel Channel to be used for exchange.
+     * @return {@code true} if exchange started successfully. {@code false} if an error occurred.
+     */
+    public boolean startOobExchange(@NonNull OobChannel oobChannel) {
+        KeyGenerator keyGenerator = null;
+        try {
+            keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
+        } catch (NoSuchAlgorithmException e) {
+            loge(TAG, "Unable to get AES key generator.", e);
+            return false;
+        }
+        mEncryptionKey = keyGenerator.generateKey();
+
+        SecureRandom secureRandom = new SecureRandom();
+        secureRandom.nextBytes(mEncryptionIv);
+        secureRandom.nextBytes(mDecryptionIv);
+
+        oobChannel.sendOobData(
+                Bytes.concat(mDecryptionIv, mEncryptionIv, mEncryptionKey.getEncoded()));
+        return true;
+    }
+}
diff --git a/connected-device-lib/tests/unit/Android.bp b/connected-device-lib/tests/unit/Android.bp
index f39e737..92810a4 100644
--- a/connected-device-lib/tests/unit/Android.bp
+++ b/connected-device-lib/tests/unit/Android.bp
@@ -45,7 +45,8 @@
         "libstaticjvmtiagent",
     ],
 
-    min_sdk_version: "29",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
 
     certificate: "platform",
 
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java
index 92a62b6..fe0386c 100644
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ConnectedDeviceManagerTest.java
@@ -38,10 +38,8 @@
 import com.android.car.connecteddevice.ConnectedDeviceManager.DeviceAssociationCallback;
 import com.android.car.connecteddevice.ConnectedDeviceManager.DeviceCallback;
 import com.android.car.connecteddevice.ConnectedDeviceManager.MessageDeliveryDelegate;
-import com.android.car.connecteddevice.ble.CarBleCentralManager;
-import com.android.car.connecteddevice.ble.CarBleManager;
-import com.android.car.connecteddevice.ble.CarBlePeripheralManager;
-import com.android.car.connecteddevice.ble.DeviceMessage;
+import com.android.car.connecteddevice.connection.CarBluetoothManager;
+import com.android.car.connecteddevice.connection.DeviceMessage;
 import com.android.car.connecteddevice.model.AssociatedDevice;
 import com.android.car.connecteddevice.model.ConnectedDevice;
 import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
@@ -86,10 +84,7 @@
     private ConnectedDeviceStorage mMockStorage;
 
     @Mock
-    private CarBlePeripheralManager mMockPeripheralManager;
-
-    @Mock
-    private CarBleCentralManager mMockCentralManager;
+    private CarBluetoothManager mMockCarBluetoothManager;
 
     private ConnectedDeviceManager mConnectedDeviceManager;
 
@@ -105,8 +100,8 @@
                 .startMocking();
         ArgumentCaptor<AssociatedDeviceCallback> callbackCaptor = ArgumentCaptor
                 .forClass(AssociatedDeviceCallback.class);
-        mConnectedDeviceManager = new ConnectedDeviceManager(mMockStorage, mMockCentralManager,
-            mMockPeripheralManager);
+        mConnectedDeviceManager = new ConnectedDeviceManager(mMockCarBluetoothManager,
+                mMockStorage);
         verify(mMockStorage).setAssociatedDeviceCallback(callbackCaptor.capture());
         when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(mUserDevices);
         when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(mUserDeviceIds);
@@ -128,7 +123,7 @@
 
     @Test
     public void getActiveUserConnectedDevices_includesNewlyConnectedDevice() {
-        String deviceId = connectNewDevice(mMockCentralManager);
+        String deviceId = connectNewDevice();
         List<ConnectedDevice> activeUserDevices =
                 mConnectedDeviceManager.getActiveUserConnectedDevices();
         ConnectedDevice expectedDevice = new ConnectedDevice(deviceId, /* deviceName= */ null,
@@ -142,14 +137,14 @@
         String otherUserDeviceId = UUID.randomUUID().toString();
         when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(
                 Collections.singletonList(otherUserDeviceId));
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockCentralManager);
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
         assertThat(mConnectedDeviceManager.getActiveUserConnectedDevices()).isEmpty();
     }
 
     @Test
     public void getActiveUserConnectedDevices_reflectsSecureChannelEstablished() {
-        String deviceId = connectNewDevice(mMockCentralManager);
-        mConnectedDeviceManager.onSecureChannelEstablished(deviceId, mMockCentralManager);
+        String deviceId = connectNewDevice();
+        mConnectedDeviceManager.onSecureChannelEstablished(deviceId);
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         assertThat(connectedDevice.hasSecureChannel()).isTrue();
@@ -157,21 +152,14 @@
 
     @Test
     public void getActiveUserConnectedDevices_excludesDisconnectedDevice() {
-        String deviceId = connectNewDevice(mMockCentralManager);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockCentralManager);
+        String deviceId = connectNewDevice();
+        mConnectedDeviceManager.removeConnectedDevice(deviceId);
         assertThat(mConnectedDeviceManager.getActiveUserConnectedDevices()).isEmpty();
     }
 
-    @Test
-    public void getActiveUserConnectedDevices_unaffectedByOtherManagerDisconnect() {
-        String deviceId = connectNewDevice(mMockCentralManager);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockPeripheralManager);
-        assertThat(mConnectedDeviceManager.getActiveUserConnectedDevices()).hasSize(1);
-    }
-
     @Test(expected = IllegalStateException.class)
     public void sendMessageSecurely_throwsIllegalStateExceptionIfNoSecureChannel() {
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice device = mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         UUID recipientId = UUID.randomUUID();
         byte[] message = ByteUtils.randomBytes(10);
@@ -180,37 +168,38 @@
 
     @Test
     public void sendMessageSecurely_sendsEncryptedMessage() {
-        String deviceId = connectNewDevice(mMockCentralManager);
-        mConnectedDeviceManager.onSecureChannelEstablished(deviceId, mMockCentralManager);
+        String deviceId = connectNewDevice();
+        mConnectedDeviceManager.onSecureChannelEstablished(deviceId);
         ConnectedDevice device = mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         UUID recipientId = UUID.randomUUID();
         byte[] message = ByteUtils.randomBytes(10);
         mConnectedDeviceManager.sendMessageSecurely(device, recipientId, message);
         ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
-        verify(mMockCentralManager).sendMessage(eq(deviceId), messageCaptor.capture());
+        verify(mMockCarBluetoothManager).sendMessage(eq(deviceId), messageCaptor.capture());
         assertThat(messageCaptor.getValue().isMessageEncrypted()).isTrue();
     }
 
     @Test
     public void sendMessageSecurely_doesNotSendIfDeviceDisconnected() {
-        String deviceId = connectNewDevice(mMockCentralManager);
+        String deviceId = connectNewDevice();
         ConnectedDevice device = mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockCentralManager);
+        mConnectedDeviceManager.removeConnectedDevice(deviceId);
         UUID recipientId = UUID.randomUUID();
         byte[] message = ByteUtils.randomBytes(10);
         mConnectedDeviceManager.sendMessageSecurely(device, recipientId, message);
-        verify(mMockCentralManager, times(0)).sendMessage(eq(deviceId), any(DeviceMessage.class));
+        verify(mMockCarBluetoothManager, times(0)).sendMessage(eq(deviceId),
+                any(DeviceMessage.class));
     }
 
     @Test
     public void sendMessageUnsecurely_sendsMessageWithoutEncryption() {
-        String deviceId = connectNewDevice(mMockCentralManager);
+        String deviceId = connectNewDevice();
         ConnectedDevice device = mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         UUID recipientId = UUID.randomUUID();
         byte[] message = ByteUtils.randomBytes(10);
         mConnectedDeviceManager.sendMessageUnsecurely(device, recipientId, message);
         ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
-        verify(mMockCentralManager).sendMessage(eq(deviceId), messageCaptor.capture());
+        verify(mMockCarBluetoothManager).sendMessage(eq(deviceId), messageCaptor.capture());
         assertThat(messageCaptor.getValue().isMessageEncrypted()).isFalse();
     }
 
@@ -221,7 +210,7 @@
         ConnectionCallback connectionCallback = createConnectionCallback(semaphore);
         mConnectedDeviceManager.registerActiveUserConnectionCallback(connectionCallback,
                 mCallbackExecutor);
-        String deviceId = connectNewDevice(mMockCentralManager);
+        String deviceId = connectNewDevice();
         assertThat(tryAcquire(semaphore)).isTrue();
         ArgumentCaptor<ConnectedDevice> deviceCaptor =
                 ArgumentCaptor.forClass(ConnectedDevice.class);
@@ -242,7 +231,7 @@
         String otherUserDeviceId = UUID.randomUUID().toString();
         when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(
                 Collections.singletonList(otherUserDeviceId));
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockCentralManager);
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
         assertThat(tryAcquire(semaphore)).isFalse();
     }
 
@@ -250,11 +239,11 @@
     public void connectionCallback_onDeviceConnectedNotInvokedForDifferentBleManager()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        String deviceId = connectNewDevice(mMockPeripheralManager);
+        String deviceId = connectNewDevice();
         ConnectionCallback connectionCallback = createConnectionCallback(semaphore);
         mConnectedDeviceManager.registerActiveUserConnectionCallback(connectionCallback,
                 mCallbackExecutor);
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockCentralManager);
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
         assertThat(tryAcquire(semaphore)).isFalse();
     }
 
@@ -262,11 +251,11 @@
     public void connectionCallback_onDeviceDisconnectedInvokedForActiveUserDevice()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        String deviceId = connectNewDevice(mMockCentralManager);
+        String deviceId = connectNewDevice();
         ConnectionCallback connectionCallback = createConnectionCallback(semaphore);
         mConnectedDeviceManager.registerActiveUserConnectionCallback(connectionCallback,
                 mCallbackExecutor);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockCentralManager);
+        mConnectedDeviceManager.removeConnectedDevice(deviceId);
         assertThat(tryAcquire(semaphore)).isTrue();
         ArgumentCaptor<ConnectedDevice> deviceCaptor =
                 ArgumentCaptor.forClass(ConnectedDevice.class);
@@ -279,11 +268,11 @@
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
         String deviceId = UUID.randomUUID().toString();
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockCentralManager);
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
         ConnectionCallback connectionCallback = createConnectionCallback(semaphore);
         mConnectedDeviceManager.registerActiveUserConnectionCallback(connectionCallback,
                 mCallbackExecutor);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockCentralManager);
+        mConnectedDeviceManager.removeConnectedDevice(deviceId);
         assertThat(tryAcquire(semaphore)).isFalse();
     }
 
@@ -295,14 +284,14 @@
         mConnectedDeviceManager.registerActiveUserConnectionCallback(connectionCallback,
                 mCallbackExecutor);
         mConnectedDeviceManager.unregisterConnectionCallback(connectionCallback);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         assertThat(tryAcquire(semaphore)).isFalse();
     }
 
     @Test
     public void registerDeviceCallback_blacklistsDuplicateRecipientId()
             throws InterruptedException {
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         Semaphore firstSemaphore = new Semaphore(0);
@@ -343,14 +332,13 @@
     @Test
     public void deviceCallback_onSecureChannelEstablishedInvoked() throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         DeviceCallback deviceCallback = createDeviceCallback(semaphore);
         mConnectedDeviceManager.registerDeviceCallback(connectedDevice, mRecipientId,
                 deviceCallback, mCallbackExecutor);
-        mConnectedDeviceManager.onSecureChannelEstablished(connectedDevice.getDeviceId(),
-                mMockCentralManager);
+        mConnectedDeviceManager.onSecureChannelEstablished(connectedDevice.getDeviceId());
         connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         assertThat(tryAcquire(semaphore)).isTrue();
@@ -358,27 +346,10 @@
     }
 
     @Test
-    public void deviceCallback_onSecureChannelEstablishedNotInvokedWithSecondBleManager()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
-        ConnectedDevice connectedDevice =
-                mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
-        mConnectedDeviceManager.onSecureChannelEstablished(connectedDevice.getDeviceId(),
-                mMockCentralManager);
-        DeviceCallback deviceCallback = createDeviceCallback(semaphore);
-        mConnectedDeviceManager.registerDeviceCallback(connectedDevice, mRecipientId,
-                deviceCallback, mCallbackExecutor);
-        mConnectedDeviceManager.onSecureChannelEstablished(connectedDevice.getDeviceId(),
-                mMockPeripheralManager);
-        assertThat(tryAcquire(semaphore)).isFalse();
-    }
-
-    @Test
     public void deviceCallback_onMessageReceivedInvokedForSameRecipientId()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         DeviceCallback deviceCallback = createDeviceCallback(semaphore);
@@ -395,7 +366,7 @@
     public void deviceCallback_onMessageReceivedNotInvokedForDifferentRecipientId()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         DeviceCallback deviceCallback = createDeviceCallback(semaphore);
@@ -410,7 +381,7 @@
     @Test
     public void deviceCallback_onDeviceErrorInvokedOnChannelError() throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         DeviceCallback deviceCallback = createDeviceCallback(semaphore);
@@ -425,7 +396,7 @@
     public void unregisterDeviceCallback_removesCallbackAndNotInvoked()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         DeviceCallback deviceCallback = createDeviceCallback(semaphore);
@@ -433,8 +404,7 @@
                 deviceCallback, mCallbackExecutor);
         mConnectedDeviceManager.unregisterDeviceCallback(connectedDevice, mRecipientId,
                 deviceCallback);
-        mConnectedDeviceManager.onSecureChannelEstablished(connectedDevice.getDeviceId(),
-                mMockPeripheralManager);
+        mConnectedDeviceManager.onSecureChannelEstablished(connectedDevice.getDeviceId());
         assertThat(tryAcquire(semaphore)).isFalse();
     }
 
@@ -442,7 +412,7 @@
     public void registerDeviceCallback_sendsMissedMessageAfterRegistration()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         byte[] payload = ByteUtils.randomBytes(10);
@@ -459,7 +429,7 @@
     public void registerDeviceCallback_sendsMultipleMissedMessagesAfterRegistration()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         byte[] payload1 = ByteUtils.randomBytes(10);
@@ -480,7 +450,7 @@
     public void registerDeviceCallback_doesNotSendMissedMessageForDifferentRecipient()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         byte[] payload = ByteUtils.randomBytes(10);
@@ -496,8 +466,8 @@
     public void registerDeviceCallback_doesNotSendMissedMessageForDifferentDevice()
             throws InterruptedException {
         Semaphore semaphore = new Semaphore(0);
-        connectNewDevice(mMockCentralManager);
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
+        connectNewDevice();
         List<ConnectedDevice> connectedDevices =
                 mConnectedDeviceManager.getActiveUserConnectedDevices();
         ConnectedDevice connectedDevice = connectedDevices.get(0);
@@ -515,7 +485,7 @@
     public void onAssociationCompleted_disconnectsOriginalDeviceAndReconnectsAsActiveUser()
             throws InterruptedException {
         String deviceId = UUID.randomUUID().toString();
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockPeripheralManager);
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
         Semaphore semaphore = new Semaphore(0);
         ConnectionCallback connectionCallback = createConnectionCallback(semaphore);
         mConnectedDeviceManager.registerActiveUserConnectionCallback(connectionCallback,
@@ -578,10 +548,10 @@
                 TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(
                 Collections.singletonList(device));
-        clearInvocations(mMockPeripheralManager);
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockPeripheralManager);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockPeripheralManager);
-        verify(mMockPeripheralManager, timeout(1000))
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
+        clearInvocations(mMockCarBluetoothManager);
+        mConnectedDeviceManager.removeConnectedDevice(deviceId);
+        verify(mMockCarBluetoothManager, timeout(1000))
                 .connectToDevice(eq(UUID.fromString(deviceId)));
     }
 
@@ -595,15 +565,15 @@
                 TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(
                 Collections.singletonList(userDevice));
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockPeripheralManager);
-        clearInvocations(mMockPeripheralManager);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockPeripheralManager);
-        verify(mMockPeripheralManager, timeout(1000))
-                .connectToDevice(eq(UUID.fromString(userDeviceId)));
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
+        clearInvocations(mMockCarBluetoothManager);
+        mConnectedDeviceManager.removeConnectedDevice(deviceId);
+        verify(mMockCarBluetoothManager, timeout(1000)).connectToDevice(
+                eq(UUID.fromString(userDeviceId)));
     }
 
     @Test
-    public void removeConnectedDevice__doesNotAdvertiseForNonActiveUserDeviceNotLastDevice() {
+    public void removeConnectedDevice_doesNotAdvertiseForNonActiveUserDeviceNotLastDevice() {
         String deviceId = UUID.randomUUID().toString();
         String userDeviceId = UUID.randomUUID().toString();
         when(mMockStorage.getActiveUserAssociatedDeviceIds()).thenReturn(
@@ -612,11 +582,11 @@
                 TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         when(mMockStorage.getActiveUserAssociatedDevices()).thenReturn(
                 Collections.singletonList(userDevice));
-        clearInvocations(mMockPeripheralManager);
-        mConnectedDeviceManager.addConnectedDevice(deviceId, mMockPeripheralManager);
-        mConnectedDeviceManager.addConnectedDevice(userDeviceId, mMockCentralManager);
-        mConnectedDeviceManager.removeConnectedDevice(deviceId, mMockPeripheralManager);
-        verify(mMockPeripheralManager, timeout(1000).times(0))
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
+        mConnectedDeviceManager.addConnectedDevice(userDeviceId);
+        clearInvocations(mMockCarBluetoothManager);
+        mConnectedDeviceManager.removeConnectedDevice(deviceId);
+        verify(mMockCarBluetoothManager, timeout(1000).times(0))
                 .connectToDevice(any());
     }
 
@@ -629,9 +599,9 @@
 
     @Test
     public void removeActiveUserAssociatedDevice_disconnectsIfConnected() {
-        String deviceId = connectNewDevice(mMockPeripheralManager);
+        String deviceId = connectNewDevice();
         mConnectedDeviceManager.removeActiveUserAssociatedDevice(deviceId);
-        verify(mMockPeripheralManager).disconnectDevice(deviceId);
+        verify(mMockCarBluetoothManager).disconnectDevice(deviceId);
     }
 
     @Test
@@ -650,14 +620,14 @@
 
     @Test
     public void disableAssociatedDeviceConnection_disconnectsIfConnected() {
-        String deviceId = connectNewDevice(mMockPeripheralManager);
+        String deviceId = connectNewDevice();
         mConnectedDeviceManager.disableAssociatedDeviceConnection(deviceId);
-        verify(mMockPeripheralManager).disconnectDevice(deviceId);
+        verify(mMockCarBluetoothManager).disconnectDevice(deviceId);
     }
 
     @Test
     public void onMessageReceived_deliversMessageIfDelegateIsNull() throws InterruptedException {
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         Semaphore semaphore = new Semaphore(0);
@@ -672,7 +642,7 @@
 
     @Test
     public void onMessageReceived_deliversMessageIfDelegateAccepts() throws InterruptedException {
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         Semaphore semaphore = new Semaphore(0);
@@ -689,7 +659,7 @@
     @Test
     public void onMessageReceived_doesNotDeliverMessageIfDelegateRejects()
             throws InterruptedException {
-        connectNewDevice(mMockCentralManager);
+        connectNewDevice();
         ConnectedDevice connectedDevice =
                 mConnectedDeviceManager.getActiveUserConnectedDevices().get(0);
         Semaphore semaphore = new Semaphore(0);
@@ -704,13 +674,13 @@
     }
 
     @NonNull
-    private String connectNewDevice(@NonNull CarBleManager carBleManager) {
+    private String connectNewDevice() {
         String deviceId = UUID.randomUUID().toString();
         AssociatedDevice device = new AssociatedDevice(deviceId, TEST_DEVICE_ADDRESS,
                 TEST_DEVICE_NAME, /* isConnectionEnabled= */ true);
         mUserDeviceIds.add(deviceId);
         mUserDevices.add(device);
-        mConnectedDeviceManager.addConnectedDevice(deviceId, carBleManager);
+        mConnectedDeviceManager.addConnectedDevice(deviceId);
         return deviceId;
     }
 
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/AssociationSecureChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/AssociationSecureChannelTest.java
deleted file mode 100644
index 1a4941c..0000000
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/AssociationSecureChannelTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.mockitoSession;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.car.encryptionrunner.DummyEncryptionRunner;
-import android.car.encryptionrunner.EncryptionRunner;
-import android.car.encryptionrunner.EncryptionRunnerFactory;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
-import com.android.car.connecteddevice.ble.BleDeviceMessageStream.MessageReceivedListener;
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-import com.android.car.connecteddevice.util.ByteUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-import java.util.UUID;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-public final class AssociationSecureChannelTest {
-    private static final UUID CLIENT_DEVICE_ID =
-            UUID.fromString("a5645523-3280-410a-90c1-582a6c6f4969");
-    private static final UUID SERVER_DEVICE_ID =
-            UUID.fromString("a29f0c74-2014-4b14-ac02-be6ed15b545a");
-    private static final byte[] CLIENT_SECRET = ByteUtils.randomBytes(32);
-
-    @Mock
-    private BleDeviceMessageStream mStreamMock;
-    @Mock
-    private ConnectedDeviceStorage mStorageMock;
-    @Mock
-    private AssociationSecureChannel.ShowVerificationCodeListener mShowVerificationCodeListenerMock;
-    private MockitoSession mMockitoSession;
-
-    private AssociationSecureChannel mChannel;
-    private MessageReceivedListener mMessageReceivedListener;
-
-    @Before
-    public void setUp() {
-        mMockitoSession = mockitoSession()
-                .initMocks(this)
-                .strictness(Strictness.WARN)
-                .startMocking();
-        when(mStorageMock.getUniqueId()).thenReturn(SERVER_DEVICE_ID);
-    }
-
-    @After
-    public void tearDown() {
-        if (mMockitoSession != null) {
-            mMockitoSession.finishMocking();
-        }
-    }
-
-    @Test
-    public void testEncryptionHandshake_Association() throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
-        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newDummyRunner);
-        ArgumentCaptor<String> deviceIdCaptor = ArgumentCaptor.forClass(String.class);
-        ArgumentCaptor<DeviceMessage> messageCaptor =
-                ArgumentCaptor.forClass(DeviceMessage.class);
-
-        initHandshakeMessage();
-        verify(mStreamMock).writeMessage(messageCaptor.capture(), any());
-        byte[] response = messageCaptor.getValue().getMessage();
-        assertThat(response).isEqualTo(DummyEncryptionRunner.INIT_RESPONSE.getBytes());
-
-        respondToContinueMessage();
-        verify(mShowVerificationCodeListenerMock).showVerificationCode(anyString());
-
-        mChannel.notifyOutOfBandAccepted();
-        sendDeviceId();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onDeviceIdReceived(deviceIdCaptor.capture());
-        verify(mStreamMock, times(2)).writeMessage(messageCaptor.capture(), any());
-        byte[] deviceIdMessage = messageCaptor.getValue().getMessage();
-        assertThat(deviceIdMessage).isEqualTo(ByteUtils.uuidToBytes(SERVER_DEVICE_ID));
-        assertThat(deviceIdCaptor.getValue()).isEqualTo(CLIENT_DEVICE_ID.toString());
-        verify(mStorageMock).saveEncryptionKey(eq(CLIENT_DEVICE_ID.toString()), any());
-        verify(mStorageMock).saveChallengeSecret(CLIENT_DEVICE_ID.toString(), CLIENT_SECRET);
-
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onSecureChannelEstablished();
-    }
-
-    @Test
-    public void testEncryptionHandshake_Association_wrongInitHandshakeMessage()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
-        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newDummyRunner);
-
-        // Wrong init handshake message
-        respondToContinueMessage();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onEstablishSecureChannelFailure(
-                eq(SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
-        );
-    }
-
-    @Test
-    public void testEncryptionHandshake_Association_wrongRespondToContinueMessage()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
-        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newDummyRunner);
-
-        initHandshakeMessage();
-
-        // Wrong respond to continue message
-        initHandshakeMessage();
-        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
-        verify(callbackSpy).onEstablishSecureChannelFailure(
-                eq(SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
-        );
-    }
-
-    private void setupAssociationSecureChannel(ChannelCallback callback,
-            EncryptionRunnerProvider encryptionRunnerProvider) {
-        mChannel = new AssociationSecureChannel(mStreamMock, mStorageMock,
-                encryptionRunnerProvider.getEncryptionRunner());
-        mChannel.registerCallback(callback);
-        mChannel.setShowVerificationCodeListener(mShowVerificationCodeListenerMock);
-        ArgumentCaptor<MessageReceivedListener> listenerCaptor =
-                ArgumentCaptor.forClass(MessageReceivedListener.class);
-        verify(mStreamMock).setMessageReceivedListener(listenerCaptor.capture());
-        mMessageReceivedListener = listenerCaptor.getValue();
-    }
-
-    private void sendDeviceId() {
-        DeviceMessage message = new DeviceMessage(
-                /* recipient= */ null,
-                /* isMessageEncrypted= */ true,
-                ByteUtils.concatByteArrays(ByteUtils.uuidToBytes(CLIENT_DEVICE_ID), CLIENT_SECRET)
-        );
-        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
-    }
-
-    private void initHandshakeMessage() {
-        DeviceMessage message = new DeviceMessage(
-                /* recipient= */ null,
-                /* isMessageEncrypted= */ false,
-                DummyEncryptionRunner.INIT.getBytes()
-        );
-        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
-    }
-
-    private void respondToContinueMessage() {
-        DeviceMessage message = new DeviceMessage(
-                /* recipient= */ null,
-                /* isMessageEncrypted= */ false,
-                DummyEncryptionRunner.CLIENT_RESPONSE.getBytes()
-        );
-        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
-    }
-
-    /**
-     * Add the thread control logic into {@link SecureBleChannel.Callback} only for spy purpose.
-     *
-     * <p>The callback will release the semaphore which hold by one test when this callback
-     * is called, telling the test that it can verify certain behaviors which will only occurred
-     * after the callback is notified. This is needed mainly because of the callback is notified
-     * in a different thread.
-     */
-    private static class ChannelCallback implements SecureBleChannel.Callback {
-        private final Semaphore mSemaphore;
-
-        ChannelCallback(Semaphore semaphore) {
-            mSemaphore = semaphore;
-        }
-
-        @Override
-        public void onSecureChannelEstablished() {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onEstablishSecureChannelFailure(int error) {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onMessageReceived(DeviceMessage deviceMessage) {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onMessageReceivedError(Exception exception) {
-            mSemaphore.release();
-        }
-
-        @Override
-        public void onDeviceIdReceived(String deviceId) {
-            mSemaphore.release();
-        }
-    }
-
-    interface EncryptionRunnerProvider {
-        EncryptionRunner getEncryptionRunner();
-    }
-}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BleDeviceMessageStreamTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BleDeviceMessageStreamTest.java
deleted file mode 100644
index ed6fb44..0000000
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BleDeviceMessageStreamTest.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2020 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.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.BleStreamProtos.BleDeviceMessageProto.BleDeviceMessage;
-import static com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType;
-import static com.android.car.connecteddevice.BleStreamProtos.BlePacketProto.BlePacket;
-import static com.android.car.connecteddevice.ble.BleDeviceMessageStream.MessageReceivedErrorListener;
-import static com.android.car.connecteddevice.ble.BleDeviceMessageStream.MessageReceivedListener;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mockitoSession;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.annotation.NonNull;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.car.connecteddevice.util.ByteUtils;
-import com.android.car.protobuf.ByteString;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-public class BleDeviceMessageStreamTest {
-
-    private static final int PACKET_SIZE = 500;
-
-    private BleDeviceMessageStream mStream;
-
-    @Mock
-    private BlePeripheralManager mMockBlePeripheralManager;
-
-    @Mock
-    private BluetoothDevice mMockBluetoothDevice;
-
-    @Mock
-    private BluetoothGattCharacteristic mMockWriteCharacteristic;
-
-    @Mock
-    private BluetoothGattCharacteristic mMockReadCharacteristic;
-
-    private MockitoSession mMockingSession;
-
-    @Before
-    public void setup() {
-        mMockingSession = mockitoSession()
-                .initMocks(this)
-                .strictness(Strictness.LENIENT)
-                .startMocking();
-
-        mStream = new BleDeviceMessageStream(mMockBlePeripheralManager, mMockBluetoothDevice,
-                mMockWriteCharacteristic, mMockReadCharacteristic, PACKET_SIZE);
-    }
-
-    @After
-    public void cleanup() {
-        if (mMockingSession != null) {
-            mMockingSession.finishMocking();
-        }
-    }
-
-    @Test
-    public void processPacket_notifiesWithEntireMessageForSinglePacketMessage()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
-        mStream.setMessageReceivedListener(listener);
-        byte[] data = ByteUtils.randomBytes(5);
-        processMessage(data);
-        assertThat(tryAcquire(semaphore)).isTrue();
-        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
-        verify(listener).onMessageReceived(messageCaptor.capture(), any());
-    }
-
-    @Test
-    public void processPacket_notifiesWithEntireMessageForMultiPacketMessage()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
-        mStream.setMessageReceivedListener(listener);
-        byte[] data = ByteUtils.randomBytes(750);
-        processMessage(data);
-        assertThat(tryAcquire(semaphore)).isTrue();
-        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
-        verify(listener).onMessageReceived(messageCaptor.capture(), any());
-        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
-    }
-
-    @Test
-    public void processPacket_receivingMultipleMessagesInParallelParsesSuccessfully()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
-        mStream.setMessageReceivedListener(listener);
-        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5));
-        List<BlePacket> packets1 = createPackets(data);
-        List<BlePacket> packets2 = createPackets(data);
-
-        for (int i = 0; i < packets1.size(); i++) {
-            mStream.processPacket(packets1.get(i));
-            if (i == packets1.size() - 1) {
-                break;
-            }
-            mStream.processPacket(packets2.get(i));
-        }
-        assertThat(tryAcquire(semaphore)).isTrue();
-        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
-        verify(listener).onMessageReceived(messageCaptor.capture(), any());
-        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
-
-        semaphore = new Semaphore(0);
-        listener = createMessageReceivedListener(semaphore);
-        mStream.setMessageReceivedListener(listener);
-        mStream.processPacket(packets2.get(packets2.size() - 1));
-        verify(listener).onMessageReceived(messageCaptor.capture(), any());
-        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
-    }
-
-    @Test
-    public void processPacket_doesNotNotifyOfNewMessageIfNotAllPacketsReceived()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        mStream.setMessageReceivedListener(createMessageReceivedListener(semaphore));
-        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
-        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5));
-        List<BlePacket> packets = createPackets(data);
-        for (int i = 0; i < packets.size() - 1; i++) {
-            mStream.processPacket(packets.get(i));
-        }
-        assertThat(tryAcquire(semaphore)).isFalse();
-    }
-
-    @Test
-    public void processPacket_ignoresDuplicatePacket() {
-        Semaphore semaphore = new Semaphore(0);
-        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 2.5));
-        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
-        mStream.setMessageReceivedListener(listener);
-        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
-        List<BlePacket> packets = createPackets(data);
-        for (int i = 0; i < packets.size(); i++) {
-            mStream.processPacket(packets.get(i));
-            mStream.processPacket(packets.get(i)); // Process each packet twice.
-        }
-        verify(listener).onMessageReceived(messageCaptor.capture(), any());
-        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
-    }
-
-    @Test
-    public void processPacket_packetBeforeExpectedRangeNotifiesMessageError()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
-        List<BlePacket> packets = createPackets(ByteUtils.randomBytes((int) (PACKET_SIZE * 2.5)));
-        mStream.processPacket(packets.get(0));
-        mStream.processPacket(packets.get(1));
-        mStream.processPacket(packets.get(0));
-        assertThat(tryAcquire(semaphore)).isTrue();
-    }
-
-    @Test
-    public void processPacket_packetAfterExpectedNotifiesMessageError()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
-        List<BlePacket> packets = createPackets(ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5)));
-        mStream.processPacket(packets.get(1));
-        assertThat(tryAcquire(semaphore)).isTrue();
-    }
-
-    @NonNull
-    private List<BlePacket> createPackets(byte[] data) {
-        try {
-            BleDeviceMessage message = BleDeviceMessage.newBuilder()
-                    .setPayload(ByteString.copyFrom(data))
-                    .setOperation(OperationType.CLIENT_MESSAGE)
-                    .build();
-            return BlePacketFactory.makeBlePackets(message.toByteArray(),
-                    ThreadLocalRandom.current().nextInt(), PACKET_SIZE);
-        } catch (Exception e) {
-            assertWithMessage("Uncaught exception while making packets.").fail();
-            return new ArrayList<>();
-        }
-    }
-
-    private void processMessage(byte[] data) {
-        List<BlePacket> packets = createPackets(data);
-        for (BlePacket packet : packets) {
-            mStream.processPacket(packet);
-        }
-    }
-
-    private boolean tryAcquire(@NonNull Semaphore semaphore) throws InterruptedException {
-        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
-    }
-
-    @NonNull
-    private MessageReceivedListener createMessageReceivedListener(@NonNull Semaphore semaphore) {
-        return spy((deviceMessage, operationType) -> semaphore.release());
-    }
-
-    @NonNull
-    private MessageReceivedErrorListener createMessageReceivedErrorListener(
-            @NonNull Semaphore semaphore) {
-        return exception -> semaphore.release();
-    }
-}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BlePacketFactoryTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BlePacketFactoryTest.java
deleted file mode 100644
index 8e8682f..0000000
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/BlePacketFactoryTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.car.connecteddevice.BleStreamProtos.BlePacketProto.BlePacket;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayOutputStream;
-import java.util.List;
-import java.util.Random;
-
-@RunWith(AndroidJUnit4.class)
-public class BlePacketFactoryTest {
-    @Test
-    public void testGetHeaderSize() {
-        // 1 byte to encode the ID, 1 byte for the field number.
-        int messageId = 1;
-        int messageIdEncodingSize = 2;
-
-        // 1 byte for the payload size, 1 byte for the field number.
-        int payloadSize = 2;
-        int payloadSizeEncodingSize = 2;
-
-        // 1 byte for total packets, 1 byte for field number.
-        int totalPackets = 5;
-        int totalPacketsEncodingSize = 2;
-
-        // Packet number if a fixed32, so 4 bytes + 1 byte for field number.
-        int packetNumberEncodingSize = 5;
-
-        int expectedHeaderSize = messageIdEncodingSize + payloadSizeEncodingSize
-                + totalPacketsEncodingSize + packetNumberEncodingSize;
-
-        assertThat(BlePacketFactory.getPacketHeaderSize(totalPackets, messageId, payloadSize))
-                .isEqualTo(expectedHeaderSize);
-    }
-
-    @Test
-    public void testGetTotalPackets_withVarintSize1_returnsCorrectPackets()
-            throws BlePacketFactoryException {
-        int messageId = 1;
-        int maxSize = 49;
-        int payloadSize = 100;
-
-        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
-        // of size 1 means it takes 2 bytes to encode its value. This leaves 38 bytes for the
-        // payload. ceil(payloadSize/38) gives the total packets.
-        int expectedTotalPackets = 3;
-
-        assertThat(BlePacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
-                .isEqualTo(expectedTotalPackets);
-    }
-
-    @Test
-    public void testGetTotalPackets_withVarintSize2_returnsCorrectPackets()
-            throws BlePacketFactoryException {
-        int messageId = 1;
-        int maxSize = 49;
-        int payloadSize = 6000;
-
-        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
-        // of size 2 means it takes 3 bytes to encode its value. This leaves 37 bytes for the
-        // payload. ceil(payloadSize/37) gives the total packets.
-        int expectedTotalPackets = 163;
-
-        assertThat(BlePacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
-                .isEqualTo(expectedTotalPackets);
-    }
-
-    @Test
-    public void testGetTotalPackets_withVarintSize3_returnsCorrectPackets()
-            throws BlePacketFactoryException {
-        int messageId = 1;
-        int maxSize = 49;
-        int payloadSize = 1000000;
-
-        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
-        // of size 3 means it takes 4 bytes to encode its value. This leaves 36 bytes for the
-        // payload. ceil(payloadSize/36) gives the total packets.
-        int expectedTotalPackets = 27778;
-
-        assertThat(BlePacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
-                .isEqualTo(expectedTotalPackets);
-    }
-
-    @Test
-    public void testGetTotalPackets_withVarintSize4_returnsCorrectPackets()
-            throws BlePacketFactoryException {
-        int messageId = 1;
-        int maxSize = 49;
-        int payloadSize = 178400320;
-
-        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
-        // of size 4 means it takes 5 bytes to encode its value. This leaves 35 bytes for the
-        // payload. ceil(payloadSize/35) gives the total packets.
-        int expectedTotalPackets = 5097152;
-
-        assertThat(BlePacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
-                .isEqualTo(expectedTotalPackets);
-    }
-
-    @Test
-    public void testMakePackets_correctlyChunksPayload() throws Exception {
-        // Payload of size 100, but maxSize of 1000 to ensure it fits.
-        byte[] payload = makePayload(/* length= */ 100);
-        int maxSize = 1000;
-
-        List<BlePacket> packets =
-                BlePacketFactory.makeBlePackets(payload, /* mesageId= */ 1, maxSize);
-
-        assertThat(packets).hasSize(1);
-
-        ByteArrayOutputStream reconstructedPayload = new ByteArrayOutputStream();
-
-        // Combine together all the payloads within the BlePackets.
-        for (BlePacket packet : packets) {
-            reconstructedPayload.write(packet.getPayload().toByteArray());
-        }
-
-        assertThat(reconstructedPayload.toByteArray()).isEqualTo(payload);
-    }
-
-    @Test
-    public void testMakePackets_correctlyChunksSplitPayload() throws Exception {
-        // Payload size of 10000 but max size of 50 to ensure the payload is split.
-        byte[] payload = makePayload(/* length= */ 10000);
-        int maxSize = 50;
-
-        List<BlePacket> packets =
-                BlePacketFactory.makeBlePackets(payload, /* mesageId= */ 1, maxSize);
-
-        assertThat(packets.size()).isGreaterThan(1);
-
-        ByteArrayOutputStream reconstructedPayload = new ByteArrayOutputStream();
-
-        // Combine together all the payloads within the BlePackets.
-        for (BlePacket packet : packets) {
-            reconstructedPayload.write(packet.getPayload().toByteArray());
-        }
-
-        assertThat(reconstructedPayload.toByteArray()).isEqualTo(payload);
-    }
-
-    /** Creates a byte array of the given length, populated with random bytes. */
-    private byte[] makePayload(int length) {
-        byte[] payload = new byte[length];
-        new Random().nextBytes(payload);
-        return payload;
-    }
-}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/CarBlePeripheralManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/CarBlePeripheralManagerTest.java
deleted file mode 100644
index acec1f5..0000000
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/CarBlePeripheralManagerTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mockitoSession;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.le.AdvertiseCallback;
-import android.bluetooth.le.AdvertiseData;
-import android.bluetooth.le.AdvertiseSettings;
-import android.os.ParcelUuid;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.car.connecteddevice.AssociationCallback;
-import com.android.car.connecteddevice.model.AssociatedDevice;
-import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
-import com.android.car.connecteddevice.util.ByteUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-import java.time.Duration;
-import java.util.UUID;
-
-@RunWith(AndroidJUnit4.class)
-public class CarBlePeripheralManagerTest {
-    private static final UUID ASSOCIATION_SERVICE_UUID = UUID.randomUUID();
-    private static final UUID RECONNECT_SERVICE_UUID = UUID.randomUUID();
-    private static final UUID RECONNECT_DATA_UUID = UUID.randomUUID();
-    private static final UUID WRITE_UUID = UUID.randomUUID();
-    private static final UUID READ_UUID = UUID.randomUUID();
-    private static final int DEVICE_NAME_LENGTH_LIMIT = 8;
-    private static final String TEST_REMOTE_DEVICE_ADDRESS = "00:11:22:33:AA:BB";
-    private static final UUID TEST_REMOTE_DEVICE_ID = UUID.randomUUID();
-    private static final String TEST_VERIFICATION_CODE = "000000";
-    private static final Duration RECONNECT_ADVERTISEMENT_DURATION = Duration.ofSeconds(2);
-    private static final int DEFAULT_MTU_SIZE = 23;
-
-    @Mock
-    private BlePeripheralManager mMockPeripheralManager;
-    @Mock
-    private ConnectedDeviceStorage mMockStorage;
-    @Mock
-    private AssociationCallback mAssociationCallback;
-
-    private CarBlePeripheralManager mCarBlePeripheralManager;
-
-    private MockitoSession mMockitoSession;
-
-    @Before
-    public void setUp() {
-        mMockitoSession = mockitoSession()
-                .initMocks(this)
-                .strictness(Strictness.WARN)
-                .startMocking();
-        mCarBlePeripheralManager = new CarBlePeripheralManager(mMockPeripheralManager, mMockStorage,
-                ASSOCIATION_SERVICE_UUID, RECONNECT_SERVICE_UUID, RECONNECT_DATA_UUID,
-                WRITE_UUID, READ_UUID, RECONNECT_ADVERTISEMENT_DURATION, DEFAULT_MTU_SIZE);
-        mCarBlePeripheralManager.start();
-    }
-
-    @After
-    public void tearDown() {
-        if (mCarBlePeripheralManager != null) {
-            mCarBlePeripheralManager.stop();
-        }
-        if (mMockitoSession != null) {
-            mMockitoSession.finishMocking();
-        }
-    }
-
-    @Test
-    public void testStartAssociationAdvertisingSuccess() {
-        String testDeviceName = getNameForAssociation();
-        startAssociation(mAssociationCallback, testDeviceName);
-        ArgumentCaptor<AdvertiseData> advertiseDataCaptor =
-                ArgumentCaptor.forClass(AdvertiseData.class);
-        ArgumentCaptor<AdvertiseData> scanResponseDataCaptor =
-                ArgumentCaptor.forClass(AdvertiseData.class);
-        verify(mMockPeripheralManager).startAdvertising(any(), advertiseDataCaptor.capture(),
-                scanResponseDataCaptor.capture(), any());
-        AdvertiseData advertisementData = advertiseDataCaptor.getValue();
-        ParcelUuid serviceUuid = new ParcelUuid(ASSOCIATION_SERVICE_UUID);
-        assertThat(advertisementData.getServiceUuids()).contains(serviceUuid);
-        AdvertiseData scanResponseData = scanResponseDataCaptor.getValue();
-        assertThat(scanResponseData.getIncludeDeviceName()).isFalse();
-        ParcelUuid dataUuid = new ParcelUuid(RECONNECT_DATA_UUID);
-        assertThat(scanResponseData.getServiceData().get(dataUuid)).isEqualTo(
-                testDeviceName.getBytes());
-    }
-
-    @Test
-    public void testStartAssociationAdvertisingFailure() {
-        startAssociation(mAssociationCallback, getNameForAssociation());
-        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
-                ArgumentCaptor.forClass(AdvertiseCallback.class);
-        verify(mMockPeripheralManager).startAdvertising(any(), any(), any(),
-                callbackCaptor.capture());
-        AdvertiseCallback advertiseCallback = callbackCaptor.getValue();
-        int testErrorCode = 2;
-        advertiseCallback.onStartFailure(testErrorCode);
-        verify(mAssociationCallback).onAssociationStartFailure();
-    }
-
-    @Test
-    public void testNotifyAssociationSuccess() {
-        String testDeviceName = getNameForAssociation();
-        startAssociation(mAssociationCallback, testDeviceName);
-        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
-                ArgumentCaptor.forClass(AdvertiseCallback.class);
-        verify(mMockPeripheralManager).startAdvertising(any(), any(), any(),
-                callbackCaptor.capture());
-        AdvertiseCallback advertiseCallback = callbackCaptor.getValue();
-        AdvertiseSettings settings = new AdvertiseSettings.Builder().build();
-        advertiseCallback.onStartSuccess(settings);
-        verify(mAssociationCallback).onAssociationStartSuccess(eq(testDeviceName));
-    }
-
-    @Test
-    public void testShowVerificationCode() {
-        AssociationSecureChannel channel = getChannelForAssociation(mAssociationCallback);
-        channel.getShowVerificationCodeListener().showVerificationCode(TEST_VERIFICATION_CODE);
-        verify(mAssociationCallback).onVerificationCodeAvailable(eq(TEST_VERIFICATION_CODE));
-    }
-
-    @Test
-    public void testAssociationSuccess() {
-        SecureBleChannel channel = getChannelForAssociation(mAssociationCallback);
-        SecureBleChannel.Callback channelCallback = channel.getCallback();
-        assertThat(channelCallback).isNotNull();
-        channelCallback.onDeviceIdReceived(TEST_REMOTE_DEVICE_ID.toString());
-        channelCallback.onSecureChannelEstablished();
-        ArgumentCaptor<AssociatedDevice> deviceCaptor =
-                ArgumentCaptor.forClass(AssociatedDevice.class);
-        verify(mMockStorage).addAssociatedDeviceForActiveUser(deviceCaptor.capture());
-        AssociatedDevice device = deviceCaptor.getValue();
-        assertThat(device.getDeviceId()).isEqualTo(TEST_REMOTE_DEVICE_ID.toString());
-        verify(mAssociationCallback).onAssociationCompleted(eq(TEST_REMOTE_DEVICE_ID.toString()));
-    }
-
-    @Test
-    public void testAssociationFailure_channelError() {
-        SecureBleChannel channel = getChannelForAssociation(mAssociationCallback);
-        SecureBleChannel.Callback channelCallback = channel.getCallback();
-        int testErrorCode = 1;
-        assertThat(channelCallback).isNotNull();
-        channelCallback.onDeviceIdReceived(TEST_REMOTE_DEVICE_ID.toString());
-        channelCallback.onEstablishSecureChannelFailure(testErrorCode);
-        verify(mAssociationCallback).onAssociationError(eq(testErrorCode));
-    }
-
-    @Test
-    public void connectToDevice_stopsAdvertisingAfterTimeout() {
-        when(mMockStorage.hashWithChallengeSecret(any(), any()))
-                .thenReturn(ByteUtils.randomBytes(32));
-        mCarBlePeripheralManager.connectToDevice(UUID.randomUUID());
-        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
-                ArgumentCaptor.forClass(AdvertiseCallback.class);
-        verify(mMockPeripheralManager).startAdvertising(any(), any(), any(),
-                callbackCaptor.capture());
-        callbackCaptor.getValue().onStartSuccess(null);
-        verify(mMockPeripheralManager,
-                timeout(RECONNECT_ADVERTISEMENT_DURATION.plusSeconds(1).toMillis()))
-                .stopAdvertising(any(AdvertiseCallback.class));
-    }
-
-    @Test
-    public void disconnectDevice_stopsAdvertisingForPendingReconnect() {
-        when(mMockStorage.hashWithChallengeSecret(any(), any()))
-                .thenReturn(ByteUtils.randomBytes(32));
-        UUID deviceId = UUID.randomUUID();
-        mCarBlePeripheralManager.connectToDevice(deviceId);
-        reset(mMockPeripheralManager);
-        mCarBlePeripheralManager.disconnectDevice(deviceId.toString());
-        verify(mMockPeripheralManager).cleanup();
-    }
-
-    private BlePeripheralManager.Callback startAssociation(AssociationCallback callback,
-            String deviceName) {
-        ArgumentCaptor<BlePeripheralManager.Callback> callbackCaptor =
-                ArgumentCaptor.forClass(BlePeripheralManager.Callback.class);
-        mCarBlePeripheralManager.startAssociation(deviceName, callback);
-        verify(mMockPeripheralManager, timeout(3000)).registerCallback(callbackCaptor.capture());
-        return callbackCaptor.getValue();
-    }
-
-    private AssociationSecureChannel getChannelForAssociation(AssociationCallback callback) {
-        BlePeripheralManager.Callback bleManagerCallback = startAssociation(callback,
-                getNameForAssociation());
-        BluetoothDevice bluetoothDevice = BluetoothAdapter.getDefaultAdapter()
-                .getRemoteDevice(TEST_REMOTE_DEVICE_ADDRESS);
-        bleManagerCallback.onRemoteDeviceConnected(bluetoothDevice);
-        return (AssociationSecureChannel) mCarBlePeripheralManager.getConnectedDeviceChannel();
-    }
-
-    private String getNameForAssociation() {
-        return ByteUtils.generateRandomNumberString(DEVICE_NAME_LENGTH_LIMIT);
-
-    }
-}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/SecureBleChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/SecureBleChannelTest.java
deleted file mode 100644
index e8f4da4..0000000
--- a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/ble/SecureBleChannelTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.car.connecteddevice.ble;
-
-import static com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType.CLIENT_MESSAGE;
-import static com.android.car.connecteddevice.BleStreamProtos.BleOperationProto.OperationType.ENCRYPTION_HANDSHAKE;
-import static com.android.car.connecteddevice.ble.SecureBleChannel.CHANNEL_ERROR_INVALID_HANDSHAKE;
-import static com.android.car.connecteddevice.ble.SecureBleChannel.Callback;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mockitoSession;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.car.encryptionrunner.DummyEncryptionRunner;
-import android.car.encryptionrunner.EncryptionRunnerFactory;
-import android.car.encryptionrunner.HandshakeException;
-import android.car.encryptionrunner.Key;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.car.connecteddevice.util.ByteUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SignatureException;
-import java.util.UUID;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-public class SecureBleChannelTest {
-
-    @Mock private BleDeviceMessageStream mMockStream;
-
-    @Mock private Key mKey = spy(new Key() {
-        @Override
-        public byte[] asBytes() {
-            return new byte[0];
-        }
-
-        @Override
-        public byte[] encryptData(byte[] data) {
-            return data;
-        }
-
-        @Override
-        public byte[] decryptData(byte[] encryptedData) throws SignatureException {
-            return encryptedData;
-        }
-
-        @Override
-        public byte[] getUniqueSession() throws NoSuchAlgorithmException {
-            return new byte[0];
-        }
-    });
-
-    private MockitoSession mMockitoSession;
-
-    private SecureBleChannel mSecureBleChannel;
-
-    @Before
-    public void setUp() throws SignatureException {
-        mMockitoSession = mockitoSession()
-                .initMocks(this)
-                .strictness(Strictness.WARN)
-                .startMocking();
-
-        mSecureBleChannel = new SecureBleChannel(mMockStream,
-                EncryptionRunnerFactory.newDummyRunner()) {
-            @Override
-            void processHandshake(byte[] message) { }
-        };
-        mSecureBleChannel.setEncryptionKey(mKey);
-    }
-
-    @After
-    public void tearDown() {
-        if (mMockitoSession != null) {
-            mMockitoSession.finishMocking();
-        }
-    }
-
-    @Test
-    public void processMessage_doesNothingForUnencryptedMessage() throws SignatureException {
-        byte[] payload = ByteUtils.randomBytes(10);
-        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ false,
-                payload);
-        mSecureBleChannel.processMessage(message);
-        assertThat(message.getMessage()).isEqualTo(payload);
-        verify(mKey, times(0)).decryptData(any());
-    }
-
-    @Test
-    public void processMessage_decryptsEncryptedMessage() throws SignatureException {
-        byte[] payload = ByteUtils.randomBytes(10);
-        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
-                payload);
-        mSecureBleChannel.processMessage(message);
-        verify(mKey).decryptData(any());
-    }
-
-    @Test
-    public void processMessage_onMessageReceivedErrorForEncryptedMessageWithNoKey()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
-                ByteUtils.randomBytes(10));
-
-        mSecureBleChannel.setEncryptionKey(null);
-        mSecureBleChannel.registerCallback(new Callback() {
-            @Override
-            public void onMessageReceivedError(Exception exception) {
-                semaphore.release();
-            }
-        });
-        mSecureBleChannel.processMessage(message);
-        assertThat(tryAcquire(semaphore)).isTrue();
-        assertThat(message.getMessage()).isNull();
-    }
-
-    @Test
-    public void onMessageReceived_onEstablishSecureChannelFailureBadHandshakeMessage()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
-                ByteUtils.randomBytes(10));
-
-        mSecureBleChannel.setEncryptionKey(null);
-        mSecureBleChannel.registerCallback(new Callback() {
-            @Override
-            public void onEstablishSecureChannelFailure(int error) {
-                assertThat(error).isEqualTo(CHANNEL_ERROR_INVALID_HANDSHAKE);
-                semaphore.release();
-            }
-        });
-        mSecureBleChannel.onMessageReceived(message, ENCRYPTION_HANDSHAKE);
-        assertThat(tryAcquire(semaphore)).isTrue();
-    }
-
-    @Test
-    public void onMessageReceived_onMessageReceivedNotIssuedForNullMessage()
-            throws InterruptedException {
-        Semaphore semaphore = new Semaphore(0);
-        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ false,
-                /* message= */ null);
-
-        mSecureBleChannel.registerCallback(new Callback() {
-            @Override
-            public void onMessageReceived(DeviceMessage message) {
-                semaphore.release();
-            }
-        });
-        mSecureBleChannel.onMessageReceived(message, CLIENT_MESSAGE);
-        assertThat(tryAcquire(semaphore)).isFalse();
-    }
-
-    @Test
-    public void onMessageReceived_processHandshakeExceptionIssuesSecureChannelFailureCallback()
-            throws InterruptedException {
-        SecureBleChannel secureChannel = new SecureBleChannel(mMockStream,
-                EncryptionRunnerFactory.newDummyRunner()) {
-            @Override
-            void processHandshake(byte[] message) throws HandshakeException {
-                DummyEncryptionRunner.throwHandshakeException("test");
-            }
-        };
-        Semaphore semaphore = new Semaphore(0);
-        secureChannel.registerCallback(new Callback() {
-            @Override
-            public void onEstablishSecureChannelFailure(int error) {
-                semaphore.release();
-            }
-        });
-        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
-                /* message= */ ByteUtils.randomBytes(10));
-
-        secureChannel.onMessageReceived(message, ENCRYPTION_HANDSHAKE);
-        assertThat(tryAcquire(semaphore)).isTrue();
-    }
-
-    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
-        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
-    }
-}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/AssociationSecureChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/AssociationSecureChannelTest.java
new file mode 100644
index 0000000..118eca9
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/AssociationSecureChannelTest.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.encryptionrunner.EncryptionRunner;
+import android.car.encryptionrunner.EncryptionRunnerFactory;
+import android.car.encryptionrunner.FakeEncryptionRunner;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType;
+import com.android.car.connecteddevice.connection.ble.BleDeviceMessageStream;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.util.UUID;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public final class AssociationSecureChannelTest {
+    private static final UUID CLIENT_DEVICE_ID =
+            UUID.fromString("a5645523-3280-410a-90c1-582a6c6f4969");
+    private static final UUID SERVER_DEVICE_ID =
+            UUID.fromString("a29f0c74-2014-4b14-ac02-be6ed15b545a");
+    private static final byte[] CLIENT_SECRET = ByteUtils.randomBytes(32);
+
+    @Mock
+    private BleDeviceMessageStream mStreamMock;
+    @Mock
+    private ConnectedDeviceStorage mStorageMock;
+    @Mock
+    private AssociationSecureChannel.ShowVerificationCodeListener mShowVerificationCodeListenerMock;
+    private MockitoSession mMockitoSession;
+
+    private AssociationSecureChannel mChannel;
+    private DeviceMessageStream.MessageReceivedListener mMessageReceivedListener;
+
+    @Before
+    public void setUp() {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+        when(mStorageMock.getUniqueId()).thenReturn(SERVER_DEVICE_ID);
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void testEncryptionHandshake_Association() throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
+        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newFakeRunner);
+        ArgumentCaptor<String> deviceIdCaptor = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<DeviceMessage> messageCaptor =
+                ArgumentCaptor.forClass(DeviceMessage.class);
+
+        initHandshakeMessage();
+        verify(mStreamMock).writeMessage(messageCaptor.capture(), any());
+        byte[] response = messageCaptor.getValue().getMessage();
+        assertThat(response).isEqualTo(FakeEncryptionRunner.INIT_RESPONSE.getBytes());
+
+        respondToContinueMessage();
+        verify(mShowVerificationCodeListenerMock).showVerificationCode(anyString());
+
+        mChannel.notifyOutOfBandAccepted();
+        sendDeviceId();
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onDeviceIdReceived(deviceIdCaptor.capture());
+        verify(mStreamMock, times(2)).writeMessage(messageCaptor.capture(), any());
+        byte[] deviceIdMessage = messageCaptor.getValue().getMessage();
+        assertThat(deviceIdMessage).isEqualTo(ByteUtils.uuidToBytes(SERVER_DEVICE_ID));
+        assertThat(deviceIdCaptor.getValue()).isEqualTo(CLIENT_DEVICE_ID.toString());
+        verify(mStorageMock).saveEncryptionKey(eq(CLIENT_DEVICE_ID.toString()), any());
+        verify(mStorageMock).saveChallengeSecret(CLIENT_DEVICE_ID.toString(), CLIENT_SECRET);
+
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onSecureChannelEstablished();
+    }
+
+    @Test
+    public void testEncryptionHandshake_Association_wrongInitHandshakeMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
+        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newFakeRunner);
+
+        // Wrong init handshake message
+        respondToContinueMessage();
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onEstablishSecureChannelFailure(
+                eq(SecureChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
+        );
+    }
+
+    @Test
+    public void testEncryptionHandshake_Association_wrongRespondToContinueMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        ChannelCallback callbackSpy = spy(new ChannelCallback(semaphore));
+        setupAssociationSecureChannel(callbackSpy, EncryptionRunnerFactory::newFakeRunner);
+
+        initHandshakeMessage();
+
+        // Wrong respond to continue message
+        initHandshakeMessage();
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onEstablishSecureChannelFailure(
+                eq(SecureChannel.CHANNEL_ERROR_INVALID_HANDSHAKE)
+        );
+    }
+
+    private void setupAssociationSecureChannel(ChannelCallback callback,
+            EncryptionRunnerProvider encryptionRunnerProvider) {
+        mChannel = new AssociationSecureChannel(mStreamMock, mStorageMock,
+                encryptionRunnerProvider.getEncryptionRunner());
+        mChannel.registerCallback(callback);
+        mChannel.setShowVerificationCodeListener(mShowVerificationCodeListenerMock);
+        ArgumentCaptor<DeviceMessageStream.MessageReceivedListener> listenerCaptor =
+                ArgumentCaptor.forClass(DeviceMessageStream.MessageReceivedListener.class);
+        verify(mStreamMock).setMessageReceivedListener(listenerCaptor.capture());
+        mMessageReceivedListener = listenerCaptor.getValue();
+    }
+
+    private void sendDeviceId() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ true,
+                ByteUtils.concatByteArrays(ByteUtils.uuidToBytes(CLIENT_DEVICE_ID), CLIENT_SECRET)
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    private void initHandshakeMessage() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ false,
+                FakeEncryptionRunner.INIT.getBytes()
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    private void respondToContinueMessage() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ false,
+                FakeEncryptionRunner.CLIENT_RESPONSE.getBytes()
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    /**
+     * Add the thread control logic into {@link SecureChannel.Callback} only for spy purpose.
+     *
+     * <p>The callback will release the semaphore which hold by one test when this callback
+     * is called, telling the test that it can verify certain behaviors which will only occurred
+     * after the callback is notified. This is needed mainly because of the callback is notified
+     * in a different thread.
+     */
+    private static class ChannelCallback implements SecureChannel.Callback {
+        private final Semaphore mSemaphore;
+
+        ChannelCallback(Semaphore semaphore) {
+            mSemaphore = semaphore;
+        }
+
+        @Override
+        public void onSecureChannelEstablished() {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onEstablishSecureChannelFailure(int error) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onMessageReceived(DeviceMessage deviceMessage) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onMessageReceivedError(Exception exception) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onDeviceIdReceived(String deviceId) {
+            mSemaphore.release();
+        }
+    }
+
+    interface EncryptionRunnerProvider {
+        EncryptionRunner getEncryptionRunner();
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/DeviceMessageStreamTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/DeviceMessageStreamTest.java
new file mode 100644
index 0000000..661bece
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/DeviceMessageStreamTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.StreamProtos.DeviceMessageProto.Message;
+import static com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType;
+import static com.android.car.connecteddevice.StreamProtos.PacketProto.Packet;
+import static com.android.car.connecteddevice.connection.DeviceMessageStream.MessageReceivedErrorListener;
+import static com.android.car.connecteddevice.connection.DeviceMessageStream.MessageReceivedListener;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.util.ByteUtils;
+import com.android.car.protobuf.ByteString;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceMessageStreamTest {
+
+    private static final int WRITE_SIZE = 500;
+
+    private DeviceMessageStream mStream;
+
+    @Before
+    public void setup() {
+        mStream = spy(new DeviceMessageStream(WRITE_SIZE) {
+            @Override
+            protected void send(byte[] data) { }
+        });
+    }
+
+    @Test
+    public void processPacket_notifiesWithEntireMessageForSinglePacketMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
+        mStream.setMessageReceivedListener(listener);
+        byte[] data = ByteUtils.randomBytes(5);
+        processMessage(data);
+        assertThat(tryAcquire(semaphore)).isTrue();
+        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
+        verify(listener).onMessageReceived(messageCaptor.capture(), any());
+    }
+
+    @Test
+    public void processPacket_notifiesWithEntireMessageForMultiPacketMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
+        mStream.setMessageReceivedListener(listener);
+        byte[] data = ByteUtils.randomBytes(750);
+        processMessage(data);
+        assertThat(tryAcquire(semaphore)).isTrue();
+        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
+        verify(listener).onMessageReceived(messageCaptor.capture(), any());
+        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
+    }
+
+    @Test
+    public void processPacket_receivingMultipleMessagesInParallelParsesSuccessfully()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
+        mStream.setMessageReceivedListener(listener);
+        byte[] data = ByteUtils.randomBytes((int) (WRITE_SIZE * 1.5));
+        List<Packet> packets1 = createPackets(data);
+        List<Packet> packets2 = createPackets(data);
+
+        for (int i = 0; i < packets1.size(); i++) {
+            mStream.processPacket(packets1.get(i));
+            if (i == packets1.size() - 1) {
+                break;
+            }
+            mStream.processPacket(packets2.get(i));
+        }
+        assertThat(tryAcquire(semaphore)).isTrue();
+        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
+        verify(listener).onMessageReceived(messageCaptor.capture(), any());
+        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
+
+        semaphore = new Semaphore(0);
+        listener = createMessageReceivedListener(semaphore);
+        mStream.setMessageReceivedListener(listener);
+        mStream.processPacket(packets2.get(packets2.size() - 1));
+        verify(listener).onMessageReceived(messageCaptor.capture(), any());
+        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
+    }
+
+    @Test
+    public void processPacket_doesNotNotifyOfNewMessageIfNotAllPacketsReceived()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        mStream.setMessageReceivedListener(createMessageReceivedListener(semaphore));
+        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
+        byte[] data = ByteUtils.randomBytes((int) (WRITE_SIZE * 1.5));
+        List<Packet> packets = createPackets(data);
+        for (int i = 0; i < packets.size() - 1; i++) {
+            mStream.processPacket(packets.get(i));
+        }
+        assertThat(tryAcquire(semaphore)).isFalse();
+    }
+
+    @Test
+    public void processPacket_ignoresDuplicatePacket() {
+        Semaphore semaphore = new Semaphore(0);
+        byte[] data = ByteUtils.randomBytes((int) (WRITE_SIZE * 2.5));
+        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
+        mStream.setMessageReceivedListener(listener);
+        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
+        List<Packet> packets = createPackets(data);
+        for (int i = 0; i < packets.size(); i++) {
+            mStream.processPacket(packets.get(i));
+            mStream.processPacket(packets.get(i)); // Process each packet twice.
+        }
+        verify(listener).onMessageReceived(messageCaptor.capture(), any());
+        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
+    }
+
+    @Test
+    public void processPacket_packetBeforeExpectedRangeNotifiesMessageError()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
+        List<Packet> packets = createPackets(ByteUtils.randomBytes((int) (WRITE_SIZE * 2.5)));
+        mStream.processPacket(packets.get(0));
+        mStream.processPacket(packets.get(1));
+        mStream.processPacket(packets.get(0));
+        assertThat(tryAcquire(semaphore)).isTrue();
+    }
+
+    @Test
+    public void processPacket_packetAfterExpectedNotifiesMessageError()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
+        List<Packet> packets = createPackets(ByteUtils.randomBytes((int) (WRITE_SIZE * 1.5)));
+        mStream.processPacket(packets.get(1));
+        assertThat(tryAcquire(semaphore)).isTrue();
+    }
+
+    @NonNull
+    private List<Packet> createPackets(byte[] data) {
+        try {
+            Message message = Message.newBuilder()
+                    .setPayload(ByteString.copyFrom(data))
+                    .setOperation(OperationType.CLIENT_MESSAGE)
+                    .build();
+            return PacketFactory.makePackets(message.toByteArray(),
+                    ThreadLocalRandom.current().nextInt(), WRITE_SIZE);
+        } catch (Exception e) {
+            assertWithMessage("Uncaught exception while making packets.").fail();
+            return new ArrayList<>();
+        }
+    }
+
+    private void processMessage(byte[] data) {
+        List<Packet> packets = createPackets(data);
+        for (Packet packet : packets) {
+            mStream.processPacket(packet);
+        }
+    }
+
+    private boolean tryAcquire(@NonNull Semaphore semaphore) throws InterruptedException {
+        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
+    }
+
+    @NonNull
+    private MessageReceivedListener createMessageReceivedListener(@NonNull Semaphore semaphore) {
+        return spy((deviceMessage, operationType) -> semaphore.release());
+    }
+
+    @NonNull
+    private MessageReceivedErrorListener createMessageReceivedErrorListener(
+            @NonNull Semaphore semaphore) {
+        return exception -> semaphore.release();
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/OobAssociationSecureChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/OobAssociationSecureChannelTest.java
new file mode 100644
index 0000000..3ad2a8d
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/OobAssociationSecureChannelTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.encryptionrunner.EncryptionRunnerFactory;
+import android.car.encryptionrunner.FakeEncryptionRunner;
+
+import com.android.car.connecteddevice.connection.ble.BleDeviceMessageStream;
+import com.android.car.connecteddevice.oob.OobConnectionManager;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.util.UUID;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+public class OobAssociationSecureChannelTest {
+    private static final UUID CLIENT_DEVICE_ID =
+            UUID.fromString("a5645523-3280-410a-90c1-582a6c6f4969");
+
+    private static final UUID SERVER_DEVICE_ID =
+            UUID.fromString("a29f0c74-2014-4b14-ac02-be6ed15b545a");
+
+    private static final byte[] CLIENT_SECRET = ByteUtils.randomBytes(32);
+
+    @Mock
+    private BleDeviceMessageStream mStreamMock;
+
+    @Mock
+    private ConnectedDeviceStorage mStorageMock;
+
+    @Mock
+    private OobConnectionManager mOobConnectionManagerMock;
+
+    private OobAssociationSecureChannel mChannel;
+
+    private BleDeviceMessageStream.MessageReceivedListener mMessageReceivedListener;
+
+    private MockitoSession mMockitoSession;
+
+    @Before
+    public void setUp() {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+        when(mStorageMock.getUniqueId()).thenReturn(SERVER_DEVICE_ID);
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void testEncryptionHandshake_oobAssociation() throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        ChannelCallback
+                callbackSpy = spy(new ChannelCallback(semaphore));
+        setupOobAssociationSecureChannel(callbackSpy);
+        ArgumentCaptor<String> deviceIdCaptor = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<DeviceMessage> messageCaptor =
+                ArgumentCaptor.forClass(DeviceMessage.class);
+
+        initHandshakeMessage();
+        verify(mStreamMock).writeMessage(messageCaptor.capture(), any());
+        byte[] response = messageCaptor.getValue().getMessage();
+        assertThat(response).isEqualTo(FakeEncryptionRunner.INIT_RESPONSE.getBytes());
+        reset(mStreamMock);
+        respondToContinueMessage();
+        verify(mStreamMock).writeMessage(messageCaptor.capture(), any());
+        byte[] oobCodeResponse = messageCaptor.getValue().getMessage();
+        assertThat(oobCodeResponse).isEqualTo(FakeEncryptionRunner.VERIFICATION_CODE.getBytes());
+        respondToOobCode();
+        sendDeviceId();
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onDeviceIdReceived(deviceIdCaptor.capture());
+        verify(mStreamMock, times(2)).writeMessage(messageCaptor.capture(), any());
+        byte[] deviceIdMessage = messageCaptor.getValue().getMessage();
+        assertThat(deviceIdMessage).isEqualTo(ByteUtils.uuidToBytes(SERVER_DEVICE_ID));
+        assertThat(deviceIdCaptor.getValue()).isEqualTo(CLIENT_DEVICE_ID.toString());
+        verify(mStorageMock).saveEncryptionKey(eq(CLIENT_DEVICE_ID.toString()), any());
+        verify(mStorageMock).saveChallengeSecret(CLIENT_DEVICE_ID.toString(), CLIENT_SECRET);
+
+        assertThat(semaphore.tryAcquire(100, TimeUnit.MILLISECONDS)).isTrue();
+        verify(callbackSpy).onSecureChannelEstablished();
+    }
+
+    private void setupOobAssociationSecureChannel(ChannelCallback callback) {
+        mChannel = new OobAssociationSecureChannel(mStreamMock, mStorageMock,
+                mOobConnectionManagerMock, EncryptionRunnerFactory.newOobFakeRunner());
+        mChannel.registerCallback(callback);
+        ArgumentCaptor<BleDeviceMessageStream.MessageReceivedListener> listenerCaptor =
+                ArgumentCaptor.forClass(BleDeviceMessageStream.MessageReceivedListener.class);
+        verify(mStreamMock).setMessageReceivedListener(listenerCaptor.capture());
+        mMessageReceivedListener = listenerCaptor.getValue();
+        try {
+            when(mOobConnectionManagerMock.encryptVerificationCode(any()))
+                    .thenReturn(FakeEncryptionRunner.VERIFICATION_CODE.getBytes());
+        } catch (InvalidAlgorithmParameterException | BadPaddingException | InvalidKeyException
+                | IllegalBlockSizeException e) {
+        }
+        try {
+            when(mOobConnectionManagerMock.decryptVerificationCode(any()))
+                    .thenReturn(FakeEncryptionRunner.VERIFICATION_CODE.getBytes());
+        } catch (InvalidAlgorithmParameterException | BadPaddingException | InvalidKeyException
+                | IllegalBlockSizeException e) {
+        }
+    }
+
+    private void sendDeviceId() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ true,
+                ByteUtils.concatByteArrays(ByteUtils.uuidToBytes(CLIENT_DEVICE_ID), CLIENT_SECRET)
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    private void initHandshakeMessage() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ false,
+                FakeEncryptionRunner.INIT.getBytes()
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    private void respondToContinueMessage() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ false,
+                FakeEncryptionRunner.CLIENT_RESPONSE.getBytes()
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    private void respondToOobCode() {
+        DeviceMessage message = new DeviceMessage(
+                /* recipient= */ null,
+                /* isMessageEncrypted= */ false,
+                FakeEncryptionRunner.VERIFICATION_CODE.getBytes()
+        );
+        mMessageReceivedListener.onMessageReceived(message, OperationType.ENCRYPTION_HANDSHAKE);
+    }
+
+    /**
+     * Add the thread control logic into {@link SecureChannel.Callback} only for spy purpose.
+     *
+     * <p>The callback will release the semaphore which hold by one test when this callback
+     * is called, telling the test that it can verify certain behaviors which will only occurred
+     * after the callback is notified. This is needed mainly because of the callback is notified
+     * in a different thread.
+     */
+    private static class ChannelCallback implements SecureChannel.Callback {
+        private final Semaphore mSemaphore;
+
+        ChannelCallback(Semaphore semaphore) {
+            mSemaphore = semaphore;
+        }
+
+        @Override
+        public void onSecureChannelEstablished() {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onEstablishSecureChannelFailure(int error) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onMessageReceived(DeviceMessage deviceMessage) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onMessageReceivedError(Exception exception) {
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onDeviceIdReceived(String deviceId) {
+            mSemaphore.release();
+        }
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/PacketFactoryTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/PacketFactoryTest.java
new file mode 100644
index 0000000..d5fdc03
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/PacketFactoryTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.StreamProtos.PacketProto.Packet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+import java.util.Random;
+
+@RunWith(AndroidJUnit4.class)
+public class PacketFactoryTest {
+    @Test
+    public void testGetHeaderSize() {
+        // 1 byte to encode the ID, 1 byte for the field number.
+        int messageId = 1;
+        int messageIdEncodingSize = 2;
+
+        // 1 byte for the payload size, 1 byte for the field number.
+        int payloadSize = 2;
+        int payloadSizeEncodingSize = 2;
+
+        // 1 byte for total packets, 1 byte for field number.
+        int totalPackets = 5;
+        int totalPacketsEncodingSize = 2;
+
+        // Packet number if a fixed32, so 4 bytes + 1 byte for field number.
+        int packetNumberEncodingSize = 5;
+
+        int expectedHeaderSize = messageIdEncodingSize + payloadSizeEncodingSize
+                + totalPacketsEncodingSize + packetNumberEncodingSize;
+
+        assertThat(PacketFactory.getPacketHeaderSize(totalPackets, messageId, payloadSize))
+                .isEqualTo(expectedHeaderSize);
+    }
+
+    @Test
+    public void testGetTotalPackets_withVarintSize1_returnsCorrectPackets()
+            throws PacketFactoryException {
+        int messageId = 1;
+        int maxSize = 49;
+        int payloadSize = 100;
+
+        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
+        // of size 1 means it takes 2 bytes to encode its value. This leaves 38 bytes for the
+        // payload. ceil(payloadSize/38) gives the total packets.
+        int expectedTotalPackets = 3;
+
+        assertThat(PacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
+                .isEqualTo(expectedTotalPackets);
+    }
+
+    @Test
+    public void testGetTotalPackets_withVarintSize2_returnsCorrectPackets()
+            throws PacketFactoryException {
+        int messageId = 1;
+        int maxSize = 49;
+        int payloadSize = 6000;
+
+        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
+        // of size 2 means it takes 3 bytes to encode its value. This leaves 37 bytes for the
+        // payload. ceil(payloadSize/37) gives the total packets.
+        int expectedTotalPackets = 163;
+
+        assertThat(PacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
+                .isEqualTo(expectedTotalPackets);
+    }
+
+    @Test
+    public void testGetTotalPackets_withVarintSize3_returnsCorrectPackets()
+            throws PacketFactoryException {
+        int messageId = 1;
+        int maxSize = 49;
+        int payloadSize = 1000000;
+
+        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
+        // of size 3 means it takes 4 bytes to encode its value. This leaves 36 bytes for the
+        // payload. ceil(payloadSize/36) gives the total packets.
+        int expectedTotalPackets = 27778;
+
+        assertThat(PacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
+                .isEqualTo(expectedTotalPackets);
+    }
+
+    @Test
+    public void testGetTotalPackets_withVarintSize4_returnsCorrectPackets()
+            throws PacketFactoryException {
+        int messageId = 1;
+        int maxSize = 49;
+        int payloadSize = 178400320;
+
+        // This leaves us 40 bytes to use for the payload and its encoding size. Assuming a varint
+        // of size 4 means it takes 5 bytes to encode its value. This leaves 35 bytes for the
+        // payload. ceil(payloadSize/35) gives the total packets.
+        int expectedTotalPackets = 5097152;
+
+        assertThat(PacketFactory.getTotalPacketNumber(messageId, payloadSize, maxSize))
+                .isEqualTo(expectedTotalPackets);
+    }
+
+    @Test
+    public void testMakePackets_correctlyChunksPayload() throws Exception {
+        // Payload of size 100, but maxSize of 1000 to ensure it fits.
+        byte[] payload = makePayload(/* length= */ 100);
+        int maxSize = 1000;
+
+        List<Packet> packets =
+                PacketFactory.makePackets(payload, /* messageId= */ 1, maxSize);
+
+        assertThat(packets).hasSize(1);
+
+        ByteArrayOutputStream reconstructedPayload = new ByteArrayOutputStream();
+
+        // Combine together all the payloads within the BlePackets.
+        for (Packet packet : packets) {
+            reconstructedPayload.write(packet.getPayload().toByteArray());
+        }
+
+        assertThat(reconstructedPayload.toByteArray()).isEqualTo(payload);
+    }
+
+    @Test
+    public void testMakePackets_correctlyChunksSplitPayload() throws Exception {
+        // Payload size of 10000 but max size of 50 to ensure the payload is split.
+        byte[] payload = makePayload(/* length= */ 10000);
+        int maxSize = 50;
+
+        List<Packet> packets =
+                PacketFactory.makePackets(payload, /* messageId= */ 1, maxSize);
+
+        assertThat(packets.size()).isGreaterThan(1);
+
+        ByteArrayOutputStream reconstructedPayload = new ByteArrayOutputStream();
+
+        // Combine together all the payloads within the BlePackets.
+        for (Packet packet : packets) {
+            reconstructedPayload.write(packet.getPayload().toByteArray());
+        }
+
+        assertThat(reconstructedPayload.toByteArray()).isEqualTo(payload);
+    }
+
+    /** Creates a byte array of the given length, populated with random bytes. */
+    private byte[] makePayload(int length) {
+        byte[] payload = new byte[length];
+        new Random().nextBytes(payload);
+        return payload;
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/SecureChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/SecureChannelTest.java
new file mode 100644
index 0000000..ce56ebb
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/SecureChannelTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection;
+
+import static com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType.CLIENT_MESSAGE;
+import static com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType.ENCRYPTION_HANDSHAKE;
+import static com.android.car.connecteddevice.connection.SecureChannel.CHANNEL_ERROR_INVALID_HANDSHAKE;
+import static com.android.car.connecteddevice.connection.SecureChannel.Callback;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.car.encryptionrunner.EncryptionRunnerFactory;
+import android.car.encryptionrunner.FakeEncryptionRunner;
+import android.car.encryptionrunner.HandshakeException;
+import android.car.encryptionrunner.Key;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.connection.ble.BleDeviceMessageStream;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+import java.util.UUID;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class SecureChannelTest {
+
+    @Mock private BleDeviceMessageStream mMockStream;
+
+    @Mock private Key mKey = spy(new Key() {
+        @Override
+        public byte[] asBytes() {
+            return new byte[0];
+        }
+
+        @Override
+        public byte[] encryptData(byte[] data) {
+            return data;
+        }
+
+        @Override
+        public byte[] decryptData(byte[] encryptedData) throws SignatureException {
+            return encryptedData;
+        }
+
+        @Override
+        public byte[] getUniqueSession() throws NoSuchAlgorithmException {
+            return new byte[0];
+        }
+    });
+
+    private MockitoSession mMockitoSession;
+
+    private SecureChannel mSecureChannel;
+
+    @Before
+    public void setUp() throws SignatureException {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+
+        mSecureChannel = new SecureChannel(mMockStream,
+                EncryptionRunnerFactory.newFakeRunner()) {
+            @Override
+            void processHandshake(byte[] message) { }
+        };
+        mSecureChannel.setEncryptionKey(mKey);
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void processMessage_doesNothingForUnencryptedMessage() throws SignatureException {
+        byte[] payload = ByteUtils.randomBytes(10);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ false,
+                payload);
+        mSecureChannel.processMessage(message);
+        assertThat(message.getMessage()).isEqualTo(payload);
+        verify(mKey, times(0)).decryptData(any());
+    }
+
+    @Test
+    public void processMessage_decryptsEncryptedMessage() throws SignatureException {
+        byte[] payload = ByteUtils.randomBytes(10);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                payload);
+        mSecureChannel.processMessage(message);
+        verify(mKey).decryptData(any());
+    }
+
+    @Test
+    public void processMessage_onMessageReceivedErrorForEncryptedMessageWithNoKey()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                ByteUtils.randomBytes(10));
+
+        mSecureChannel.setEncryptionKey(null);
+        mSecureChannel.registerCallback(new Callback() {
+            @Override
+            public void onMessageReceivedError(Exception exception) {
+                semaphore.release();
+            }
+        });
+        mSecureChannel.processMessage(message);
+        assertThat(tryAcquire(semaphore)).isTrue();
+        assertThat(message.getMessage()).isNull();
+    }
+
+    @Test
+    public void onMessageReceived_onEstablishSecureChannelFailureBadHandshakeMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                ByteUtils.randomBytes(10));
+
+        mSecureChannel.setEncryptionKey(null);
+        mSecureChannel.registerCallback(new Callback() {
+            @Override
+            public void onEstablishSecureChannelFailure(int error) {
+                assertThat(error).isEqualTo(CHANNEL_ERROR_INVALID_HANDSHAKE);
+                semaphore.release();
+            }
+        });
+        mSecureChannel.onMessageReceived(message, ENCRYPTION_HANDSHAKE);
+        assertThat(tryAcquire(semaphore)).isTrue();
+    }
+
+    @Test
+    public void onMessageReceived_onMessageReceivedNotIssuedForNullMessage()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ false,
+                /* message= */ null);
+
+        mSecureChannel.registerCallback(new Callback() {
+            @Override
+            public void onMessageReceived(DeviceMessage message) {
+                semaphore.release();
+            }
+        });
+        mSecureChannel.onMessageReceived(message, CLIENT_MESSAGE);
+        assertThat(tryAcquire(semaphore)).isFalse();
+    }
+
+    @Test
+    public void onMessageReceived_processHandshakeExceptionIssuesSecureChannelFailureCallback()
+            throws InterruptedException {
+        SecureChannel secureChannel = new SecureChannel(mMockStream,
+                EncryptionRunnerFactory.newFakeRunner()) {
+            @Override
+            void processHandshake(byte[] message) throws HandshakeException {
+                FakeEncryptionRunner.throwHandshakeException("test");
+            }
+        };
+        Semaphore semaphore = new Semaphore(0);
+        secureChannel.registerCallback(new Callback() {
+            @Override
+            public void onEstablishSecureChannelFailure(int error) {
+                semaphore.release();
+            }
+        });
+        DeviceMessage message = new DeviceMessage(UUID.randomUUID(), /* isEncrypted= */ true,
+                /* message= */ ByteUtils.randomBytes(10));
+
+        secureChannel.onMessageReceived(message, ENCRYPTION_HANDSHAKE);
+        assertThat(tryAcquire(semaphore)).isTrue();
+    }
+
+    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
+        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/ble/CarBlePeripheralManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/ble/CarBlePeripheralManagerTest.java
new file mode 100644
index 0000000..b4a229e
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/ble/CarBlePeripheralManagerTest.java
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+package com.android.car.connecteddevice.connection.ble;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.os.ParcelUuid;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.AssociationCallback;
+import com.android.car.connecteddevice.connection.AssociationSecureChannel;
+import com.android.car.connecteddevice.connection.SecureChannel;
+import com.android.car.connecteddevice.model.AssociatedDevice;
+import com.android.car.connecteddevice.oob.OobConnectionManager;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.time.Duration;
+import java.util.UUID;
+
+@RunWith(AndroidJUnit4.class)
+public class CarBlePeripheralManagerTest {
+    private static final UUID ASSOCIATION_SERVICE_UUID = UUID.randomUUID();
+    private static final UUID RECONNECT_SERVICE_UUID = UUID.randomUUID();
+    private static final UUID RECONNECT_DATA_UUID = UUID.randomUUID();
+    private static final UUID WRITE_UUID = UUID.randomUUID();
+    private static final UUID READ_UUID = UUID.randomUUID();
+    private static final int DEVICE_NAME_LENGTH_LIMIT = 8;
+    private static final String TEST_REMOTE_DEVICE_ADDRESS = "00:11:22:33:AA:BB";
+    private static final UUID TEST_REMOTE_DEVICE_ID = UUID.randomUUID();
+    private static final String TEST_VERIFICATION_CODE = "000000";
+    private static final String TEST_ENCRYPTED_VERIFICATION_CODE = "12345";
+    private static final Duration RECONNECT_ADVERTISEMENT_DURATION = Duration.ofSeconds(2);
+    private static final int DEFAULT_MTU_SIZE = 23;
+
+    @Mock
+    private BlePeripheralManager mMockPeripheralManager;
+    @Mock
+    private ConnectedDeviceStorage mMockStorage;
+    @Mock
+    private OobConnectionManager mMockOobConnectionManager;
+    @Mock
+    private AssociationCallback mAssociationCallback;
+
+    private CarBlePeripheralManager mCarBlePeripheralManager;
+
+    private MockitoSession mMockitoSession;
+
+    @Before
+    public void setUp() throws Exception {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+        mCarBlePeripheralManager = new CarBlePeripheralManager(mMockPeripheralManager, mMockStorage,
+                ASSOCIATION_SERVICE_UUID, RECONNECT_SERVICE_UUID,
+                RECONNECT_DATA_UUID, WRITE_UUID, READ_UUID, RECONNECT_ADVERTISEMENT_DURATION,
+                DEFAULT_MTU_SIZE);
+
+        when(mMockOobConnectionManager.encryptVerificationCode(
+                TEST_VERIFICATION_CODE.getBytes())).thenReturn(
+                TEST_ENCRYPTED_VERIFICATION_CODE.getBytes());
+        when(mMockOobConnectionManager.decryptVerificationCode(
+                TEST_ENCRYPTED_VERIFICATION_CODE.getBytes())).thenReturn(
+                TEST_VERIFICATION_CODE.getBytes());
+        mCarBlePeripheralManager.start();
+    }
+
+    @After
+    public void tearDown() {
+        if (mCarBlePeripheralManager != null) {
+            mCarBlePeripheralManager.stop();
+        }
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void testStartAssociationAdvertisingSuccess() {
+        String testDeviceName = getNameForAssociation();
+        startAssociation(mAssociationCallback, testDeviceName);
+        ArgumentCaptor<AdvertiseData> advertisementDataCaptor =
+                ArgumentCaptor.forClass(AdvertiseData.class);
+        ArgumentCaptor<AdvertiseData> scanResponseDataCaptor =
+                ArgumentCaptor.forClass(AdvertiseData.class);
+        verify(mMockPeripheralManager).startAdvertising(any(), advertisementDataCaptor.capture(),
+                scanResponseDataCaptor.capture(), any());
+        AdvertiseData advertisementData = advertisementDataCaptor.getValue();
+        ParcelUuid serviceUuid = new ParcelUuid(ASSOCIATION_SERVICE_UUID);
+        assertThat(advertisementData.getServiceUuids()).contains(serviceUuid);
+        AdvertiseData scanResponseData = scanResponseDataCaptor.getValue();
+        assertThat(scanResponseData.getIncludeDeviceName()).isFalse();
+        ParcelUuid dataUuid = new ParcelUuid(RECONNECT_DATA_UUID);
+        assertThat(scanResponseData.getServiceData().get(dataUuid)).isEqualTo(
+                testDeviceName.getBytes());
+    }
+
+    @Test
+    public void testStartAssociationAdvertisingFailure() {
+        startAssociation(mAssociationCallback, getNameForAssociation());
+        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
+                ArgumentCaptor.forClass(AdvertiseCallback.class);
+        verify(mMockPeripheralManager).startAdvertising(any(), any(), any(),
+                callbackCaptor.capture());
+        AdvertiseCallback advertiseCallback = callbackCaptor.getValue();
+        int testErrorCode = 2;
+        advertiseCallback.onStartFailure(testErrorCode);
+        verify(mAssociationCallback).onAssociationStartFailure();
+    }
+
+    @Test
+    public void testNotifyAssociationSuccess() {
+        String testDeviceName = getNameForAssociation();
+        startAssociation(mAssociationCallback, testDeviceName);
+        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
+                ArgumentCaptor.forClass(AdvertiseCallback.class);
+        verify(mMockPeripheralManager).startAdvertising(any(), any(), any(),
+                callbackCaptor.capture());
+        AdvertiseCallback advertiseCallback = callbackCaptor.getValue();
+        AdvertiseSettings settings = new AdvertiseSettings.Builder().build();
+        advertiseCallback.onStartSuccess(settings);
+        verify(mAssociationCallback).onAssociationStartSuccess(eq(testDeviceName));
+    }
+
+    @Test
+    public void testShowVerificationCode() {
+        AssociationSecureChannel channel = getChannelForAssociation(mAssociationCallback);
+        channel.getShowVerificationCodeListener().showVerificationCode(TEST_VERIFICATION_CODE);
+        verify(mAssociationCallback).onVerificationCodeAvailable(eq(TEST_VERIFICATION_CODE));
+    }
+
+    @Test
+    public void testAssociationSuccess() {
+        SecureChannel channel = getChannelForAssociation(mAssociationCallback);
+        SecureChannel.Callback channelCallback = channel.getCallback();
+        assertThat(channelCallback).isNotNull();
+        channelCallback.onDeviceIdReceived(TEST_REMOTE_DEVICE_ID.toString());
+        channelCallback.onSecureChannelEstablished();
+        ArgumentCaptor<AssociatedDevice> deviceCaptor =
+                ArgumentCaptor.forClass(AssociatedDevice.class);
+        verify(mMockStorage).addAssociatedDeviceForActiveUser(deviceCaptor.capture());
+        AssociatedDevice device = deviceCaptor.getValue();
+        assertThat(device.getDeviceId()).isEqualTo(TEST_REMOTE_DEVICE_ID.toString());
+        verify(mAssociationCallback).onAssociationCompleted(eq(TEST_REMOTE_DEVICE_ID.toString()));
+    }
+
+    @Test
+    public void testAssociationFailure_channelError() {
+        SecureChannel channel = getChannelForAssociation(mAssociationCallback);
+        SecureChannel.Callback channelCallback = channel.getCallback();
+        int testErrorCode = 1;
+        assertThat(channelCallback).isNotNull();
+        channelCallback.onDeviceIdReceived(TEST_REMOTE_DEVICE_ID.toString());
+        channelCallback.onEstablishSecureChannelFailure(testErrorCode);
+        verify(mAssociationCallback).onAssociationError(eq(testErrorCode));
+    }
+
+    @Test
+    public void connectToDevice_stopsAdvertisingAfterTimeout() {
+        when(mMockStorage.hashWithChallengeSecret(any(), any()))
+                .thenReturn(ByteUtils.randomBytes(32));
+        mCarBlePeripheralManager.connectToDevice(UUID.randomUUID());
+        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
+                ArgumentCaptor.forClass(AdvertiseCallback.class);
+        verify(mMockPeripheralManager).startAdvertising(any(), any(), any(),
+                callbackCaptor.capture());
+        callbackCaptor.getValue().onStartSuccess(null);
+        verify(mMockPeripheralManager,
+                timeout(RECONNECT_ADVERTISEMENT_DURATION.plusSeconds(1).toMillis()))
+                .stopAdvertising(any(AdvertiseCallback.class));
+    }
+
+    @Test
+    public void disconnectDevice_stopsAdvertisingForPendingReconnect() {
+        when(mMockStorage.hashWithChallengeSecret(any(), any()))
+                .thenReturn(ByteUtils.randomBytes(32));
+        UUID deviceId = UUID.randomUUID();
+        mCarBlePeripheralManager.connectToDevice(deviceId);
+        reset(mMockPeripheralManager);
+        mCarBlePeripheralManager.disconnectDevice(deviceId.toString());
+        verify(mMockPeripheralManager).cleanup();
+    }
+
+    private BlePeripheralManager.Callback startAssociation(AssociationCallback callback,
+            String deviceName) {
+        ArgumentCaptor<BlePeripheralManager.Callback> callbackCaptor =
+                ArgumentCaptor.forClass(BlePeripheralManager.Callback.class);
+        mCarBlePeripheralManager.startAssociation(deviceName, callback);
+        verify(mMockPeripheralManager, timeout(3000)).registerCallback(callbackCaptor.capture());
+        return callbackCaptor.getValue();
+    }
+
+    private AssociationSecureChannel getChannelForAssociation(AssociationCallback callback) {
+        BlePeripheralManager.Callback bleManagerCallback = startAssociation(callback,
+                getNameForAssociation());
+        BluetoothDevice bluetoothDevice = BluetoothAdapter.getDefaultAdapter()
+                .getRemoteDevice(TEST_REMOTE_DEVICE_ADDRESS);
+        bleManagerCallback.onRemoteDeviceConnected(bluetoothDevice);
+        return (AssociationSecureChannel) mCarBlePeripheralManager.getConnectedDeviceChannel();
+    }
+
+    private String getNameForAssociation() {
+        return ByteUtils.generateRandomNumberString(DEVICE_NAME_LENGTH_LIMIT);
+
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/CarSppManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/CarSppManagerTest.java
new file mode 100644
index 0000000..ef0ee85
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/CarSppManagerTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+
+import androidx.annotation.NonNull;
+
+import com.android.car.connecteddevice.AssociationCallback;
+import com.android.car.connecteddevice.connection.AssociationSecureChannel;
+import com.android.car.connecteddevice.connection.SecureChannel;
+import com.android.car.connecteddevice.model.AssociatedDevice;
+import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.util.UUID;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class CarSppManagerTest {
+    private static final String TEST_REMOTE_DEVICE_ADDRESS = "00:11:22:33:AA:BB";
+    private static final UUID TEST_REMOTE_DEVICE_ID = UUID.randomUUID();
+    private static final UUID TEST_SERVICE_UUID = UUID.randomUUID();
+    private static final String TEST_VERIFICATION_CODE = "000000";
+    private static final int MAX_PACKET_SIZE = 700;
+    @Mock
+    private SppManager mMockSppManager;
+    @Mock
+    private ConnectedDeviceStorage mMockStorage;
+
+    private CarSppManager mCarSppManager;
+
+    private MockitoSession mMockitoSession;
+
+    @Before
+    public void setUp() throws Exception {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+        mCarSppManager = new CarSppManager(mMockSppManager, mMockStorage, TEST_SERVICE_UUID,
+                MAX_PACKET_SIZE);
+    }
+
+    @After
+    public void tearDown() {
+        if (mCarSppManager != null) {
+            mCarSppManager.stop();
+        }
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void testStartAssociationSuccess() throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        AssociationCallback callback = createAssociationCallback(semaphore);
+        when(mMockSppManager.startListening(TEST_SERVICE_UUID)).thenReturn(true);
+
+        mCarSppManager.startAssociation(null, callback);
+
+        verify(mMockSppManager).startListening(TEST_SERVICE_UUID);
+        assertThat(tryAcquire(semaphore)).isTrue();
+        verify(callback).onAssociationStartSuccess(eq(null));
+    }
+
+    @Test
+    public void testStartAssociationFailure() throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        AssociationCallback callback = createAssociationCallback(semaphore);
+        when(mMockSppManager.startListening(TEST_SERVICE_UUID)).thenReturn(false);
+
+        mCarSppManager.startAssociation(null, callback);
+
+        assertThat(tryAcquire(semaphore)).isTrue();
+        verify(callback).onAssociationStartFailure();
+    }
+
+    @Test
+    public void testShowVerificationCode() throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        AssociationCallback callback = createAssociationCallback(semaphore);
+        AssociationSecureChannel channel = getChannelForAssociation(callback);
+
+        channel.getShowVerificationCodeListener().showVerificationCode(TEST_VERIFICATION_CODE);
+
+        assertThat(tryAcquire(semaphore)).isTrue();
+        verify(callback).onVerificationCodeAvailable(eq(TEST_VERIFICATION_CODE));
+    }
+
+    @Test
+    public void testAssociationSuccess() throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        AssociationCallback callback = createAssociationCallback(semaphore);
+        SecureChannel channel = getChannelForAssociation(callback);
+        SecureChannel.Callback channelCallback = channel.getCallback();
+
+        assertThat(channelCallback).isNotNull();
+
+        channelCallback.onDeviceIdReceived(TEST_REMOTE_DEVICE_ID.toString());
+        channelCallback.onSecureChannelEstablished();
+        ArgumentCaptor<AssociatedDevice> deviceCaptor =
+                ArgumentCaptor.forClass(AssociatedDevice.class);
+        verify(mMockStorage).addAssociatedDeviceForActiveUser(deviceCaptor.capture());
+        AssociatedDevice device = deviceCaptor.getValue();
+
+        assertThat(device.getDeviceId()).isEqualTo(TEST_REMOTE_DEVICE_ID.toString());
+        assertThat(tryAcquire(semaphore)).isTrue();
+        verify(callback).onAssociationCompleted(eq(TEST_REMOTE_DEVICE_ID.toString()));
+    }
+
+    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
+        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
+    }
+
+    private AssociationSecureChannel getChannelForAssociation(AssociationCallback callback) {
+        ArgumentCaptor<SppManager.ConnectionCallback> callbackCaptor =
+                ArgumentCaptor.forClass(SppManager.ConnectionCallback.class);
+        mCarSppManager.startAssociation(null, callback);
+        verify(mMockSppManager).registerCallback(callbackCaptor.capture(), any());
+        BluetoothDevice bluetoothDevice = BluetoothAdapter.getDefaultAdapter()
+                .getRemoteDevice(TEST_REMOTE_DEVICE_ADDRESS);
+        callbackCaptor.getValue().onRemoteDeviceConnected(bluetoothDevice);
+        return (AssociationSecureChannel) mCarSppManager.getConnectedDeviceChannel();
+    }
+
+    @NonNull
+    private AssociationCallback createAssociationCallback(@NonNull final Semaphore semaphore) {
+        return spy(new AssociationCallback() {
+            @Override
+            public void onAssociationStartSuccess(String deviceName) {
+                semaphore.release();
+            }
+
+            @Override
+            public void onAssociationStartFailure() {
+                semaphore.release();
+            }
+
+            @Override
+            public void onAssociationError(int error) {
+                semaphore.release();
+            }
+
+            @Override
+            public void onVerificationCodeAvailable(String code) {
+                semaphore.release();
+            }
+
+            @Override
+            public void onAssociationCompleted(String deviceId) {
+                semaphore.release();
+            }
+        });
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/ConnectedTaskTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/ConnectedTaskTest.java
new file mode 100644
index 0000000..7ae8192
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/ConnectedTaskTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class ConnectedTaskTest {
+
+    private final byte[] mTestData = "testData".getBytes();
+    private ConnectedTask mConnectedTask;
+    private InputStream mInputStream = new ByteArrayInputStream(mTestData);
+    private OutputStream mOutputStream = new ByteArrayOutputStream();
+    private ConnectedTask.Callback mCallback;
+    private Executor mExecutor = Executors.newSingleThreadExecutor();
+    private Semaphore mSemaphore = new Semaphore(0);
+
+
+    @Before
+    public void setUp() {
+        mCallback = spy(new ConnectedTask.Callback() {
+            @Override
+            public void onMessageReceived(byte[] message) {
+                mSemaphore.release();
+            }
+
+            @Override
+            public void onDisconnected() {
+
+            }
+        });
+        mConnectedTask = new ConnectedTask(mInputStream, mOutputStream, null, mCallback);
+    }
+
+    @Test
+    public void testTaskRun_InformCallback() throws InterruptedException {
+        mExecutor.execute(mConnectedTask);
+        assertThat(tryAcquire(mSemaphore)).isTrue();
+        verify(mCallback).onMessageReceived(mTestData);
+    }
+
+    @Test
+    public void testWrite_WriteToOutputStream() {
+        mConnectedTask.write(mTestData);
+        assertThat(mOutputStream.toString()).isEqualTo(new String(mTestData));
+    }
+
+    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
+        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppDeviceMessageStreamTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppDeviceMessageStreamTest.java
new file mode 100644
index 0000000..a126d04
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppDeviceMessageStreamTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+@RunWith(AndroidJUnit4.class)
+public class SppDeviceMessageStreamTest {
+    private static final int MAX_WRITE_SIZE = 700;
+
+    @Mock
+    private SppManager mMockSppManager;
+    private BluetoothDevice mBluetoothDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(
+            "00:11:22:33:44:55");
+    private MockitoSession mMockingSession;
+    private SppDeviceMessageStream mSppDeviceMessageStream;
+
+    @Before
+    public void setUp() {
+        mMockingSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+        mSppDeviceMessageStream = spy(
+                new SppDeviceMessageStream(mMockSppManager, mBluetoothDevice, MAX_WRITE_SIZE));
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockingSession != null) {
+            mMockingSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void send_callsWriteAndSendCompleted() {
+        byte[] data = ByteUtils.randomBytes(10);
+        mSppDeviceMessageStream.send(data);
+        verify(mMockSppManager).write(data);
+        verify(mSppDeviceMessageStream).sendCompleted();
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppManagerTest.java
new file mode 100644
index 0000000..a99fc6b
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppManagerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothDevice;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.io.IOException;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class SppManagerTest {
+    private static final UUID TEST_SERVICE_UUID = UUID.randomUUID();
+    private final boolean mIsSecureRfcommChannel = true;
+    private final byte[] mTestData = "testData".getBytes();
+    private SppManager mSppManager;
+    private Executor mCallbackExecutor = Executors.newSingleThreadExecutor();
+    private byte[] mCompletedMessage = SppPayloadStream.wrapWithArrayLength(mTestData);
+    @Mock
+    private ConnectedTask mMockConnectedTask;
+
+    @Mock
+    private ExecutorService mMockExecutorService;
+    private MockitoSession mMockitoSession;
+
+
+    @Before
+    public void setUp() throws IOException {
+        mSppManager = new SppManager(mIsSecureRfcommChannel);
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void testStartListen_StartAcceptTask() {
+        mSppManager.mConnectionExecutor = mMockExecutorService;
+        mSppManager.startListening(TEST_SERVICE_UUID);
+        assertThat(mSppManager.mAcceptTask).isNotNull();
+        verify(mMockExecutorService).execute(mSppManager.mAcceptTask);
+    }
+
+    @Test
+    public void testWrite_CallConnectedTaskToWrite() {
+        mSppManager.mConnectedTask = mMockConnectedTask;
+        mSppManager.mState = SppManager.ConnectionState.CONNECTED;
+        mSppManager.write(mTestData);
+        verify(mMockConnectedTask).write(SppPayloadStream.wrapWithArrayLength(mTestData));
+    }
+
+    @Test
+    public void testConnectedTaskCallback_onMessageReceived_CallOnMessageReceivedListener()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        SppManager.OnMessageReceivedListener listener = createOnMessageReceivedListener(semaphore);
+        mSppManager.addOnMessageReceivedListener(listener, mCallbackExecutor);
+        mSppManager.mConnectedTaskCallback.onMessageReceived(mCompletedMessage);
+        assertThat(tryAcquire(semaphore)).isTrue();
+        verify(listener).onMessageReceived(any(), eq(mTestData));
+    }
+
+    @Test
+    public void testConnectedTaskCallback_onDisconnected_CallOnRemoteDeviceDisconnected()
+            throws InterruptedException {
+        Semaphore semaphore = new Semaphore(0);
+        SppManager.ConnectionCallback callback = createConnectionCallback(semaphore);
+        mSppManager.registerCallback(callback, mCallbackExecutor);
+        mSppManager.mConnectedTaskCallback.onDisconnected();
+        assertThat(tryAcquire(semaphore)).isTrue();
+        verify(callback).onRemoteDeviceDisconnected(any());
+    }
+
+    @NonNull
+    private SppManager.ConnectionCallback createConnectionCallback(
+            @NonNull final Semaphore semaphore) {
+        return spy(new SppManager.ConnectionCallback() {
+
+            @Override
+            public void onRemoteDeviceConnected(BluetoothDevice device) {
+                semaphore.release();
+            }
+
+            @Override
+            public void onRemoteDeviceDisconnected(BluetoothDevice device) {
+                semaphore.release();
+            }
+        });
+    }
+
+    @NonNull
+    private SppManager.OnMessageReceivedListener createOnMessageReceivedListener(
+            @NonNull final Semaphore semaphore) {
+        return spy((device, value) -> semaphore.release());
+    }
+
+    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
+        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppPayloadStreamTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppPayloadStreamTest.java
new file mode 100644
index 0000000..9f0b42b
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/connection/spp/SppPayloadStreamTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.connection.spp;
+
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+public class SppPayloadStreamTest {
+    private SppPayloadStream mSppPayloadStream;
+    private MockitoSession mMockitoSession;
+    private final byte[] mTestData = "testData".getBytes();
+    private byte[] mCompletedMessage = SppPayloadStream.wrapWithArrayLength(mTestData);
+    ;
+    private byte[] mCompletedMessageSplit1;
+    private byte[] mCompletedMessageSplit2;
+    @Mock
+    private SppPayloadStream.OnMessageCompletedListener mMockListener;
+
+
+    @Before
+    public void setUp() {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+        mSppPayloadStream = new SppPayloadStream();
+        mSppPayloadStream.setMessageCompletedListener(mMockListener);
+        int length = mCompletedMessage.length;
+        mCompletedMessageSplit1 = Arrays.copyOfRange(mCompletedMessage, 0, (length + 1) / 2);
+        mCompletedMessageSplit2 = Arrays.copyOfRange(mCompletedMessage, (length + 1) / 2, length);
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockitoSession != null) {
+            mMockitoSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void testWriteCompletedMessage_InformListener() throws IOException {
+        mSppPayloadStream.write(mCompletedMessage);
+        verify(mMockListener).onMessageCompleted(mTestData);
+    }
+
+    @Test
+    public void testWriteIncompleteMessage_DoNotInformListener() throws IOException {
+        mSppPayloadStream.write(mCompletedMessageSplit1);
+        verify(mMockListener, never()).onMessageCompleted(mTestData);
+    }
+
+    @Test
+    public void testWriteTwoMessage_InformListenerCompletedMessage() throws IOException {
+        mSppPayloadStream.write(mCompletedMessageSplit1);
+        mSppPayloadStream.write(mCompletedMessageSplit2);
+
+        verify(mMockListener).onMessageCompleted(mTestData);
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/oob/BluetoothRfcommChannelTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/oob/BluetoothRfcommChannelTest.java
new file mode 100644
index 0000000..9628afa
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/oob/BluetoothRfcommChannelTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.oob;
+
+
+import static com.android.car.connecteddevice.model.OobEligibleDevice.OOB_TYPE_BLUETOOTH;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mockitoSession;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.model.OobEligibleDevice;
+import com.android.car.connecteddevice.util.ByteUtils;
+
+import com.google.common.primitives.Bytes;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.UUID;
+
+@RunWith(AndroidJUnit4.class)
+public class BluetoothRfcommChannelTest {
+    private BluetoothRfcommChannel mBluetoothRfcommChannel;
+    private OobEligibleDevice mOobEligibleDevice;
+    @Mock
+    private OobChannel.Callback mMockCallback;
+    @Mock
+    private BluetoothAdapter mMockBluetoothAdapter;
+    @Mock
+    private BluetoothDevice mMockBluetoothDevice;
+    @Mock
+    private BluetoothSocket mMockBluetoothSocket;
+    @Mock
+    private OutputStream mMockOutputStream;
+
+    private MockitoSession mMockingSession;
+
+    @Before
+    public void setUp() {
+        mMockingSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.WARN)
+                .startMocking();
+
+
+        mBluetoothRfcommChannel = new BluetoothRfcommChannel();
+
+        mOobEligibleDevice = new OobEligibleDevice("00:11:22:33:44:55", OOB_TYPE_BLUETOOTH);
+
+        when(mMockBluetoothAdapter.getRemoteDevice(
+                mOobEligibleDevice.getDeviceAddress())).thenReturn(mMockBluetoothDevice);
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockingSession != null) {
+            mMockingSession.finishMocking();
+        }
+    }
+
+    @Test
+    public void completeOobExchange_success() throws Exception {
+        when(mMockBluetoothSocket.getOutputStream()).thenReturn(mMockOutputStream);
+        when(mMockBluetoothDevice.createRfcommSocketToServiceRecord(any(UUID.class))).thenReturn(
+                mMockBluetoothSocket);
+        mBluetoothRfcommChannel.completeOobDataExchange(mOobEligibleDevice, mMockCallback,
+                mMockBluetoothAdapter);
+
+        verify(mMockCallback, timeout(1000)).onOobExchangeSuccess();
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        oobConnectionManager.startOobExchange(mBluetoothRfcommChannel);
+
+        ArgumentCaptor<byte[]> oobDataCaptor = ArgumentCaptor.forClass(byte[].class);
+        verify(mMockOutputStream).write(oobDataCaptor.capture());
+        byte[] oobData = oobDataCaptor.getValue();
+
+        assertThat(oobData).isEqualTo(Bytes.concat(oobConnectionManager.mDecryptionIv,
+                oobConnectionManager.mEncryptionIv,
+                oobConnectionManager.mEncryptionKey.getEncoded()));
+    }
+
+    @Test
+    public void completeOobExchange_ioExceptionCausesRetry() throws Exception {
+        doThrow(IOException.class).doAnswer(invocation -> null)
+                .when(mMockBluetoothSocket).connect();
+        when(mMockBluetoothDevice.createRfcommSocketToServiceRecord(any(UUID.class))).thenReturn(
+                mMockBluetoothSocket);
+        mBluetoothRfcommChannel.completeOobDataExchange(mOobEligibleDevice, mMockCallback,
+                mMockBluetoothAdapter);
+        verify(mMockBluetoothSocket, timeout(3000).times(2)).connect();
+    }
+
+    @Test
+    public void completeOobExchange_createRfcommSocketFails_callOnFailed() throws Exception {
+        when(mMockBluetoothDevice.createRfcommSocketToServiceRecord(any(UUID.class))).thenThrow(
+                IOException.class);
+
+        mBluetoothRfcommChannel.completeOobDataExchange(mOobEligibleDevice, mMockCallback,
+                mMockBluetoothAdapter);
+        verify(mMockCallback).onOobExchangeFailure();
+    }
+
+    @Test
+    public void sendOobData_nullBluetoothDevice_callOnFailed() {
+        mBluetoothRfcommChannel.mCallback = mMockCallback;
+
+        mBluetoothRfcommChannel.sendOobData("someData".getBytes());
+        verify(mMockCallback).onOobExchangeFailure();
+    }
+
+    @Test
+    public void sendOobData_writeFails_callOnFailed() throws Exception {
+        byte[] testMessage = "testMessage".getBytes();
+        completeOobExchange_success();
+        doThrow(IOException.class).when(mMockOutputStream).write(testMessage);
+
+        mBluetoothRfcommChannel.sendOobData(testMessage);
+        verify(mMockCallback).onOobExchangeFailure();
+    }
+
+    @Test
+    public void interrupt_closesSocket() throws Exception {
+        when(mMockBluetoothSocket.getOutputStream()).thenReturn(mMockOutputStream);
+        when(mMockBluetoothDevice.createRfcommSocketToServiceRecord(any(UUID.class))).thenReturn(
+                mMockBluetoothSocket);
+        mBluetoothRfcommChannel.completeOobDataExchange(mOobEligibleDevice, mMockCallback,
+                mMockBluetoothAdapter);
+        mBluetoothRfcommChannel.interrupt();
+        mBluetoothRfcommChannel.sendOobData(ByteUtils.randomBytes(10));
+        verify(mMockOutputStream, times(0)).write(any());
+        verify(mMockOutputStream).flush();
+        verify(mMockOutputStream).close();
+    }
+
+    @Test
+    public void interrupt_preventsCallbacks() throws Exception {
+        when(mMockBluetoothSocket.getOutputStream()).thenReturn(mMockOutputStream);
+        when(mMockBluetoothDevice.createRfcommSocketToServiceRecord(any(UUID.class))).thenReturn(
+                mMockBluetoothSocket);
+        doAnswer(invocation -> {
+            mBluetoothRfcommChannel.interrupt();
+            return invocation.callRealMethod();
+        }).when(mMockBluetoothSocket).connect();
+        mBluetoothRfcommChannel.completeOobDataExchange(mOobEligibleDevice, mMockCallback,
+                mMockBluetoothAdapter);
+        verify(mMockCallback, times(0)).onOobExchangeSuccess();
+        verify(mMockCallback, times(0)).onOobExchangeFailure();
+    }
+}
diff --git a/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/oob/OobConnectionManagerTest.java b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/oob/OobConnectionManagerTest.java
new file mode 100644
index 0000000..13f93c9
--- /dev/null
+++ b/connected-device-lib/tests/unit/src/com/android/car/connecteddevice/oob/OobConnectionManagerTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2020 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.car.connecteddevice.oob;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.security.keystore.KeyProperties;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.connecteddevice.model.OobEligibleDevice;
+
+import com.google.common.primitives.Bytes;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+
+import javax.crypto.AEADBadTagException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+@RunWith(AndroidJUnit4.class)
+public class OobConnectionManagerTest {
+    private static final byte[] TEST_MESSAGE = "testMessage".getBytes();
+    private TestChannel mTestChannel;
+    private SecretKey mTestKey;
+    private byte[] mTestEncryptionIv = new byte[OobConnectionManager.NONCE_LENGTH_BYTES];
+    private byte[] mTestDecryptionIv = new byte[OobConnectionManager.NONCE_LENGTH_BYTES];
+    private byte[] mTestOobData;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestChannel = new TestChannel();
+        mTestKey = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES).generateKey();
+
+        SecureRandom secureRandom = new SecureRandom();
+        secureRandom.nextBytes(mTestEncryptionIv);
+        secureRandom.nextBytes(mTestDecryptionIv);
+
+        mTestOobData = Bytes.concat(mTestDecryptionIv, mTestEncryptionIv, mTestKey.getEncoded());
+    }
+
+    @Test
+    public void testInitAsServer_keyIsNull() {
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        assertThat(oobConnectionManager.mEncryptionKey).isNull();
+    }
+
+    @Test
+    public void testServer_onSetOobData_setsKeyAndNonce() {
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        oobConnectionManager.setOobData(mTestOobData);
+        assertThat(oobConnectionManager.mEncryptionKey).isEqualTo(mTestKey);
+        // The decryption IV for the server is the encryption IV for the client and vice versa
+        assertThat(oobConnectionManager.mDecryptionIv).isEqualTo(mTestEncryptionIv);
+        assertThat(oobConnectionManager.mEncryptionIv).isEqualTo(mTestDecryptionIv);
+    }
+
+    @Test
+    public void testInitAsClient_keyAndNoncesAreNonNullAndSent() {
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        oobConnectionManager.startOobExchange(mTestChannel);
+        assertThat(oobConnectionManager.mEncryptionKey).isNotNull();
+        assertThat(oobConnectionManager.mEncryptionIv).isNotNull();
+        assertThat(oobConnectionManager.mDecryptionIv).isNotNull();
+        assertThat(mTestChannel.mSentOobData).isEqualTo(Bytes.concat(
+                oobConnectionManager.mDecryptionIv,
+                oobConnectionManager.mEncryptionIv,
+                oobConnectionManager.mEncryptionKey.getEncoded()
+        ));
+    }
+
+    @Test
+    public void testServerEncryptAndClientDecrypt() throws Exception {
+        OobConnectionManager clientOobConnectionManager = new OobConnectionManager();
+        clientOobConnectionManager.startOobExchange(mTestChannel);
+        OobConnectionManager serverOobConnectionManager = new OobConnectionManager();
+        serverOobConnectionManager.setOobData(mTestChannel.mSentOobData);
+
+        byte[] encryptedTestMessage = clientOobConnectionManager.encryptVerificationCode(
+                TEST_MESSAGE);
+        byte[] decryptedTestMessage = serverOobConnectionManager.decryptVerificationCode(
+                encryptedTestMessage);
+
+        assertThat(decryptedTestMessage).isEqualTo(TEST_MESSAGE);
+    }
+
+    @Test
+    public void testClientEncryptAndServerDecrypt() throws Exception {
+        OobConnectionManager clientOobConnectionManager = new OobConnectionManager();
+        clientOobConnectionManager.startOobExchange(mTestChannel);
+        OobConnectionManager serverOobConnectionManager = new OobConnectionManager();
+        serverOobConnectionManager.setOobData(mTestChannel.mSentOobData);
+
+        byte[] encryptedTestMessage = serverOobConnectionManager.encryptVerificationCode(
+                TEST_MESSAGE);
+        byte[] decryptedTestMessage = clientOobConnectionManager.decryptVerificationCode(
+                encryptedTestMessage);
+
+        assertThat(decryptedTestMessage).isEqualTo(TEST_MESSAGE);
+    }
+
+    @Test
+    public void testEncryptAndDecryptWithDifferentNonces_throwsAEADBadTagException()
+            throws Exception {
+        // The OobConnectionManager stores a different nonce for encryption and decryption, so it
+        // can't decrypt messages that it encrypted itself. It can only send encrypted messages to
+        // an OobConnectionManager on another device that share its nonces and encryption key.
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        oobConnectionManager.startOobExchange(mTestChannel);
+        byte[] encryptedMessage = oobConnectionManager.encryptVerificationCode(TEST_MESSAGE);
+        assertThrows(AEADBadTagException.class,
+                () -> oobConnectionManager.decryptVerificationCode(encryptedMessage));
+    }
+
+    @Test
+    public void testDecryptWithShortMessage_throwsAEADBadTagException() {
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        oobConnectionManager.startOobExchange(mTestChannel);
+        assertThrows(AEADBadTagException.class,
+                () -> oobConnectionManager.decryptVerificationCode("short".getBytes()));
+    }
+
+    @Test
+    public void testEncryptWithNullKey_throwsInvalidKeyException() {
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        assertThrows(InvalidKeyException.class,
+                () -> oobConnectionManager.encryptVerificationCode(TEST_MESSAGE));
+    }
+
+    @Test
+    public void testDecryptWithNullKey_throwsInvalidKeyException() {
+        OobConnectionManager oobConnectionManager = new OobConnectionManager();
+        assertThrows(InvalidKeyException.class,
+                () -> oobConnectionManager.decryptVerificationCode(TEST_MESSAGE));
+    }
+
+    private static class TestChannel implements OobChannel {
+        byte[] mSentOobData = null;
+
+        @Override
+        public void completeOobDataExchange(OobEligibleDevice device, Callback callback) {
+
+        }
+
+        @Override
+        public void sendOobData(byte[] oobData) {
+            mSentOobData = oobData;
+        }
+
+        @Override
+        public void interrupt() {
+
+        }
+    }
+}
diff --git a/encryption-runner/Android.bp b/encryption-runner/Android.bp
index dde4aa8..c507c56 100644
--- a/encryption-runner/Android.bp
+++ b/encryption-runner/Android.bp
@@ -14,7 +14,8 @@
 
 android_library {
     name: "encryption-runner",
-    min_sdk_version: "23",
+    sdk_version: "current",
+    min_sdk_version: "28",
     product_variables: {
         pdk: {
             enabled: false,
diff --git a/encryption-runner/src/android/car/encryptionrunner/DummyEncryptionRunner.java b/encryption-runner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
deleted file mode 100644
index 39b14a6..0000000
--- a/encryption-runner/src/android/car/encryptionrunner/DummyEncryptionRunner.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2020 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 android.car.encryptionrunner;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * An encryption runner that doesn't actually do encryption. Useful for debugging. Do not use in
- * production environments.
- */
-@VisibleForTesting
-public class DummyEncryptionRunner implements EncryptionRunner {
-
-    private static final String KEY = "key";
-    private static final byte[] DUMMY_MESSAGE = "Dummy Message".getBytes();
-    @VisibleForTesting
-    public static final String INIT = "init";
-    @VisibleForTesting
-    public static final String INIT_RESPONSE = "initResponse";
-    @VisibleForTesting
-    public static final String CLIENT_RESPONSE = "clientResponse";
-    public static final String VERIFICATION_CODE = "1234";
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({Mode.UNKNOWN, Mode.CLIENT, Mode.SERVER})
-    private @interface Mode {
-
-        int UNKNOWN = 0;
-        int CLIENT = 1;
-        int SERVER = 2;
-    }
-
-    private boolean mIsReconnect;
-    private boolean mInitReconnectVerification;
-    private Key mCurrentDummyKey;
-    @Mode
-    private int mMode;
-    @HandshakeMessage.HandshakeState
-    private int mState;
-
-    @Override
-    public HandshakeMessage initHandshake() {
-        checkRunnerIsNew();
-        mMode = Mode.CLIENT;
-        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(mState)
-                .setNextMessage(INIT.getBytes())
-                .build();
-    }
-
-    @Override
-    public HandshakeMessage respondToInitRequest(byte[] initializationRequest)
-            throws HandshakeException {
-        checkRunnerIsNew();
-        mMode = Mode.SERVER;
-        if (!new String(initializationRequest).equals(INIT)) {
-            throw new HandshakeException("Unexpected initialization request");
-        }
-        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(HandshakeMessage.HandshakeState.IN_PROGRESS)
-                .setNextMessage(INIT_RESPONSE.getBytes())
-                .build();
-    }
-
-    private void checkRunnerIsNew() {
-        if (mState != HandshakeMessage.HandshakeState.UNKNOWN) {
-            throw new IllegalStateException("runner already initialized.");
-        }
-    }
-
-    @Override
-    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
-        if (mState != HandshakeMessage.HandshakeState.IN_PROGRESS) {
-            throw new HandshakeException("not waiting for response but got one");
-        }
-        switch (mMode) {
-            case Mode.SERVER:
-                if (!CLIENT_RESPONSE.equals(new String(response))) {
-                    throw new HandshakeException("unexpected response: " + new String(response));
-                }
-                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
-                if (mIsReconnect) {
-                    verifyPin();
-                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
-                }
-                return HandshakeMessage.newBuilder()
-                        .setVerificationCode(VERIFICATION_CODE)
-                        .setHandshakeState(mState)
-                        .build();
-            case Mode.CLIENT:
-                if (!INIT_RESPONSE.equals(new String(response))) {
-                    throw new HandshakeException("unexpected response: " + new String(response));
-                }
-                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
-                if (mIsReconnect) {
-                    verifyPin();
-                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
-                }
-                return HandshakeMessage.newBuilder()
-                        .setHandshakeState(mState)
-                        .setNextMessage(CLIENT_RESPONSE.getBytes())
-                        .setVerificationCode(VERIFICATION_CODE)
-                        .build();
-            default:
-                throw new IllegalStateException("unexpected role: " + mMode);
-        }
-    }
-
-    @Override
-    public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
-            throws HandshakeException {
-        mCurrentDummyKey = new DummyKey();
-        // Blindly verify the reconnection because this is a dummy encryption runner.
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
-                .setKey(mCurrentDummyKey)
-                .setNextMessage(mInitReconnectVerification ? null : DUMMY_MESSAGE)
-                .build();
-    }
-
-    @Override
-    public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
-            throws HandshakeException {
-        mInitReconnectVerification = true;
-        mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
-        return HandshakeMessage.newBuilder()
-                .setHandshakeState(mState)
-                .setNextMessage(DUMMY_MESSAGE)
-                .build();
-    }
-
-    @Override
-    public Key keyOf(byte[] serialized) {
-        return new DummyKey();
-    }
-
-    @Override
-    public HandshakeMessage verifyPin() throws HandshakeException {
-        if (mState != HandshakeMessage.HandshakeState.VERIFICATION_NEEDED) {
-            throw new IllegalStateException("asking to verify pin, state = " + mState);
-        }
-        mState = HandshakeMessage.HandshakeState.FINISHED;
-        return HandshakeMessage.newBuilder().setKey(new DummyKey()).setHandshakeState(
-                mState).build();
-    }
-
-    @Override
-    public void invalidPin() {
-        mState = HandshakeMessage.HandshakeState.INVALID;
-    }
-
-    @Override
-    public void setIsReconnect(boolean isReconnect) {
-        mIsReconnect = isReconnect;
-    }
-
-    /** Method to throw a HandshakeException for testing. */
-    public static void throwHandshakeException(String message) throws HandshakeException {
-        throw new HandshakeException(message);
-    }
-
-    private class DummyKey implements Key {
-        @Override
-        public byte[] asBytes() {
-            return KEY.getBytes();
-        }
-
-        @Override
-        public byte[] encryptData(byte[] data) {
-            return data;
-        }
-
-        @Override
-        public byte[] decryptData(byte[] encryptedData) {
-            return encryptedData;
-        }
-
-        @Override
-        public byte[] getUniqueSession() {
-            return KEY.getBytes();
-        }
-    }
-}
diff --git a/encryption-runner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java b/encryption-runner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java
index be6cd68..b479b50 100644
--- a/encryption-runner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java
+++ b/encryption-runner/src/android/car/encryptionrunner/EncryptionRunnerFactory.java
@@ -28,10 +28,12 @@
         // prevent instantiation.
     }
 
-    @IntDef({EncryptionRunnerType.UKEY2})
+    @IntDef({EncryptionRunnerType.UKEY2, EncryptionRunnerType.OOB_UKEY2})
     public @interface EncryptionRunnerType {
         /** Use Ukey2 as underlying key exchange. */
         int UKEY2 = 0;
+        /** Use Ukey2 and an out of band channel as underlying key exchange. */
+        int OOB_UKEY2 = 1;
     }
 
     /**
@@ -41,6 +43,8 @@
         switch (type) {
             case EncryptionRunnerType.UKEY2:
                 return new Ukey2EncryptionRunner();
+            case EncryptionRunnerType.OOB_UKEY2:
+                return new OobUkey2EncryptionRunner();
             default:
                 throw new IllegalArgumentException("Unknown EncryptionRunnerType: " + type);
         }
@@ -61,7 +65,16 @@
      * for testing.
      */
     @VisibleForTesting
-    public static EncryptionRunner newDummyRunner() {
-        return new DummyEncryptionRunner();
+    public static EncryptionRunner newFakeRunner() {
+        return new FakeEncryptionRunner();
+    }
+
+    /**
+     * Creates a new {@link EncryptionRunner} that doesn't actually do encryption but is useful
+     * for out of band association testing.
+     */
+    @VisibleForTesting
+    public static EncryptionRunner newOobFakeRunner() {
+        return new OobFakeEncryptionRunner();
     }
 }
diff --git a/encryption-runner/src/android/car/encryptionrunner/FakeEncryptionRunner.java b/encryption-runner/src/android/car/encryptionrunner/FakeEncryptionRunner.java
new file mode 100644
index 0000000..5fd1ff2
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/FakeEncryptionRunner.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2020 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 android.car.encryptionrunner;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An encryption runner that doesn't actually do encryption. Useful for debugging. Do not use in
+ * production environments.
+ */
+@VisibleForTesting
+public class FakeEncryptionRunner implements EncryptionRunner {
+
+    private static final String KEY = "key";
+    private static final byte[] PLACEHOLDER_MESSAGE = "Placeholder Message".getBytes();
+    @VisibleForTesting
+    public static final String INIT = "init";
+    @VisibleForTesting
+    public static final String INIT_RESPONSE = "initResponse";
+    @VisibleForTesting
+    public static final String CLIENT_RESPONSE = "clientResponse";
+    public static final String VERIFICATION_CODE = "1234";
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({Mode.UNKNOWN, Mode.CLIENT, Mode.SERVER})
+    @interface Mode {
+
+        int UNKNOWN = 0;
+        int CLIENT = 1;
+        int SERVER = 2;
+    }
+
+    private boolean mIsReconnect;
+    private boolean mInitReconnectVerification;
+    private Key mCurrentFakeKey;
+    @Mode
+    private int mMode;
+    @HandshakeMessage.HandshakeState
+    private int mState;
+
+    @Override
+    public HandshakeMessage initHandshake() {
+        checkRunnerIsNew();
+        mMode = Mode.CLIENT;
+        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(mState)
+                .setNextMessage(INIT.getBytes())
+                .build();
+    }
+
+    @Override
+    public HandshakeMessage respondToInitRequest(byte[] initializationRequest)
+            throws HandshakeException {
+        checkRunnerIsNew();
+        mMode = Mode.SERVER;
+        if (!new String(initializationRequest).equals(INIT)) {
+            throw new HandshakeException("Unexpected initialization request");
+        }
+        mState = HandshakeMessage.HandshakeState.IN_PROGRESS;
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(HandshakeMessage.HandshakeState.IN_PROGRESS)
+                .setNextMessage(INIT_RESPONSE.getBytes())
+                .build();
+    }
+
+    @Mode
+    protected int getMode() {
+        return mMode;
+    }
+
+    @HandshakeMessage.HandshakeState
+    protected int getState() {
+        return mState;
+    }
+
+    protected void setState(@HandshakeMessage.HandshakeState int state) {
+        mState = state;
+    }
+
+    private void checkRunnerIsNew() {
+        if (mState != HandshakeMessage.HandshakeState.UNKNOWN) {
+            throw new IllegalStateException("runner already initialized.");
+        }
+    }
+
+    @Override
+    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
+        if (mState != HandshakeMessage.HandshakeState.IN_PROGRESS) {
+            throw new HandshakeException("not waiting for response but got one");
+        }
+        switch (mMode) {
+            case Mode.SERVER:
+                if (!CLIENT_RESPONSE.equals(new String(response))) {
+                    throw new HandshakeException("unexpected response: " + new String(response));
+                }
+                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
+                if (mIsReconnect) {
+                    verifyPin();
+                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+                }
+                return HandshakeMessage.newBuilder()
+                        .setVerificationCode(VERIFICATION_CODE)
+                        .setHandshakeState(mState)
+                        .build();
+            case Mode.CLIENT:
+                if (!INIT_RESPONSE.equals(new String(response))) {
+                    throw new HandshakeException("unexpected response: " + new String(response));
+                }
+                mState = HandshakeMessage.HandshakeState.VERIFICATION_NEEDED;
+                if (mIsReconnect) {
+                    verifyPin();
+                    mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+                }
+                return HandshakeMessage.newBuilder()
+                        .setHandshakeState(mState)
+                        .setNextMessage(CLIENT_RESPONSE.getBytes())
+                        .setVerificationCode(VERIFICATION_CODE)
+                        .build();
+            default:
+                throw new IllegalStateException("unexpected role: " + mMode);
+        }
+    }
+
+    @Override
+    public HandshakeMessage authenticateReconnection(byte[] message, byte[] previousKey)
+            throws HandshakeException {
+        mCurrentFakeKey = new FakeKey();
+        // Blindly verify the reconnection because this is a fake encryption runner.
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(HandshakeMessage.HandshakeState.FINISHED)
+                .setKey(mCurrentFakeKey)
+                .setNextMessage(mInitReconnectVerification ? null : PLACEHOLDER_MESSAGE)
+                .build();
+    }
+
+    @Override
+    public HandshakeMessage initReconnectAuthentication(byte[] previousKey)
+            throws HandshakeException {
+        mInitReconnectVerification = true;
+        mState = HandshakeMessage.HandshakeState.RESUMING_SESSION;
+        return HandshakeMessage.newBuilder()
+                .setHandshakeState(mState)
+                .setNextMessage(PLACEHOLDER_MESSAGE)
+                .build();
+    }
+
+    @Override
+    public Key keyOf(byte[] serialized) {
+        return new FakeKey();
+    }
+
+    @Override
+    public HandshakeMessage verifyPin() throws HandshakeException {
+        if (mState != HandshakeMessage.HandshakeState.VERIFICATION_NEEDED) {
+            throw new IllegalStateException("asking to verify pin, state = " + mState);
+        }
+        mState = HandshakeMessage.HandshakeState.FINISHED;
+        return HandshakeMessage.newBuilder().setKey(new FakeKey()).setHandshakeState(
+                mState).build();
+    }
+
+    @Override
+    public void invalidPin() {
+        mState = HandshakeMessage.HandshakeState.INVALID;
+    }
+
+    @Override
+    public void setIsReconnect(boolean isReconnect) {
+        mIsReconnect = isReconnect;
+    }
+
+    /** Method to throw a HandshakeException for testing. */
+    public static void throwHandshakeException(String message) throws HandshakeException {
+        throw new HandshakeException(message);
+    }
+
+    class FakeKey implements Key {
+        @Override
+        public byte[] asBytes() {
+            return KEY.getBytes();
+        }
+
+        @Override
+        public byte[] encryptData(byte[] data) {
+            return data;
+        }
+
+        @Override
+        public byte[] decryptData(byte[] encryptedData) {
+            return encryptedData;
+        }
+
+        @Override
+        public byte[] getUniqueSession() {
+            return KEY.getBytes();
+        }
+    }
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/OobFakeEncryptionRunner.java b/encryption-runner/src/android/car/encryptionrunner/OobFakeEncryptionRunner.java
new file mode 100644
index 0000000..3ab17d2
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/OobFakeEncryptionRunner.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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 android.car.encryptionrunner;
+
+/**
+ * An encryption runner that doesn't actually do encryption. Useful for debugging out of band
+ * association. Do not use in production environments.
+ */
+public class OobFakeEncryptionRunner extends FakeEncryptionRunner {
+
+    @Override
+    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
+        if (getState() != HandshakeMessage.HandshakeState.IN_PROGRESS) {
+            throw new HandshakeException("not waiting for response but got one");
+        }
+
+        @HandshakeMessage.HandshakeState int newState =
+                HandshakeMessage.HandshakeState.OOB_VERIFICATION_NEEDED;
+        switch (getMode()) {
+            case Mode.SERVER:
+                if (!CLIENT_RESPONSE.equals(new String(response))) {
+                    throw new HandshakeException("unexpected response: " + new String(response));
+                }
+                setState(newState);
+                return HandshakeMessage.newBuilder()
+                        .setOobVerificationCode(VERIFICATION_CODE.getBytes())
+                        .setHandshakeState(newState)
+                        .build();
+            case Mode.CLIENT:
+                if (!INIT_RESPONSE.equals(new String(response))) {
+                    throw new HandshakeException("unexpected response: " + new String(response));
+                }
+                setState(newState);
+                return HandshakeMessage.newBuilder()
+                        .setHandshakeState(newState)
+                        .setNextMessage(CLIENT_RESPONSE.getBytes())
+                        .setOobVerificationCode(VERIFICATION_CODE.getBytes())
+                        .build();
+            default:
+                throw new IllegalStateException("unexpected role: " + getMode());
+        }
+    }
+
+    @Override
+    public HandshakeMessage verifyPin() throws HandshakeException {
+        @HandshakeMessage.HandshakeState int state = getState();
+        if (state != HandshakeMessage.HandshakeState.OOB_VERIFICATION_NEEDED) {
+            throw new IllegalStateException("asking to verify pin, state = " + state);
+        }
+        state = HandshakeMessage.HandshakeState.FINISHED;
+        return HandshakeMessage.newBuilder().setKey(new FakeKey()).setHandshakeState(
+                state).build();
+    }
+}
diff --git a/encryption-runner/src/android/car/encryptionrunner/OobUkey2EncryptionRunner.java b/encryption-runner/src/android/car/encryptionrunner/OobUkey2EncryptionRunner.java
new file mode 100644
index 0000000..9474bd4
--- /dev/null
+++ b/encryption-runner/src/android/car/encryptionrunner/OobUkey2EncryptionRunner.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2020 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 android.car.encryptionrunner;
+
+import com.google.security.cryptauth.lib.securegcm.Ukey2Handshake;
+
+/**
+ * An {@link EncryptionRunner} that uses Ukey2 as the underlying implementation, and generates a
+ * longer token for the out of band verification step.
+ *
+ * <p>To use this class:
+ *
+ * <p>1. As a client.
+ *
+ * <p>{@code
+ * HandshakeMessage initialClientMessage = clientRunner.initHandshake();
+ * sendToServer(initialClientMessage.getNextMessage());
+ * byte message = getServerResponse();
+ * HandshakeMessage message = clientRunner.continueHandshake(message);
+ * }
+ *
+ * <p>If it is a first-time connection,
+ *
+ * <p>{@code message.getHandshakeState()} should be OOB_VERIFICATION_NEEDED. Wait for an encrypted
+ * message sent from the server, and decrypt that message with an out of band key that was generated
+ * before the start of the handshake.
+ *
+ * <p>After confirming that the decrypted message matches the verification code, send an encrypted
+ * message back to the server, and call {@code HandshakeMessage lastMessage =
+ * clientRunner.verifyPin();} otherwise {@code clientRunner.invalidPin(); }
+ *
+ * <p>Use {@code lastMessage.getKey()} to get the key for encryption.
+ *
+ * <p>If it is a reconnection,
+ *
+ * <p>{@code message.getHandshakeState()} should be RESUMING_SESSION, PIN has been verified blindly,
+ * send the authentication message over to server, then authenticate the message from server.
+ *
+ * <p>{@code
+ * clientMessage = clientRunner.initReconnectAuthentication(previousKey)
+ * sendToServer(clientMessage.getNextMessage());
+ * HandshakeMessage lastMessage = clientRunner.authenticateReconnection(previousKey, message)
+ * }
+ *
+ * <p>{@code lastMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
+ *
+ * <p>2. As a server.
+ *
+ * <p>{@code
+ * byte[] initialMessage = getClientMessageBytes();
+ * HandshakeMessage message = serverRunner.respondToInitRequest(initialMessage);
+ * sendToClient(message.getNextMessage());
+ * byte[] clientMessage = getClientResponse();
+ * HandshakeMessage message = serverRunner.continueHandshake(clientMessage);}
+ *
+ * <p>if it is a first-time connection,
+ *
+ * <p>{@code message.getHandshakeState()} should be OOB_VERIFICATION_NEEDED, send the verification
+ * code to the client, encrypted using an out of band key generated before the start of the
+ * handshake, and wait for a response from the client.
+ * If the decrypted message from the client matches the verification code, call {@code
+ * HandshakeMessage lastMessage = serverRunner.verifyPin}, otherwise
+ * {@code clientRunner.invalidPin(); }
+ * Use {@code lastMessage.getKey()} to get the key for encryption.
+ *
+ * <p>If it is a reconnection,
+ *
+ * <p>{@code message.getHandshakeState()} should be RESUMING_SESSION,PIN has been verified blindly,
+ * waiting for client message.
+ * After client message been received,
+ * {@code serverMessage = serverRunner.authenticateReconnection(previousKey, message);
+ * sendToClient(serverMessage.getNextMessage());}
+ * {@code serverMessage.getHandshakeState()} should be FINISHED if reconnection handshake is done.
+ *
+ * <p>Also see {@link EncryptionRunnerTest} for examples.
+ */
+public final class OobUkey2EncryptionRunner extends Ukey2EncryptionRunner {
+    // Choose max verification string length supported by Ukey2
+    private static final int VERIFICATION_STRING_LENGTH = 32;
+
+    @Override
+    public HandshakeMessage continueHandshake(byte[] response) throws HandshakeException {
+        checkInitialized();
+
+        Ukey2Handshake uKey2Client = getUkey2Client();
+
+        try {
+            if (uKey2Client.getHandshakeState() != Ukey2Handshake.State.IN_PROGRESS) {
+                throw new IllegalStateException(
+                        "handshake is not in progress, state =" + uKey2Client.getHandshakeState());
+            }
+            uKey2Client.parseHandshakeMessage(response);
+
+            // Not obvious from ukey2 api, but getting the next message can change the state.
+            // calling getNext message might go from in progress to verification needed, on
+            // the assumption that we already send this message to the peer.
+            byte[] nextMessage = null;
+            if (uKey2Client.getHandshakeState() == Ukey2Handshake.State.IN_PROGRESS) {
+                nextMessage = uKey2Client.getNextHandshakeMessage();
+            }
+
+            byte[] verificationCode = null;
+            if (uKey2Client.getHandshakeState() == Ukey2Handshake.State.VERIFICATION_NEEDED) {
+                // getVerificationString() needs to be called before notifyPinVerified().
+                verificationCode = uKey2Client.getVerificationString(VERIFICATION_STRING_LENGTH);
+                if (isReconnect()) {
+                    HandshakeMessage handshakeMessage = verifyPin();
+                    return HandshakeMessage.newBuilder()
+                            .setHandshakeState(handshakeMessage.getHandshakeState())
+                            .setNextMessage(nextMessage)
+                            .build();
+                }
+            }
+
+            return HandshakeMessage.newBuilder()
+                    .setHandshakeState(HandshakeMessage.HandshakeState.OOB_VERIFICATION_NEEDED)
+                    .setNextMessage(nextMessage)
+                    .setOobVerificationCode(verificationCode)
+                    .build();
+        } catch (com.google.security.cryptauth.lib.securegcm.HandshakeException
+                | Ukey2Handshake.AlertException e) {
+            throw new HandshakeException(e);
+        }
+    }
+}
diff --git a/glide/Android.mk b/glide/Android.mk
deleted file mode 100644
index 41e3937..0000000
--- a/glide/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Copyright (C) 2018 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-glide-disklrucache
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/disklrucache/SNAPSHOT/disklrucache-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_NOTICE_FILE := prebuilts/maven_repo/bumptech/LICENSE
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-gifdecoder
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/gifdecoder/SNAPSHOT/gifdecoder-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_NOTICE_FILE := prebuilts/maven_repo/bumptech/LICENSE
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := car-glide
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := ../../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/glide/SNAPSHOT/glide-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_NOTICE_FILE := prebuilts/maven_repo/bumptech/LICENSE
-LOCAL_JETIFIER_ENABLED := true
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_PREBUILT)
\ No newline at end of file