Add overflow support to Chassis toolbar

Fixes: 140432159
Test: Manually

Change-Id: I7c374ee3a9e513e24d2c4f35fdf36ec7468bcb5c
diff --git a/car-chassis-lib/res/values-port/dimens.xml b/car-chassis-lib/res/color/chassis_toolbar_icon_tint.xml
similarity index 72%
rename from car-chassis-lib/res/values-port/dimens.xml
rename to car-chassis-lib/res/color/chassis_toolbar_icon_tint.xml
index 543e63b..e8fc154 100644
--- a/car-chassis-lib/res/values-port/dimens.xml
+++ b/car-chassis-lib/res/color/chassis_toolbar_icon_tint.xml
@@ -14,6 +14,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<resources>
-    <dimen name="chassis_toolbar_second_row_height">@dimen/chassis_app_bar_height</dimen>
-</resources>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/chassis_tab_selected_color" android:state_enabled="true"/>
+    <item android:color="@color/chassis_tab_unselected_color"/>
+</selector>
diff --git a/car-chassis-lib/res/drawable/chassis_icon_overflow_menu.xml b/car-chassis-lib/res/drawable/chassis_icon_overflow_menu.xml
new file mode 100644
index 0000000..6228c3b
--- /dev/null
+++ b/car-chassis-lib/res/drawable/chassis_icon_overflow_menu.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="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
+</vector>
diff --git a/car-chassis-lib/res/drawable/chassis_pagedrecyclerview_button_ripple_background.xml b/car-chassis-lib/res/drawable/chassis_pagedrecyclerview_button_ripple_background.xml
index b5f107c..988ac74 100644
--- a/car-chassis-lib/res/drawable/chassis_pagedrecyclerview_button_ripple_background.xml
+++ b/car-chassis-lib/res/drawable/chassis_pagedrecyclerview_button_ripple_background.xml
@@ -17,4 +17,4 @@
 
 <ripple
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/chassis_card_ripple_background" />
+    android:color="@color/chassis_ripple_color" />
diff --git a/car-chassis-lib/res/drawable/chassis_toolbar_button_background.xml b/car-chassis-lib/res/drawable/chassis_toolbar_icon_background.xml
similarity index 84%
rename from car-chassis-lib/res/drawable/chassis_toolbar_button_background.xml
rename to car-chassis-lib/res/drawable/chassis_toolbar_icon_background.xml
index efa63b9..eda49c2 100644
--- a/car-chassis-lib/res/drawable/chassis_toolbar_button_background.xml
+++ b/car-chassis-lib/res/drawable/chassis_toolbar_icon_background.xml
@@ -17,5 +17,5 @@
   ~
  -->
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@color/chassis_card_ripple_background"
-        android:radius="@dimen/chassis_toolbar_button_background_radius"/>
+        android:color="@color/chassis_ripple_color"
+        android:radius="@dimen/chassis_toolbar_icon_ripple_radius"/>
diff --git a/car-chassis-lib/res/layout-port/chassis_toolbar.xml b/car-chassis-lib/res/layout-port/chassis_toolbar.xml
index 48cacb3..327abe9 100644
--- a/car-chassis-lib/res/layout-port/chassis_toolbar.xml
+++ b/car-chassis-lib/res/layout-port/chassis_toolbar.xml
@@ -57,7 +57,7 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@id/row_separator"
         app:layout_constraintStart_toEndOf="@id/nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@id/buttons_container"/>
+        app:layout_constraintEnd_toStartOf="@id/menu_items_container"/>
 
     <com.android.car.chassis.SearchView
         android:id="@+id/search_view"
@@ -67,7 +67,7 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@id/row_separator"
         app:layout_constraintStart_toEndOf="@id/nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@id/buttons_container"/>
+        app:layout_constraintEnd_toStartOf="@id/menu_items_container"/>
 
     <FrameLayout
         android:id="@+id/custom_view_container"
@@ -77,16 +77,36 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@id/row_separator"
         app:layout_constraintStart_toEndOf="@id/nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@id/buttons_container"/>
+        app:layout_constraintEnd_toStartOf="@id/menu_items_container"/>
 
     <LinearLayout
-        android:id="@+id/buttons_container"
+        android:id="@+id/menu_items_container"
         android:layout_width="wrap_content"
         android:layout_height="0dp"
         android:orientation="horizontal"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@id/row_separator"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        app:layout_constraintEnd_toStartOf="@id/chassis_toolbar_overflow_button"/>
+
+    <FrameLayout
+        android:id="@+id/chassis_toolbar_overflow_button"
+        android:layout_width="@dimen/chassis_touch_target_width"
+        android:layout_height="@dimen/chassis_touch_target_height"
+        android:layout_marginLeft="@dimen/chassis_toolbar_menu_item_margin"
+        android:layout_marginRight="@dimen/chassis_toolbar_menu_item_margin"
+        android:visibility="gone"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/row_separator"
+        app:layout_constraintEnd_toEndOf="parent">
+        <ImageView
+            android:src="@drawable/chassis_icon_overflow_menu"
+            android:layout_width="@dimen/chassis_primary_icon_size"
+            android:layout_height="@dimen/chassis_primary_icon_size"
+            android:layout_gravity="center"
+            android:background="@drawable/chassis_toolbar_icon_background"
+            android:tint="@color/chassis_toolbar_icon_tint"
+            android:tintMode="src_in"/>
+    </FrameLayout>
 
     <com.android.car.chassis.TabLayout
         android:id="@+id/tabs"
diff --git a/car-chassis-lib/res/layout/chassis_search_view.xml b/car-chassis-lib/res/layout/chassis_search_view.xml
index 7decb3a..71548f2 100644
--- a/car-chassis-lib/res/layout/chassis_search_view.xml
+++ b/car-chassis-lib/res/layout/chassis_search_view.xml
@@ -48,7 +48,7 @@
         android:id="@+id/search_close"
         android:layout_width="@dimen/chassis_touch_target_width"
         android:layout_height="@dimen/chassis_touch_target_height"
-        android:background="@drawable/chassis_toolbar_button_background"
+        android:background="@drawable/chassis_toolbar_icon_background"
         android:src="@drawable/chassis_icon_close"
         android:scaleType="center"
         app:layout_constraintTop_toTopOf="parent"
diff --git a/car-chassis-lib/res/layout/chassis_toolbar.xml b/car-chassis-lib/res/layout/chassis_toolbar.xml
index 57056fb..8a5b6bc 100644
--- a/car-chassis-lib/res/layout/chassis_toolbar.xml
+++ b/car-chassis-lib/res/layout/chassis_toolbar.xml
@@ -43,17 +43,17 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@+id/bottom_styleable"
         app:layout_constraintStart_toEndOf="@+id/nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/buttons_container"/>
+        app:layout_constraintEnd_toStartOf="@+id/menu_items_container"/>
 
     <com.android.car.chassis.TabLayout
         android:id="@+id/tabs"
         android:layout_width="wrap_content"
         android:layout_height="0dp"
-        android:layout_marginEnd="@dimen/chassis_toolbar_custom_button_margin"
+        android:layout_marginEnd="@dimen/chassis_toolbar_menu_item_margin"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@+id/bottom_styleable"
         app:layout_constraintStart_toEndOf="@+id/nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/buttons_container"
+        app:layout_constraintEnd_toStartOf="@+id/menu_items_container"
         app:layout_constraintHorizontal_bias="0.0"/>
 
     <FrameLayout
@@ -64,16 +64,36 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@+id/bottom_styleable"
         app:layout_constraintStart_toEndOf="@+id/nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/buttons_container"/>
+        app:layout_constraintEnd_toStartOf="@+id/menu_items_container"/>
 
     <LinearLayout
-        android:id="@+id/buttons_container"
+        android:id="@+id/menu_items_container"
         android:layout_width="wrap_content"
         android:layout_height="0dp"
         android:orientation="horizontal"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@+id/bottom_styleable"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        app:layout_constraintEnd_toStartOf="@id/chassis_toolbar_overflow_button"/>
+
+    <FrameLayout
+        android:id="@+id/chassis_toolbar_overflow_button"
+        android:layout_width="@dimen/chassis_touch_target_width"
+        android:layout_height="@dimen/chassis_touch_target_height"
+        android:layout_marginLeft="@dimen/chassis_toolbar_menu_item_margin"
+        android:layout_marginRight="@dimen/chassis_toolbar_menu_item_margin"
+        android:visibility="gone"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/bottom_styleable"
+        app:layout_constraintEnd_toEndOf="parent">
+        <ImageView
+            android:src="@drawable/chassis_icon_overflow_menu"
+            android:layout_width="@dimen/chassis_primary_icon_size"
+            android:layout_height="@dimen/chassis_primary_icon_size"
+            android:layout_gravity="center"
+            android:background="@drawable/chassis_toolbar_icon_background"
+            android:tint="@color/chassis_toolbar_icon_tint"
+            android:tintMode="src_in"/>
+    </FrameLayout>
 
     <com.android.car.chassis.SearchView
         android:id="@+id/search_view"
@@ -83,7 +103,7 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@+id/bottom_styleable"
         app:layout_constraintStart_toEndOf="@+id/nav_icon_container"
-        app:layout_constraintEnd_toStartOf="@+id/buttons_container"/>
+        app:layout_constraintEnd_toStartOf="@+id/menu_items_container"/>
 
     <View
         android:id="@+id/bottom_styleable"
diff --git a/car-chassis-lib/res/layout/chassis_toolbar_menu_item_icon.xml b/car-chassis-lib/res/layout/chassis_toolbar_menu_item_icon.xml
new file mode 100644
index 0000000..690147e
--- /dev/null
+++ b/car-chassis-lib/res/layout/chassis_toolbar_menu_item_icon.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"
+    android:layout_width="@dimen/chassis_touch_target_width"
+    android:layout_height="@dimen/chassis_touch_target_height"
+    android:layout_marginLeft="@dimen/chassis_toolbar_menu_item_margin"
+    android:layout_marginRight="@dimen/chassis_toolbar_menu_item_margin"
+    android:layout_gravity="center_vertical">
+    <ImageView
+        android:id="@+id/chassis_toolbar_menu_item_icon"
+        android:layout_width="@dimen/chassis_primary_icon_size"
+        android:layout_height="@dimen/chassis_primary_icon_size"
+        android:layout_gravity="center"
+        android:background="@drawable/chassis_toolbar_icon_background"
+        android:tint="@color/chassis_toolbar_icon_tint"
+        android:tintMode="src_in"/>
+</FrameLayout>
diff --git a/car-chassis-lib/res/layout/chassis_toolbar_search_button.xml b/car-chassis-lib/res/layout/chassis_toolbar_menu_item_switch.xml
similarity index 64%
rename from car-chassis-lib/res/layout/chassis_toolbar_search_button.xml
rename to car-chassis-lib/res/layout/chassis_toolbar_menu_item_switch.xml
index e42e4ce..1528ca5 100644
--- a/car-chassis-lib/res/layout/chassis_toolbar_search_button.xml
+++ b/car-chassis-lib/res/layout/chassis_toolbar_menu_item_switch.xml
@@ -14,11 +14,17 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<ImageView
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/search"
     android:layout_width="@dimen/chassis_touch_target_width"
     android:layout_height="@dimen/chassis_touch_target_height"
-    android:src="@drawable/chassis_icon_search"
-    android:scaleType="center"
-    android:background="@drawable/chassis_toolbar_button_background"/>
+    android:layout_marginLeft="@dimen/chassis_toolbar_menu_item_margin"
+    android:layout_marginRight="@dimen/chassis_toolbar_menu_item_margin"
+    android:layout_gravity="center_vertical">
+    <Switch
+        android:id="@+id/chassis_toolbar_menu_item_switch"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:clickable="false"/>
+</FrameLayout>
diff --git a/car-chassis-lib/res/layout/chassis_toolbar_search_button.xml b/car-chassis-lib/res/layout/chassis_toolbar_menu_item_text.xml
similarity index 64%
copy from car-chassis-lib/res/layout/chassis_toolbar_search_button.xml
copy to car-chassis-lib/res/layout/chassis_toolbar_menu_item_text.xml
index e42e4ce..cc71e12 100644
--- a/car-chassis-lib/res/layout/chassis_toolbar_search_button.xml
+++ b/car-chassis-lib/res/layout/chassis_toolbar_menu_item_text.xml
@@ -14,11 +14,12 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<ImageView
+<Button
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/search"
-    android:layout_width="@dimen/chassis_touch_target_width"
-    android:layout_height="@dimen/chassis_touch_target_height"
-    android:src="@drawable/chassis_icon_search"
-    android:scaleType="center"
-    android:background="@drawable/chassis_toolbar_button_background"/>
+    android:id="@+id/chassis_toolbar_menu_item_text"
+    style="@style/ChassisToolbarTextButtonStyle"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:layout_marginLeft="@dimen/chassis_toolbar_menu_item_margin"
+    android:layout_marginRight="@dimen/chassis_toolbar_menu_item_margin"
+    android:layout_gravity="center_vertical"/>
diff --git a/car-chassis-lib/res/layout/chassis_toolbar_settings_button.xml b/car-chassis-lib/res/layout/chassis_toolbar_settings_button.xml
deleted file mode 100644
index f044099..0000000
--- a/car-chassis-lib/res/layout/chassis_toolbar_settings_button.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.
--->
-<ImageView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/settings"
-    android:layout_width="@dimen/chassis_touch_target_width"
-    android:layout_height="@dimen/chassis_touch_target_height"
-    android:src="@drawable/chassis_icon_settings"
-    android:scaleType="center"
-    android:background="@drawable/chassis_toolbar_button_background"/>
diff --git a/car-chassis-lib/res/values/attrs.xml b/car-chassis-lib/res/values/attrs.xml
index 4caf70b..bab87ad 100644
--- a/car-chassis-lib/res/values/attrs.xml
+++ b/car-chassis-lib/res/values/attrs.xml
@@ -21,10 +21,8 @@
         <attr name="logo" format="reference"/>
         <!-- Hint for the search bar in the toolbar -->
         <attr name="searchHint" format="string"/>
-        <!-- Buttons to display, as an array of layout ids. Use @layout/chassis_toolbar_search_button and @layout/chassis_toolbar_settings_button for the search and settings buttons -->
-        <attr name="buttons" format="reference"/>
-        <!-- Whether or not to show the custom buttons while searching. If using chassis_toolbar_search_button, or any other layout with a view with the id of "search", it will always be hidden. -->
-        <attr name="showButtonsWhileSearching" format="boolean"/>
+        <!-- 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"/>
diff --git a/car-chassis-lib/res/values/colors.xml b/car-chassis-lib/res/values/colors.xml
index caf7266..4882df5 100644
--- a/car-chassis-lib/res/values/colors.xml
+++ b/car-chassis-lib/res/values/colors.xml
@@ -20,8 +20,8 @@
     <color name="chassis_primary_text_color">#FFFFFFFF</color>
     <!-- Text color used in subtitles or other secondary text blocks -->
     <color name="chassis_secondary_text_color">#90FFFFFF</color>
-    <!-- The ripple color for a card. -->
-    <color name="chassis_card_ripple_background">#27ffffff</color>
+    <!-- The ripple color. -->
+    <color name="chassis_ripple_color">#27ffffff</color>
 
     <!-- Tabs -->
 
diff --git a/car-chassis-lib/res/values/dimens.xml b/car-chassis-lib/res/values/dimens.xml
index d299edc..1d45143 100644
--- a/car-chassis-lib/res/values/dimens.xml
+++ b/car-chassis-lib/res/values/dimens.xml
@@ -22,9 +22,6 @@
     <item name="chassis_letter_spacing_body1" format="float" type="dimen">0.0</item>
     <item name="chassis_letter_spacing_body3" format="float" type="dimen">0.0</item>
 
-    <!-- Application Bar -->
-    <dimen name="chassis_app_bar_height">80dp</dimen>
-
     <!-- Margin -->
     <dimen name="chassis_margin">112dp</dimen>
 
@@ -49,13 +46,14 @@
     <dimen name="chassis_tab_icon_height">36dp</dimen>
 
     <!-- Car toolbar -->
-    <dimen name="chassis_toolbar_view_nav_button_width">@dimen/chassis_margin</dimen>
-    <dimen name="chassis_toolbar_first_row_height">@dimen/chassis_app_bar_height</dimen>
-    <dimen name="chassis_toolbar_second_row_height">0dp</dimen>
-    <dimen name="chassis_toolbar_view_icon_size">@dimen/chassis_primary_icon_size</dimen>
-    <dimen name="chassis_toolbar_view_title_margin_start">@dimen/chassis_padding_2</dimen>
-    <dimen name="chassis_toolbar_custom_button_margin">@dimen/chassis_padding_2</dimen>
-    <dimen name="chassis_toolbar_button_background_radius">48dp</dimen>
+    <dimen name="chassis_toolbar_row_height">96dp</dimen>
+    <dimen name="chassis_toolbar_first_row_height">@dimen/chassis_toolbar_row_height</dimen>
+    <dimen name="chassis_toolbar_second_row_height">@dimen/chassis_toolbar_row_height</dimen>
+    <dimen name="chassis_toolbar_nav_button_width">@dimen/chassis_margin</dimen>
+    <dimen name="chassis_toolbar_icon_size">@dimen/chassis_primary_icon_size</dimen>
+    <dimen name="chassis_toolbar_title_margin_start">@dimen/chassis_padding_2</dimen>
+    <dimen name="chassis_toolbar_menu_item_margin">@dimen/chassis_padding_2</dimen>
+    <dimen name="chassis_toolbar_icon_ripple_radius">48dp</dimen>
 
     <!-- Internal artifacts. Do not overlay -->
     <item name="wrap_content" format="integer" type="dimen">-2</item>
diff --git a/car-chassis-lib/res/values/strings.xml b/car-chassis-lib/res/values/strings.xml
index 38ea967..b4944e1 100644
--- a/car-chassis-lib/res/values/strings.xml
+++ b/car-chassis-lib/res/values/strings.xml
@@ -22,4 +22,8 @@
     <string name="chassis_scrollbar_page_down_button">Scroll down</string>
     <!-- Content description for paged recycler view scroll bar up arrow [CHAR LIMIT=30] -->
     <string name="chassis_scrollbar_page_up_button">Scroll up</string>
+    <!-- Title of the search menu item. Will be displayed if the button is in the overflow menu. [CHAR_LIMIT=50] -->
+    <string name="chassis_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="chassis_toolbar_menu_item_settings_title">Settings</string>
 </resources>
diff --git a/car-chassis-lib/res/values/styles.xml b/car-chassis-lib/res/values/styles.xml
index 6d5308f..b9ea23a 100644
--- a/car-chassis-lib/res/values/styles.xml
+++ b/car-chassis-lib/res/values/styles.xml
@@ -40,7 +40,7 @@
     <style name="ChassisToolbarTitleStyle">
         <item name="android:textAppearance">@style/TextAppearance.Body1</item>
         <item name="android:singleLine">true</item>
-        <item name="android:layout_marginStart">@dimen/chassis_toolbar_view_title_margin_start</item>
+        <item name="android:layout_marginStart">@dimen/chassis_toolbar_title_margin_start</item>
     </style>
 
     <style name="ChassisToolbarContainerStyle"/>
@@ -58,14 +58,14 @@
     </style>
 
     <style name="ChassisToolbarNavIconContainerStyle">
-        <item name="android:layout_width">@dimen/chassis_toolbar_view_nav_button_width</item>
+        <item name="android:layout_width">@dimen/chassis_toolbar_nav_button_width</item>
         <item name="android:layout_height">0dp</item>
         <item name="android:background">?android:attr/selectableItemBackground</item>
     </style>
 
     <style name="ChassisToolbarNavIconStyle">
-        <item name="android:layout_width">@dimen/chassis_toolbar_view_icon_size</item>
-        <item name="android:layout_height">@dimen/chassis_toolbar_view_icon_size</item>
+        <item name="android:layout_width">@dimen/chassis_toolbar_icon_size</item>
+        <item name="android:layout_height">@dimen/chassis_toolbar_icon_size</item>
         <item name="android:layout_gravity">center</item>
         <item name="android:tint">@color/chassis_primary_text_color</item>
         <item name="android:src">@drawable/chassis_icon_arrow_back</item>
@@ -73,12 +73,18 @@
     </style>
 
     <style name="ChassisToolbarLogoStyle">
-        <item name="android:layout_width">@dimen/chassis_toolbar_view_icon_size</item>
-        <item name="android:layout_height">@dimen/chassis_toolbar_view_icon_size</item>
+        <item name="android:layout_width">@dimen/chassis_toolbar_icon_size</item>
+        <item name="android:layout_height">@dimen/chassis_toolbar_icon_size</item>
         <item name="android:layout_gravity">center</item>
         <item name="android:scaleType">fitXY</item>
     </style>
 
+    <style name="ChassisToolbarTextButtonStyle">
+        <item name="android:background">?android:attr/selectableItemBackground</item>
+        <item name="android:textColor">?android:attr/colorAccent</item>
+        <item name="android:textAppearance">@style/TextAppearance.Body3</item>
+    </style>
+
     <style name="TextAppearance">
         <item name="android:fontFamily">roboto-regular</item>
         <item name="android:textColor">@color/chassis_primary_text_color</item>
diff --git a/car-chassis-lib/src/com/android/car/chassis/MenuItem.java b/car-chassis-lib/src/com/android/car/chassis/MenuItem.java
new file mode 100644
index 0000000..79cff4a
--- /dev/null
+++ b/car-chassis-lib/src/com/android/car/chassis/MenuItem.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.chassis;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.Switch;
+
+/**
+ * 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#createSearch(Context, OnClickListener)} or
+ * {@link Builder#createSettings(Context, OnClickListener)}.
+ *
+ * <p>Some properties can be changed after the creating a MenuItem, but others require being set
+ * with a {@link Builder}.
+ */
+public class MenuItem {
+
+    private Context mContext;
+    private Listener mListener;
+    private CharSequence mTitle;
+    private Drawable mIcon;
+    private OnClickListener mOnClickListener;
+    private DisplayBehavior mDisplayBehavior;
+    private boolean mIsEnabled;
+    private boolean mIsCheckable;
+    private boolean mIsChecked;
+    private int mId;
+    private View mView;
+
+    private MenuItem(Builder builder) {
+        mContext = builder.mContext;
+        mTitle = builder.mTitle;
+        mIcon = builder.mIcon;
+        mOnClickListener = builder.mOnClickListener;
+        mDisplayBehavior = builder.mDisplayBehavior;
+        mIsEnabled = builder.mIsEnabled;
+        mIsCheckable = builder.mIsCheckable;
+        mIsChecked = builder.mIsChecked;
+        mId = builder.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;
+
+        if (mView != null) {
+            recursiveSetEnabled(mView, mIsEnabled);
+        }
+    }
+
+    /** 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;
+
+        if (mView != null) {
+            Switch s = mView.requireViewById(R.id.chassis_toolbar_menu_item_switch);
+            s.setChecked(mIsChecked);
+        }
+
+        if (isEnabled() && getOnClickListener() != null) {
+            getOnClickListener().onClick(this);
+        }
+    }
+
+    /** Gets the title of this MenuItem. */
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /** Sets the title of this MenuItem. */
+    public void setTitle(CharSequence title) {
+        mTitle = title;
+
+        if (mView != null) {
+            Button button = mView.findViewById(R.id.chassis_toolbar_menu_item_text);
+            if (button != null) {
+                button.setText(mTitle);
+            }
+        }
+
+        if (mListener != null) {
+            mListener.onMenuItemTitleChanged(this, mTitle);
+        }
+    }
+
+    /** Sets the title of this MenuItem to a string resource. */
+    public void setTitle(int resId) {
+        setTitle(mContext.getString(resId));
+    }
+
+    /** Gets the current {@link OnClickListener} */
+    public OnClickListener getOnClickListener() {
+        return mOnClickListener;
+    }
+
+    /** Sets the {@link OnClickListener} */
+    public void setOnClickListener(OnClickListener listener) {
+        mOnClickListener = listener;
+    }
+
+    /** Gets the current {@link DisplayBehavior} */
+    public DisplayBehavior getDisplayBehavior() {
+        return mDisplayBehavior;
+    }
+
+    /** Gets the current Icon */
+    public Drawable getIcon() {
+        return mIcon;
+    }
+
+    int getId() {
+        return mId;
+    }
+
+    /**
+     * Builder class.
+     *
+     * <p>Use the static {@link #createSearch(Context, OnClickListener)} or
+     * {@link #createSettings(Context, OnClickListener)} if you want one of those specialized
+     * buttons.
+     */
+    public static final class Builder {
+        private Context mContext;
+
+        private CharSequence mTitle;
+        private Drawable mIcon;
+        private OnClickListener mOnClickListener;
+        private DisplayBehavior mDisplayBehavior = DisplayBehavior.ALWAYS;
+        private boolean mIsEnabled = true;
+        private boolean mIsCheckable = false;
+        private boolean mIsChecked = false;
+        private int mId;
+
+        public Builder(Context c) {
+            mContext = c;
+        }
+
+        /** Builds a {@link MenuItem} from the current state of the Builder */
+        public MenuItem build() {
+            return new MenuItem(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 */
+        public Builder setIcon(int resId) {
+            mIcon = mContext.getDrawable(resId);
+            return this;
+        }
+
+        /** Sets the {@link OnClickListener} */
+        public Builder setOnClickListener(OnClickListener listener) {
+            mOnClickListener = listener;
+            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) {
+            if (behavior == DisplayBehavior.NEVER && mIsCheckable) {
+                throw new IllegalStateException(
+                        "Currently we don't support a checkable overflow item");
+            }
+            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() {
+            if (mDisplayBehavior == DisplayBehavior.NEVER) {
+                throw new IllegalStateException(
+                        "Currently we don't support a checkable overflow item");
+            }
+            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;
+        }
+
+        private Builder setId(int id) {
+            mId = id;
+            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.
+         */
+        public static MenuItem createSearch(Context c, OnClickListener listener) {
+            return new Builder(c)
+                    .setTitle(R.string.chassis_toolbar_menu_item_search_title)
+                    .setIcon(R.drawable.chassis_icon_search)
+                    .setOnClickListener(listener)
+                    .setId(R.id.search)
+                    .build();
+        }
+
+        /**
+         * Creates a settings MenuItem.
+         *
+         * <p>The advantage of this over creating your own is getting an OEM-styled settings icon.
+         */
+        public static MenuItem createSettings(Context c, OnClickListener listener) {
+            return new Builder(c)
+                    .setTitle(R.string.chassis_toolbar_menu_item_settings_title)
+                    .setIcon(R.drawable.chassis_icon_settings)
+                    .setOnClickListener(listener)
+                    .build();
+        }
+    }
+
+    /**
+     * 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's title is changed. For use only by {@link Toolbar} */
+        void onMenuItemTitleChanged(MenuItem item, CharSequence title);
+    }
+
+    void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    View createView(ViewGroup parent) {
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+
+        if (isCheckable()) {
+            mView = inflater.inflate(
+                    R.layout.chassis_toolbar_menu_item_switch, parent, false);
+            Switch s = mView.requireViewById(R.id.chassis_toolbar_menu_item_switch);
+            s.setChecked(isChecked());
+        } else if (getIcon() != null) {
+            mView = inflater.inflate(
+                    R.layout.chassis_toolbar_menu_item_icon, parent, false);
+            ImageView imageView = mView.requireViewById(R.id.chassis_toolbar_menu_item_icon);
+            imageView.setImageDrawable(getIcon());
+        } else {
+            mView = (Button) inflater.inflate(
+                    R.layout.chassis_toolbar_menu_item_text, parent, false);
+            Button button = mView.requireViewById(R.id.chassis_toolbar_menu_item_text);
+            button.setText(getTitle());
+        }
+
+        if (getId() != 0) {
+            mView.setId(getId());
+        }
+
+        recursiveSetEnabled(mView, isEnabled());
+        mView.setOnClickListener(v -> {
+            Switch s = v.findViewById(R.id.chassis_toolbar_menu_item_switch);
+            if (s != null) {
+                s.toggle();
+                setChecked(s.isChecked());
+            }
+
+            if (getOnClickListener() != null) {
+                getOnClickListener().onClick(this);
+            }
+        });
+
+        return mView;
+    }
+
+    private void recursiveSetEnabled(View view, boolean enabled) {
+        view.setEnabled(enabled);
+        if (view instanceof ViewGroup) {
+            ViewGroup viewGroup = ((ViewGroup) view);
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                recursiveSetEnabled(viewGroup.getChildAt(i), enabled);
+            }
+        }
+    }
+}
diff --git a/car-chassis-lib/src/com/android/car/chassis/Toolbar.java b/car-chassis-lib/src/com/android/car/chassis/Toolbar.java
index 0cb2373..09f8bdd 100644
--- a/car-chassis-lib/src/com/android/car/chassis/Toolbar.java
+++ b/car-chassis-lib/src/com/android/car/chassis/Toolbar.java
@@ -15,12 +15,12 @@
  */
 package com.android.car.chassis;
 
+import android.app.AlertDialog;
 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.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -29,11 +29,12 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -41,11 +42,11 @@
 /**
  * A toolbar for Android Automotive OS apps.
  *
- * This isn't a toolbar in the android framework sense, it's merely a custom view that can be
+ * <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)
  *
- * The toolbar supports a navigation button, title, tabs, search, and custom buttons.
+ * <p>The toolbar supports a navigation button, title, tabs, search, and {@link MenuItem MenuItems}
  */
 public class Toolbar extends FrameLayout {
 
@@ -56,12 +57,12 @@
         /**
          * 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. Custom buttons will be displayed.
+         * 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 custom buttons will be displayed.
+         * be visible. The title and MenuItems will be displayed.
          */
         SUBPAGE,
         /**
@@ -87,15 +88,24 @@
     private ViewGroup mNavIconContainer;
     private TextView mTitle;
     private TabLayout mTabLayout;
-    private LinearLayout mButtonsContainer;
+    private LinearLayout mMenuItemsContainer;
     private FrameLayout mCustomViewContainer;
+    private View mOverflowButton;
     private Set<Listener> mListeners = new HashSet<>();
     private SearchView mSearchView;
     private boolean mHasLogo = false;
-    private int[] mCurrentButtons;
-    private boolean mShowButtonsWhileSearching;
+    private boolean mShowMenuItemsWhileSearching;
     private View mSearchButton;
     private State mState = State.HOME;
+    @NonNull
+    private List<MenuItem> mMenuItems = Collections.emptyList();
+    private List<MenuItem> mOverflowItems = new ArrayList<>();
+    private MenuItem.Listener mMenuItemListener = (item, title) -> {
+        if (item.getDisplayBehavior() == MenuItem.DisplayBehavior.NEVER) {
+            createOverflowDialog();
+        }
+    };
+    private AlertDialog mOverflowDialog;
 
     public Toolbar(Context context) {
         this(context, null);
@@ -120,59 +130,71 @@
         mNavIcon = requireViewById(R.id.nav_icon);
         mLogo = requireViewById(R.id.logo);
         mNavIconContainer = requireViewById(R.id.nav_icon_container);
-        mButtonsContainer = requireViewById(R.id.buttons_container);
+        mMenuItemsContainer = requireViewById(R.id.menu_items_container);
         mTitle = requireViewById(R.id.title);
         mSearchView = requireViewById(R.id.search_view);
         mCustomViewContainer = requireViewById(R.id.custom_view_container);
+        mOverflowButton = requireViewById(R.id.chassis_toolbar_overflow_button);
 
         TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.ChassisToolbar, defStyleAttr, defStyleRes);
 
-        mTitle.setText(a.getString(R.styleable.ChassisToolbar_title));
-        setLogo(a.getResourceId(R.styleable.ChassisToolbar_logo, 0));
-        setButtons(a.getResourceId(R.styleable.ChassisToolbar_buttons, 0));
-        setBackgroundShown(a.getBoolean(R.styleable.ChassisToolbar_showBackground, true));
-        mShowButtonsWhileSearching = a.getBoolean(
-                R.styleable.ChassisToolbar_showButtonsWhileSearching, false);
-        String searchHint = a.getString(R.styleable.ChassisToolbar_searchHint);
-        if (searchHint != null) {
-            setSearchHint(searchHint);
-        }
+        try {
+            mTitle.setText(a.getString(R.styleable.ChassisToolbar_title));
+            setLogo(a.getResourceId(R.styleable.ChassisToolbar_logo, 0));
+            setBackgroundShown(a.getBoolean(R.styleable.ChassisToolbar_showBackground, true));
+            mShowMenuItemsWhileSearching = a.getBoolean(
+                    R.styleable.ChassisToolbar_showMenuItemsWhileSearching, false);
+            String searchHint = a.getString(R.styleable.ChassisToolbar_searchHint);
+            if (searchHint != null) {
+                setSearchHint(searchHint);
+            }
 
-        switch (a.getInt(R.styleable.ChassisToolbar_state, 0)) {
-            case 0:
-                setState(State.HOME);
-                break;
-            case 1:
-                setState(State.SUBPAGE);
-                break;
-            case 2:
-                setState(State.SUBPAGE_CUSTOM);
-                break;
-            case 3:
-                setState(State.SEARCH);
-                break;
-            default:
-                if (Log.isLoggable(TAG, Log.WARN)) {
-                    Log.w(TAG, "Unknown initial state");
-                }
-                break;
+            switch (a.getInt(R.styleable.ChassisToolbar_state, 0)) {
+                case 0:
+                    setState(State.HOME);
+                    break;
+                case 1:
+                    setState(State.SUBPAGE);
+                    break;
+                case 2:
+                    setState(State.SUBPAGE_CUSTOM);
+                    break;
+                case 3:
+                    setState(State.SEARCH);
+                    break;
+                default:
+                    if (Log.isLoggable(TAG, Log.WARN)) {
+                        Log.w(TAG, "Unknown initial state");
+                    }
+                    break;
+            }
+        } finally {
+            a.recycle();
         }
 
-        a.recycle();
-
         mTabLayout.addListener(new TabLayout.Listener() {
             @Override
             public void onTabSelected(TabLayout.Tab tab) {
                 forEachListener(listener -> listener.onTabSelected(tab));
             }
         });
+
+        mOverflowButton.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();
+            }
+        });
     }
 
     /**
      * Sets the title of the toolbar to a string resource.
      *
-     * The title may not always be shown, for example in landscape with tabs.
+     * <p>The title may not always be shown, for example in landscape with tabs.
      */
     public void setTitle(@StringRes int title) {
         mTitle.setText(title);
@@ -181,7 +203,7 @@
     /**
      * Sets the title of the toolbar to a CharSequence.
      *
-     * The title may not always be shown, for example in landscape with tabs.
+     * <p>The title may not always be shown, for example in landscape with tabs.
      */
     public void setTitle(CharSequence title) {
         mTitle.setText(title);
@@ -268,84 +290,66 @@
     }
 
     /**
-     * Sets the buttons to be shown. Click events for these buttons will be received in
-     * {@link Listener#onCustomButtonPressed(View)}.
-     *
-     * Buttons are encouraged to use @drawable/chassis_toolbar_button_background as their
-     * background. In the default implementation it's a ripple that is sized appropriately to fit
-     * the toolbar.
-     *
-     * R.layout.chassis_toolbar_search_button can be used to add a search button, which will have an
-     * id of R.id.search in {@link Listener#onCustomButtonPressed(View)} callback.
-     *
-     * R.layout.chassis_toolbar_settings_button can be used to add a search button, which will have
-     * an id of R.id.settings in {@link Listener#onCustomButtonPressed(View)} callback.
-     *
-     * @param buttons An array of layout ids specifying the buttons to show. Toolbar will keep
-     *                a reference to this array, so don't modify it afterwards.
+     * Sets the {@link MenuItem Menuitems} to display.
      */
-    public void setButtons(@Nullable int[] buttons) {
-        if (!Arrays.equals(buttons, mCurrentButtons)) {
-            mButtonsContainer.removeAllViews();
+    public void setMenuItems(@Nullable List<MenuItem> items) {
+        if (items == null) {
+            items = Collections.emptyList();
+        }
 
-            if (buttons != null) {
-                LayoutInflater inflater = (LayoutInflater) getContext()
-                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        if (items.equals(mMenuItems)) {
+            return;
+        }
 
-                for (int button : buttons) {
-                    View v = inflater.inflate(button, mButtonsContainer, false);
-                    mButtonsContainer.addView(v);
+        mMenuItems = items;
 
-                    setupCustomButton(v);
-                }
+        mOverflowItems.clear();
+        mMenuItemsContainer.removeAllViews();
+
+        for (MenuItem item : items) {
+            item.setListener(mMenuItemListener);
+            if (item.getDisplayBehavior() == MenuItem.DisplayBehavior.NEVER) {
+                mOverflowItems.add(item);
+            } else {
+                View menuItemView = item.createView(mMenuItemsContainer);
+                mMenuItemsContainer.addView(menuItemView);
             }
-
-            mSearchButton = mButtonsContainer.findViewById(R.id.search);
-            mCurrentButtons = buttons;
-            setState(mState);
         }
+
+        createOverflowDialog();
+
+        mSearchButton = mMenuItemsContainer.findViewById(R.id.search);
+
+        setState(mState);
     }
 
-    private void setButtons(TypedArray buttons) {
-        int[] layouts = new int[buttons.length()];
-        for (int i = 0; i < buttons.length(); ++i) {
-            layouts[i] = buttons.getResourceId(i, 0);
-        }
-        setButtons(layouts);
+    private void createOverflowDialog() {
+        // TODO(b/140564530) Use a chassis alert with a (paged)recyclerview here
+        // TODO(b/140563930) Support enabled/disabled overflow items
+
+        CharSequence[] itemTitles = mOverflowItems.stream()
+                .map(MenuItem::getTitle)
+                .toArray(CharSequence[]::new);
+
+        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();
     }
 
     /**
-     * Sets the buttons to be shown, based on an XML array of layouts. See
-     * {@link #setButtons(int[])} for more info.
-     *
-     * @param arrayId A resource id of an array of layouts.
+     * 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#createSearch(Context, MenuItem.OnClickListener)} will still be
+     * hidden.
      */
-    public void setButtons(int arrayId) {
-        if (arrayId == 0) {
-            mButtonsContainer.removeAllViews();
-            mCurrentButtons = null;
-        } else {
-            setButtons(getContext().getResources().obtainTypedArray(arrayId));
-        }
-    }
-
-    private void setupCustomButton(View v) {
-        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) v.getLayoutParams();
-        lp.rightMargin = getContext().getResources().getDimensionPixelSize(
-                R.dimen.chassis_toolbar_custom_button_margin);
-        lp.leftMargin = lp.rightMargin;
-        lp.gravity = Gravity.CENTER_VERTICAL;
-
-        v.setOnClickListener(x -> forEachListener(listener -> listener.onCustomButtonPressed(x)));
-    }
-
-    /**
-     * Set whether or not to show the custom buttons while searching. Default false.
-     * Even if this is set to true, if there is a button with the id "search", such as the button
-     * added by R.layout.chassis_toolbar_search_button, that buttons will always be hidden.
-     */
-    public void setShowButtonsWhileSearching(boolean showButtons) {
-        mShowButtonsWhileSearching = showButtons;
+    public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
+        mShowMenuItemsWhileSearching = showMenuItems;
         setState(mState);
     }
 
@@ -384,13 +388,14 @@
         mNavIcon.setImageResource(state != State.HOME ? R.drawable.chassis_icon_arrow_back : 0);
         mLogo.setVisibility(state == State.HOME && mHasLogo ? VISIBLE : INVISIBLE);
         mNavIconContainer.setVisibility(state != State.HOME || mHasLogo ? VISIBLE : GONE);
-        mNavIconContainer.setClickable(state != State.HOME);
         mNavIconContainer.setOnClickListener(state != State.HOME ? backClickListener : null);
+        mNavIconContainer.setClickable(state != State.HOME);
         mTitle.setVisibility(state == State.HOME || state == State.SUBPAGE ? VISIBLE : GONE);
         mTabLayout.setVisibility(state == State.HOME ? VISIBLE : GONE);
         mSearchView.setVisibility(state == State.SEARCH ? VISIBLE : GONE);
-        mButtonsContainer.setVisibility(state != State.SEARCH || mShowButtonsWhileSearching
-                ? VISIBLE : GONE);
+        boolean showButtons = state != State.SEARCH || mShowMenuItemsWhileSearching;
+        mMenuItemsContainer.setVisibility(showButtons ? VISIBLE : GONE);
+        mOverflowButton.setVisibility(showButtons && mOverflowItems.size() > 0 ? VISIBLE : GONE);
         if (mSearchButton != null) {
             mSearchButton.setVisibility(state != State.SEARCH ? VISIBLE : GONE);
         }
@@ -418,12 +423,6 @@
          * Invoked when the user submits a search query.
          */
         default void onSearch(String query) {}
-
-        /**
-         * Invoked when the user clicks on a custom button
-         * @param v The button that was clicked
-         */
-        default void onCustomButtonPressed(View v) {}
     }
 
     /**