ActionBar initial implementation

Bug: 74118268
Specs: https://spec.googleplex.com/aauto/embedded-components/action-bar.html#action-bar-specs
Test: ActionBarTest
Change-Id: I0310053fae10192625ef8c65a09e3a62558d49ab
diff --git a/car/res/drawable/car_action_button_activated_ring_foreground.xml b/car/res/drawable/car_action_button_activated_ring_foreground.xml
new file mode 100644
index 0000000..cf9570b
--- /dev/null
+++ b/car/res/drawable/car_action_button_activated_ring_foreground.xml
@@ -0,0 +1,48 @@
+<?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/car/res/drawable/car_action_button_background.xml b/car/res/drawable/car_action_button_background.xml
new file mode 100644
index 0000000..27e97e3
--- /dev/null
+++ b/car/res/drawable/car_action_button_background.xml
@@ -0,0 +1,19 @@
+<?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/car/res/drawable/ic_down.xml b/car/res/drawable/ic_down.xml
index c6bb32d..cd486c1 100644
--- a/car/res/drawable/ic_down.xml
+++ b/car/res/drawable/ic_down.xml
@@ -1,3 +1,19 @@
+<?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"
diff --git a/car/res/drawable/ic_overflow.xml b/car/res/drawable/ic_overflow.xml
new file mode 100644
index 0000000..eda306c
--- /dev/null
+++ b/car/res/drawable/ic_overflow.xml
@@ -0,0 +1,45 @@
+<?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/car/res/drawable/ic_up.xml b/car/res/drawable/ic_up.xml
index 05f69b9..ec18410 100644
--- a/car/res/drawable/ic_up.xml
+++ b/car/res/drawable/ic_up.xml
@@ -1,3 +1,19 @@
+<?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"
diff --git a/car/res/layout/action_bar.xml b/car/res/layout/action_bar.xml
new file mode 100644
index 0000000..3ba656a
--- /dev/null
+++ b/car/res/layout/action_bar.xml
@@ -0,0 +1,49 @@
+<?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.
+-->
+<android.support.v7.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>
+
+</android.support.v7.widget.CardView>
\ No newline at end of file
diff --git a/car/res/layout/action_bar_button.xml b/car/res/layout/action_bar_button.xml
new file mode 100644
index 0000000..e9d2370
--- /dev/null
+++ b/car/res/layout/action_bar_button.xml
@@ -0,0 +1,16 @@
+<?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/car/res/layout/action_bar_slot.xml b/car/res/layout/action_bar_slot.xml
new file mode 100644
index 0000000..804e356
--- /dev/null
+++ b/car/res/layout/action_bar_slot.xml
@@ -0,0 +1,25 @@
+<?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/car/res/values/attrs.xml b/car/res/values/attrs.xml
index 076c342..3a2959f 100644
--- a/car/res/values/attrs.xml
+++ b/car/res/values/attrs.xml
@@ -141,6 +141,12 @@
         <attr name="clickThrough" format="boolean"/>
     </declare-styleable>
 
+    <!-- Attributes for the ActionBar. -->
+    <declare-styleable name="ActionBar">
+        <!-- The number of horizontal slots. The minimum number is 3. -->
+        <attr name="columns" format="integer" />
+    </declare-styleable>
+
     <!-- Attributes specifically related to modifying car themes. -->
     <declare-styleable name="CarTheme">
         <!-- ================== -->
@@ -193,5 +199,6 @@
         <attr name="drawerItemBodyTextAppearance" format="reference"/>
         <!-- The styling of the list in the drawer. -->
         <attr name="drawerListStyle" format="reference"/>
+
     </declare-styleable>
 </resources>
diff --git a/car/res/values/dimens.xml b/car/res/values/dimens.xml
index 4a5010f..2f77343 100644
--- a/car/res/values/dimens.xml
+++ b/car/res/values/dimens.xml
@@ -86,15 +86,26 @@
     <dimen name="car_app_bar_height">80dp</dimen>
     <dimen name="car_app_bar_default_elevation">8dp</dimen>
 
-    <!-- Action Bars -->
+    <!-- Action Bar -->
     <dimen name="car_action_bar_height">128dp</dimen>
-    <dimen name="car_secondary_single_action_bar_height">@dimen/car_action_bar_height</dimen>
-    <dimen name="car_secondary_double_action_bar_height">256dp</dimen>
+    <dimen name="car_action_bar_buttons_space">@dimen/car_padding_4</dimen>
+    <dimen name="car_action_bar_button_width">128dp</dimen>
+    <dimen name="car_action_bar_button_height">128dp</dimen>
+    <dimen name="car_action_bar_activation_ring_stroke_width">3dp</dimen>
+    <dimen name="car_action_bar_activation_ring_radius">64dp</dimen>
+    <dimen name="car_action_bar_touch_ripple_size">38dp</dimen>
+    <dimen name="car_action_bar_button_ripple_radius">48dp</dimen>
+    <dimen name="car_action_bar_elevation">2dp</dimen>
+
+    <!-- Action Buttons -->
+    <dimen name="car_action_button_icon_inset">24dp</dimen>
+    <dimen name="car_action_button_ripple_inset">16dp</dimen>
 
     <!-- Lists -->
     <dimen name="car_single_line_list_item_height">96dp</dimen>
     <dimen name="car_double_line_list_item_height">@dimen/car_single_line_list_item_height</dimen>
     <dimen name="car_list_divider_height">1dp</dimen>
+
     <!-- The height of a vertical line divider. -->
     <dimen name="car_vertical_line_divider_height">60dp</dimen>
     <dimen name="car_vertical_line_divider_width">1dp</dimen>
@@ -182,4 +193,5 @@
     <!-- Speed Bump -->
     <dimen name="speed_bump_lock_out_message_height">96dp</dimen>
     <dimen name="speed_bump_lock_out_drawable_margin_bottom">8dp</dimen>
+
 </resources>
diff --git a/car/res/values/integers.xml b/car/res/values/integers.xml
index 97fb9c1..6c737af 100644
--- a/car/res/values/integers.xml
+++ b/car/res/values/integers.xml
@@ -19,9 +19,6 @@
     <integer name="car_column_number">4</integer>
 
     <!-- Application Components -->
-    <!-- Action Bar -->
-    <integer name="action_bar_column_number">@integer/car_column_number</integer>
-
     <!-- Cards -->
     <integer name="column_card_default_column_span">4</integer>
 
@@ -56,4 +53,9 @@
 
     <!-- The amount of time for the speed bump background color to transition. -->
     <integer name="speed_bump_lock_out_color_change_ms">500</integer>
+
+    <!-- Action Bar animation durations -->
+    <integer name="car_action_bar_expand_anim_duration">333</integer>
+    <integer name="car_action_bar_collapse_anim_duration">233</integer>
+
 </resources>
diff --git a/car/res/values/strings.xml b/car/res/values/strings.xml
index bbba469..fb00957 100644
--- a/car/res/values/strings.xml
+++ b/car/res/values/strings.xml
@@ -23,8 +23,13 @@
     <string name="car_drawer_close" translatable="false">Close drawer</string>
     <string name="ellipsis" translatable="false">&#8230;</string>
 
+    <!-- Speed Bump -->
     <!-- The message that is displayed to the user to inform them that they should focus on the
          task of driving. When this message is displayed, the user is also locked out from
          interacting with the current application. [CHAR_LIMIT=30] -->
     <string name="speed_bump_lockout_message">Focus on the road</string>
+
+    <!-- Action Bar -->
+    <!-- Content description for the 'Expand/Collapse' button [CHAR_LIMIT=50] -->
+    <string name="action_bar_expand_collapse_button">Expand/collapse button</string>
 </resources>
diff --git a/car/res/values/styles.xml b/car/res/values/styles.xml
index 5f1cdec..ccd661a 100644
--- a/car/res/values/styles.xml
+++ b/car/res/values/styles.xml
@@ -339,4 +339,17 @@
     <style name="Widget.Car.Dialog.Body.Dark">
         <item name="android:textAppearance">@style/TextAppearance.Car.Body2.Dark</item>
     </style>
+
+    <!-- ================ -->
+    <!-- ActionBar Themes -->
+    <!-- ================ -->
+    <eat-comment />
+
+    <!-- Styles for action buttons -->
+    <style name="Widget.Car.Button.ActionBar">
+        <item name="android:scaleType">fitCenter</item>
+        <item name="android:padding">@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>
 </resources>
diff --git a/car/src/androidTest/AndroidManifest.xml b/car/src/androidTest/AndroidManifest.xml
index 24b98bc..38bf758 100644
--- a/car/src/androidTest/AndroidManifest.xml
+++ b/car/src/androidTest/AndroidManifest.xml
@@ -29,5 +29,7 @@
                   android:theme="@style/Theme.Car.Light.NoActionBar" />
         <activity android:name="androidx.car.widget.DividerVisibilityManagerTestActivity"
                   android:theme="@style/Theme.Car.Light.NoActionBar" />
+	<activity android:name="androidx.car.widget.ActionBarTestActivity"
+                  android:theme="@style/Theme.Car.Light.NoActionBar" />
     </application>
 </manifest>
diff --git a/car/src/androidTest/AndroidManifest.xml.orig b/car/src/androidTest/AndroidManifest.xml.orig
new file mode 100644
index 0000000..c195f3c
--- /dev/null
+++ b/car/src/androidTest/AndroidManifest.xml.orig
@@ -0,0 +1,41 @@
+<?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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="androidx.car.widget.test">
+    <uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
+
+    <application android:supportsRtl="true">
+        <activity android:name="androidx.car.drawer.CarDrawerTestActivity"
+                  android:theme="@style/Theme.Car.Light.NoActionBar.Drawer" />
+<<<<<<< HEAD
+        <activity android:name="androidx.car.widget.ColumnCardViewTestActivity"
+                  android:theme="@style/Theme.Car.Light.NoActionBar" />
+        <activity android:name="androidx.car.widget.PagedListViewSavedStateActivity"
+                  android:theme="@style/Theme.Car.Light.NoActionBar" />
+        <activity android:name="androidx.car.widget.PagedListViewTestActivity"
+                  android:theme="@style/Theme.Car.Light.NoActionBar" />
+        <activity android:name="androidx.car.widget.DividerVisibilityManagerTestActivity"
+                  android:theme="@style/Theme.Car.Light.NoActionBar" />
+=======
+        <activity android:name="androidx.car.widget.ColumnCardViewTestActivity"/>
+        <activity android:name="androidx.car.widget.PagedListViewSavedStateActivity"/>
+        <activity android:name="androidx.car.widget.PagedListViewTestActivity"/>
+        <activity android:name="androidx.car.widget.DividerVisibilityManagerTestActivity"/>
+        <activity android:name="androidx.car.widget.ActionBarTestActivity"/>
+>>>>>>> ActionBar initial implementation
+    </application>
+</manifest>
diff --git a/car/src/androidTest/java/androidx/car/widget/ActionBarTest.java b/car/src/androidTest/java/androidx/car/widget/ActionBarTest.java
new file mode 100644
index 0000000..08d794a
--- /dev/null
+++ b/car/src/androidTest/java/androidx/car/widget/ActionBarTest.java
@@ -0,0 +1,222 @@
+/*
+ * 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 androidx.car.widget;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.util.Preconditions;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.Space;
+import android.widget.ToggleButton;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.car.R;
+
+/** Unit tests for {@link ActionBar}. */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class ActionBarTest {
+    @Rule
+    public ActivityTestRule<ActionBarTestActivity> mActivityRule =
+            new ActivityTestRule<>(ActionBarTestActivity.class);
+    private ActionBarTestActivity mActivity;
+    private ActionBar mActionBar;
+    private LinearLayout mRowsContainer;
+    private View[] mItems;
+
+    private static final int TOP_ROW_IDX = 0;
+    private static final int BOTTOM_ROW_IDX = 1;
+    private static final int NUM_COLS = 5;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mActionBar = mActivity.findViewById(androidx.car.test.R.id.action_bar);
+        mRowsContainer = mActionBar.findViewById(R.id.rows_container);
+    }
+
+    private void setUpActionBarItems(int numItems) {
+        mItems = new View[numItems];
+        for (int i = 0; i < numItems; i++) {
+            mItems[i] = createButton(mActivity);
+        }
+        mActivity.runOnUiThread(() ->  mActionBar.setViews(mItems));
+    }
+
+    private ImageButton createButton(Context context) {
+        ImageButton button = new ImageButton(context, null, R.style.Widget_Car_Button_ActionBar);
+        button.setImageDrawable(context.getDrawable(androidx.car.test.R.drawable.ic_overflow));
+        return button;
+    }
+
+    /**
+     * Asserts that only the first 'numItems' slots are used.
+     */
+    private void assertLeftItemsNotEmpty(int rowIdx, int numItems) {
+        for (int colIdx = 0; colIdx < NUM_COLS - 1; colIdx++) {
+            if (colIdx < numItems) {
+                assertNotNull(String.format("Slot (%d, %d) should be taken", rowIdx, colIdx),
+                        mActionBar.getViewAt(rowIdx, colIdx));
+            } else {
+                assertNull(String.format("Slot (%d, %d) should be empty", rowIdx, colIdx),
+                        mActionBar.getViewAt(rowIdx, colIdx));
+            }
+        }
+    }
+
+    /**
+     * Tests that the bar with no children views is displayed correctly
+     */
+    @Test
+    public void testEmptyState() {
+        setUpActionBarItems(0);
+        onView(withId(androidx.car.test.R.id.action_bar)).check((view, noViewFoundException) -> {
+            Preconditions.checkNotNull(view);
+            // All slots should be empty.
+            assertLeftItemsNotEmpty(TOP_ROW_IDX, 0);
+            assertLeftItemsNotEmpty(BOTTOM_ROW_IDX, 0);
+        });
+    }
+
+    /**
+     * Tests that slots are used from left to right and from bottom to top
+     */
+    @Test
+    public void testNormalSlotUsage() {
+        for (int items = 1; items < NUM_COLS - 1; items++) {
+            setUpActionBarItems(items);
+            final int numItems = items;
+            onView(withId(androidx.car.test.R.id.action_bar))
+                    .check((view, noViewFoundException) -> {
+                        Preconditions.checkNotNull(view);
+                        // Top row should be empty
+                        assertLeftItemsNotEmpty(TOP_ROW_IDX, 0);
+                        // Expand/collapse slot should be empty
+                        assertNull("Expand/collapse should be empty" ,
+                                mActionBar.getViewAt(BOTTOM_ROW_IDX, NUM_COLS - 1));
+                        // Slots on the bottom left should be taken while the rest should be empty.
+                        assertLeftItemsNotEmpty(BOTTOM_ROW_IDX, numItems);
+                    });
+        }
+    }
+
+    private void assertRowVisibility(int rowIdx, int visibility) {
+        assertEquals(visibility, mRowsContainer.getChildAt(rowIdx).getVisibility());
+    }
+
+    /**
+     * Tests that the expand/collapse button is added if enough views are set
+     */
+    @Test
+    public void testExpandCollapseEnabled() {
+        setUpActionBarItems(NUM_COLS + 1);
+
+        // Top row should have 2 slot taken (as expand/collapse takes one slot on the bottom row)
+        onView(withContentDescription(R.string.action_bar_expand_collapse_button))
+                .check((view, noViewFoundException) -> {
+                    Preconditions.checkNotNull(view);
+                    assertLeftItemsNotEmpty(TOP_ROW_IDX, 2);
+                    assertLeftItemsNotEmpty(BOTTOM_ROW_IDX, NUM_COLS);
+                    assertRowVisibility(TOP_ROW_IDX, View.GONE);
+                })
+                // Check that expand/collapse works
+                .perform(click())
+                .check((view, noViewFoundException) -> {
+                    assertRowVisibility(TOP_ROW_IDX, View.VISIBLE);
+                })
+                .perform(click())
+                .check((view, noViewFoundException) -> {
+                    assertRowVisibility(TOP_ROW_IDX, View.GONE);
+                });
+    }
+
+    private void setViewInPosition(View view, @ActionBar.SlotPosition int position) {
+        mActivity.runOnUiThread(() -> {
+            mActionBar.setView(view, position);
+        });
+    }
+
+    /**
+     * Tests that reserved slots are not used by normal views.
+     */
+    @Test
+    public void testReservingNamedSlots() {
+        View mainView = createButton(mActivity);
+        setViewInPosition(mainView, ActionBar.SLOT_MAIN);
+        View leftView = new Space(mActivity);
+        setViewInPosition(leftView, ActionBar.SLOT_LEFT);
+        setUpActionBarItems(NUM_COLS + 1);
+
+        // Expand/collapse plus two other slots should be taken in the bottom row.
+        onView(withContentDescription(R.string.action_bar_expand_collapse_button))
+                .check((view, noViewFoundException) -> {
+                    // Only 2 items fit in the bottom row. The remaining 4 should be on the top
+                    Preconditions.checkNotNull(view);
+                    assertLeftItemsNotEmpty(TOP_ROW_IDX, 4);
+                    assertLeftItemsNotEmpty(BOTTOM_ROW_IDX, NUM_COLS);
+                    assertRowVisibility(TOP_ROW_IDX, View.GONE);
+                    assertEquals(mainView, mActionBar.getViewAt(BOTTOM_ROW_IDX, 2));
+                    assertEquals(leftView, mActionBar.getViewAt(BOTTOM_ROW_IDX, 1));
+                })
+                .perform(click())
+                .check((view, noViewFoundException) -> {
+                    assertRowVisibility(TOP_ROW_IDX, View.VISIBLE);
+                });
+    }
+
+    private void setExpandCollapseCustomView(View view) {
+        mActivity.runOnUiThread(() -> {
+            mActionBar.setExpandCollapseView(view);
+        });
+    }
+
+    /**
+     * Tests setting custom expand/collapse views.
+     */
+    @Test
+    public void testCustomExpandCollapseView() {
+        View customExpandCollapse = new ToggleButton(mActivity);
+        customExpandCollapse.setContentDescription(mActivity.getString(
+                R.string.action_bar_expand_collapse_button));
+        setExpandCollapseCustomView(customExpandCollapse);
+        setUpActionBarItems(NUM_COLS + 1);
+
+        onView(withContentDescription(R.string.action_bar_expand_collapse_button))
+                .check((view, noViewFoundException) -> {
+                    Preconditions.checkNotNull(view);
+                    assertEquals(customExpandCollapse, mActionBar.getViewAt(BOTTOM_ROW_IDX,
+                            NUM_COLS - 1));
+                });
+    }
+}
diff --git a/car/src/androidTest/java/androidx/car/widget/ActionBarTestActivity.java b/car/src/androidTest/java/androidx/car/widget/ActionBarTestActivity.java
new file mode 100644
index 0000000..f5b2458
--- /dev/null
+++ b/car/src/androidTest/java/androidx/car/widget/ActionBarTestActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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 androidx.car.widget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Simple test activity for {@link PagedListView} class.
+ */
+public class ActionBarTestActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(androidx.car.test.R.layout.activity_action_bar);
+    }
+}
diff --git a/car/src/androidTest/res/layout/activity_action_bar.xml b/car/src/androidTest/res/layout/activity_action_bar.xml
new file mode 100644
index 0000000..43e3331
--- /dev/null
+++ b/car/src/androidTest/res/layout/activity_action_bar.xml
@@ -0,0 +1,33 @@
+<?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"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <androidx.car.widget.ActionBar
+        android:id="@+id/action_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="@dimen/car_margin"
+        android:layout_marginRight="@dimen/car_margin"
+        android:layout_marginBottom="@dimen/car_padding_2"
+        android:layout_alignParentBottom="true"
+        app:columns="5" />
+
+</RelativeLayout>
diff --git a/car/src/main/java/androidx/car/widget/ActionBar.java b/car/src/main/java/androidx/car/widget/ActionBar.java
new file mode 100644
index 0000000..a494eb3
--- /dev/null
+++ b/car/src/main/java/androidx/car/widget/ActionBar.java
@@ -0,0 +1,336 @@
+/*
+ * 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.
+ */
+
+package androidx.car.widget;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
+import android.transition.ChangeBounds;
+import android.transition.Fade;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.Space;
+
+import java.lang.annotation.Retention;
+import java.util.Locale;
+
+import androidx.car.R;
+
+/**
+ * An actions panel with three distinctive zones:
+ * <ul>
+ * <li>Main control: located in the bottom center it shows a highlighted icon and a circular
+ * progress bar.
+ * <li>Secondary controls: these are displayed at the left and at the right of the main control.
+ * <li>Overflow controls: these are displayed at the left and at the right of the secondary controls
+ * (if the space allows) and on the additional space if the panel is expanded.
+ * </ul>
+ */
+public class ActionBar extends RelativeLayout {
+    private static final String TAG = "ActionBar";
+
+    // ActionBar container
+    private ViewGroup mActionBarWrapper;
+    // Rows container
+    private ViewGroup mRowsContainer;
+    // All slots in this action bar where 0 is the bottom-start corner of the matrix, and
+    // mNumColumns * nNumRows - 1 is the top-end corner
+    private FrameLayout[] mSlots;
+    /** Views to set in particular {@link SlotPosition}s */
+    private final SparseArray<View> mFixedViews = new SparseArray<>();
+    // View to be used for the expand/collapse action
+    private @Nullable View mExpandCollapseView;
+    // Default expand/collapse view to use one is not provided.
+    private View mDefaultExpandCollapseView;
+    // Number of rows in actual use. This is the number of extra rows that will be displayed when
+    // the action bar is expanded
+    private int mNumExtraRowsInUse;
+    // Whether the action bar is expanded or not.
+    private boolean mIsExpanded;
+    // Views to accomodate in the slots.
+    private @Nullable View[] mViews;
+    // Number of columns of slots to use.
+    private int mNumColumns;
+    // Maximum number of rows to use.
+    private int mNumRows;
+
+    @Retention(SOURCE)
+    @IntDef({SLOT_MAIN, SLOT_LEFT, SLOT_RIGHT, SLOT_EXPAND_COLLAPSE})
+    public @interface SlotPosition {}
+
+    /** Slot used for main actions {@link ActionBar}, usually at the bottom center */
+    public static final int SLOT_MAIN = 0;
+    /** Slot used to host 'move left', 'rewind', 'previous' or similar secondary actions,
+     * usually at the left of the main action on the bottom row */
+    public static final int SLOT_LEFT = 1;
+    /** Slot used to host 'move right', 'fast-forward', 'next' or similar secondary actions,
+     * usually at the right of the main action on the bottom row */
+    public static final int SLOT_RIGHT = 2;
+    /** Slot reserved for the expand/collapse button */
+    public static final int SLOT_EXPAND_COLLAPSE = 3;
+
+    // Minimum number of columns supported
+    private static final int MIN_COLUMNS = 3;
+    // Weight for the spacers used at the start and end of each slots row.
+    private static final float SPACERS_WEIGHT = 0.5f;
+
+    public ActionBar(Context context) {
+        super(context);
+        init(context, null, 0, 0);
+    }
+
+    public ActionBar(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs, 0, 0);
+    }
+
+    public ActionBar(Context context, AttributeSet attrs, int defStyleAttrs) {
+        super(context, attrs, defStyleAttrs);
+        init(context, attrs, defStyleAttrs, 0);
+    }
+
+    public ActionBar(Context context, AttributeSet attrs, int defStyleAttrs, int defStyleRes) {
+        super(context, attrs, defStyleAttrs, defStyleRes);
+        init(context, attrs, defStyleAttrs, defStyleRes);
+    }
+
+    private void init(Context context, AttributeSet attrs, int defStyleAttrs, int defStyleRes) {
+        inflate(context, R.layout.action_bar, this);
+
+        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ActionBar,
+                defStyleAttrs, defStyleRes);
+        mNumColumns = Math.max(ta.getInteger(R.styleable.ActionBar_columns, MIN_COLUMNS),
+                MIN_COLUMNS);
+        ta.recycle();
+
+        mActionBarWrapper = findViewById(R.id.action_bar_wrapper);
+        mRowsContainer = findViewById(R.id.rows_container);
+        mNumRows = mRowsContainer.getChildCount();
+        mSlots = new FrameLayout[mNumColumns * mNumRows];
+
+        for (int i = 0; i < mNumRows; i++) {
+            // Slots are reserved in reverse order (first slots are in the bottom row)
+            ViewGroup mRow = (ViewGroup) mRowsContainer.getChildAt(mNumRows - i - 1);
+            // Inflate space on the left
+            Space space = new Space(context);
+            mRow.addView(space);
+            space.setLayoutParams(new LinearLayout.LayoutParams(0,
+                    ViewGroup.LayoutParams.MATCH_PARENT, SPACERS_WEIGHT));
+            // Inflate necessary number of columns
+            for (int j = 0; j < mNumColumns; j++) {
+                int pos = i * mNumColumns + j;
+                mSlots[pos] = (FrameLayout) inflate(context, R.layout.action_bar_slot, null);
+                mSlots[pos].setLayoutParams(new LinearLayout.LayoutParams(0,
+                        ViewGroup.LayoutParams.MATCH_PARENT, 1f));
+                mRow.addView(mSlots[pos]);
+            }
+            // Inflate space on the right
+            space = new Space(context);
+            mRow.addView(space);
+            space.setLayoutParams(new LinearLayout.LayoutParams(0,
+                    ViewGroup.LayoutParams.MATCH_PARENT, SPACERS_WEIGHT));
+        }
+
+        mDefaultExpandCollapseView = createIconButton(context, R.drawable.ic_overflow);
+        mDefaultExpandCollapseView.setContentDescription(context.getString(
+                R.string.action_bar_expand_collapse_button));
+        mDefaultExpandCollapseView.setOnClickListener(v -> onExpandCollapse());
+    }
+
+    /**
+     * Returns an index in the {@link #mSlots} array, given a well-known slot position.
+     */
+    private int getSlotIndex(@SlotPosition int slotPosition) {
+        switch (slotPosition) {
+            case SLOT_MAIN:
+                return mNumColumns / 2;
+            case SLOT_LEFT:
+                return mNumColumns < 3 ? -1 : (mNumColumns / 2) - 1;
+            case SLOT_RIGHT:
+                return mNumColumns < 2 ? -1 : (mNumColumns / 2) + 1;
+            case SLOT_EXPAND_COLLAPSE:
+                return mNumColumns - 1;
+            default:
+                throw new IllegalArgumentException("Unknown position: " + slotPosition);
+        }
+    }
+
+    /**
+     * Sets or clears the view to be displayed at a particular position.
+     *
+     * @param view view to be displayed, or null to leave the position available.
+     * @param slotPosition position to update
+     */
+    public void setView(@Nullable View view, @SlotPosition int slotPosition) {
+        if (view != null) {
+            mFixedViews.put(slotPosition, view);
+        } else {
+            mFixedViews.remove(slotPosition);
+        }
+        updateViewsLayout();
+    }
+
+    /**
+     * Sets the view to use for the expand/collapse action. If not provided, a default
+     * {@link ImageButton} will be used. The provided {@link View} should be able be able to display
+     * changes in the "activated" state appropriately.
+     *
+     * @param view {@link View} to use for the expand/collapse action.
+     */
+    public void setExpandCollapseView(@NonNull View view) {
+        mExpandCollapseView = view;
+        mExpandCollapseView.setOnClickListener(v -> onExpandCollapse());
+        updateViewsLayout();
+    }
+
+    private View getExpandCollapseView() {
+        return mExpandCollapseView != null ? mExpandCollapseView : mDefaultExpandCollapseView;
+    }
+
+    private ImageButton createIconButton(Context context, @DrawableRes int iconResId) {
+        ImageButton button = (ImageButton) inflate(context, R.layout.action_bar_button, null);
+        Drawable icon = context.getDrawable(iconResId);
+        button.setImageDrawable(icon);
+        return button;
+    }
+
+    /**
+     * Sets the views to include in each available slot of the action bar. Slots will be filled from
+     * start to end (i.e: left to right) and from bottom to top. If more views than available slots
+     * are provided, all extra views will be ignored.
+     *
+     * @param views array of views to include in each available slot.
+     */
+    public void setViews(@Nullable View[] views) {
+        mViews = views;
+        updateViewsLayout();
+    }
+
+    private void updateViewsLayout() {
+        // Prepare an array of positions taken
+        int totalSlots = mSlots.length;
+        View[] slotViews = new View[totalSlots];
+
+        // Take all known positions
+        for (int i = 0; i < mFixedViews.size(); i++) {
+            int index = getSlotIndex(mFixedViews.keyAt(i));
+            if (index >= 0 && index < slotViews.length) {
+                slotViews[index] = mFixedViews.valueAt(i);
+            }
+        }
+
+        // Set all views using both the fixed and flexible positions
+        int expandCollapseIndex = getSlotIndex(SLOT_EXPAND_COLLAPSE);
+        int lastUsedIndex = 0;
+        int viewsIndex = 0;
+        for (int i = 0; i < totalSlots; i++) {
+            View viewToUse = null;
+
+            if (slotViews[i] != null) {
+                // If there is a view assigned for this slot, use it.
+                viewToUse = slotViews[i];
+            } else if (i == expandCollapseIndex && mViews != null
+                    && viewsIndex < mViews.length - 1) {
+                // If this is the expand/collapse slot, use the corresponding view
+                viewToUse = getExpandCollapseView();
+            } else if (mViews != null && viewsIndex < mViews.length) {
+                // Otherwise, if the slot is not reserved, and if we still have views to assign,
+                // take one and assign it to this slot.
+                viewToUse = mViews[viewsIndex];
+                viewsIndex++;
+            }
+            setView(viewToUse, mSlots[i]);
+            if (viewToUse != null) {
+                lastUsedIndex = i;
+            }
+        }
+
+        mNumExtraRowsInUse = lastUsedIndex / mNumColumns;
+    }
+
+    private void setView(@Nullable View view, FrameLayout container) {
+        container.removeAllViews();
+        if (view != null) {
+            container.addView(view);
+            container.setVisibility(VISIBLE);
+            view.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER));
+        } else {
+            container.setVisibility(INVISIBLE);
+        }
+    }
+
+    private void onExpandCollapse() {
+        mIsExpanded = !mIsExpanded;
+        mSlots[getSlotIndex(SLOT_EXPAND_COLLAPSE)].setActivated(mIsExpanded);
+
+        int animationDuration = getContext().getResources().getInteger(mIsExpanded
+                ? R.integer.car_action_bar_expand_anim_duration
+                : R.integer.car_action_bar_collapse_anim_duration);
+        TransitionSet set = new TransitionSet()
+                .addTransition(new ChangeBounds())
+                .addTransition(new Fade())
+                .setDuration(animationDuration)
+                .setInterpolator(new FastOutSlowInInterpolator());
+        TransitionManager.beginDelayedTransition(mActionBarWrapper, set);
+        for (int i = 0; i < mNumExtraRowsInUse; i++) {
+            mRowsContainer.getChildAt(i).setVisibility(mIsExpanded ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    /**
+     * Returns the view assigned to the given row and column, after layout.
+     *
+     * @param rowIdx row index from 0 being the top row, and {@link #mNumRows{ -1 being the bottom
+     * row.
+     * @param colIdx column index from 0 on start (left), to {@link #mNumColumns} on end (right)
+     */
+    @VisibleForTesting
+    @Nullable
+    View getViewAt(int rowIdx, int colIdx) {
+        if (rowIdx < 0 || rowIdx > mRowsContainer.getChildCount()) {
+            throw new IllegalArgumentException(String.format((Locale) null,
+                    "Row index out of range (requested: %d, max: %d)",
+                    rowIdx, mRowsContainer.getChildCount()));
+        }
+        if (colIdx < 0 || colIdx > mNumColumns) {
+            throw new IllegalArgumentException(String.format((Locale) null,
+                    "Column index out of range (requested: %d, max: %d)",
+                    colIdx, mNumColumns));
+        }
+        FrameLayout slot = (FrameLayout) ((LinearLayout) mRowsContainer.getChildAt(rowIdx))
+                .getChildAt(colIdx + 1);
+        return slot.getChildCount() > 0 ? slot.getChildAt(0) : null;
+    }
+}
diff --git a/samples/SupportCarDemos/src/main/AndroidManifest.xml b/samples/SupportCarDemos/src/main/AndroidManifest.xml
index f976df6..b1d5820 100644
--- a/samples/SupportCarDemos/src/main/AndroidManifest.xml
+++ b/samples/SupportCarDemos/src/main/AndroidManifest.xml
@@ -61,6 +61,18 @@
             <meta-data android:name="android.support.PARENT_ACTIVITY"
                        android:value=".SupportCarDemoActivity" />
         </activity>
+
+        <activity android:name=".ActionBarActivity"
+            android:label="ActionBar"
+            android:parentActivityName=".SupportCarDemoActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+            <meta-data android:name="android.support.PARENT_ACTIVITY"
+                android:value=".SupportCarDemoActivity" />
+        </activity>
+
     </application>
 </manifest>
 
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ActionBarActivity.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ActionBarActivity.java
new file mode 100644
index 0000000..2adfa24
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ActionBarActivity.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package com.example.androidx.car;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.DrawableRes;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.ImageButton;
+
+import androidx.car.widget.ActionBar;
+
+/**
+ * Demo activity for ActionBar
+ */
+public class ActionBarActivity extends FragmentActivity {
+    private ActionBar mActionPanel;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_action_bar);
+        mActionPanel = findViewById(R.id.action_panel);
+        mActionPanel.setView(createButton(this, R.drawable.ic_play),
+                ActionBar.SLOT_MAIN);
+        ImageButton skpPrevious = createButton(this, R.drawable.ic_skip_next);
+        skpPrevious.setVisibility(View.GONE);
+        mActionPanel.setView(skpPrevious, ActionBar.SLOT_LEFT);
+        mActionPanel.setView(createButton(this, R.drawable.ic_skip_next),
+                ActionBar.SLOT_RIGHT);
+        mActionPanel.setViews(new ImageButton[]{
+                createButton(this, R.drawable.ic_queue_music),
+                createButton(this, R.drawable.ic_overflow),
+                createButton(this, R.drawable.ic_overflow),
+                createButton(this, R.drawable.ic_overflow),
+                createButton(this, R.drawable.ic_overflow),
+                createButton(this, R.drawable.ic_overflow)
+        });
+    }
+
+    private ImageButton createButton(Context context, @DrawableRes int iconResId) {
+        ImageButton button = new ImageButton(context, null,
+                androidx.car.R.style.Widget_Car_Button_ActionBar);
+        button.setImageDrawable(context.getDrawable(iconResId));
+        return button;
+    }
+}
diff --git a/samples/SupportCarDemos/src/main/res/drawable/ic_play.xml b/samples/SupportCarDemos/src/main/res/drawable/ic_play.xml
new file mode 100644
index 0000000..268104a
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/drawable/ic_play.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:name="ic_play"
+    android:width="44dp"
+    android:viewportWidth="44"
+    android:height="44dp"
+    android:viewportHeight="44" >
+    <group
+        android:name="group"
+        android:translateX="25.025"
+        android:translateY="22"
+        android:scaleX="0.08892"
+        android:scaleY="0.08892"
+        android:rotation="90" >
+        <group
+            android:name="group_pivot"
+            android:translateX="0.3042"
+            android:translateY="-2.99512" >
+            <group
+                android:name="rectangle_02" >
+                <path
+                    android:name="rectangle_02_path"
+                    android:pathData="M -0.25,-112.634796143 c 0.0,0.0 -26.3583984375,231.259857178 -26.3583984375,231.259857178 c 0.0,0.0 172.608398438,-0.00005 172.608398438,-0.00005 c 0.0,0.0 -146.125,-231.259750366 -146.125,-231.259750366 c 0.0,0.0 -0.125,-0.00006 -0.125,-0.00006 Z"
+                    android:fillColor="#FF000000" />
+            </group>
+            <group
+                android:name="rectangle_01"
+                android:translateX="-138.9834" >
+                <path
+                    android:name="rectangle_01_path"
+                    android:pathData="M 138.5,-112.634811401 c 0.0,0.0 -146.125,231.259811401 -146.125,231.259811401 c 0.0,0.0 172.608398438,-0.00005 172.608398438,-0.00005 c 0.0,0.0 -26.3583984375,-231.25970459 -26.3583984375,-231.25970459 c 0.0,0.0 -0.125,-0.00006 -0.125,-0.00006 Z"
+                    android:fillColor="#FF000000" />
+            </group>
+        </group>
+    </group>
+</vector>
diff --git a/samples/SupportCarDemos/src/main/res/drawable/ic_queue_music.xml b/samples/SupportCarDemos/src/main/res/drawable/ic_queue_music.xml
new file mode 100644
index 0000000..d3db138
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/drawable/ic_queue_music.xml
@@ -0,0 +1,4 @@
+<vector android:height="44dp" android:viewportHeight="24.0"
+    android:viewportWidth="24.0" android:width="44dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#000000" android:pathData="M15,6L3,6v2h12L15,6zM15,10L3,10v2h12v-2zM3,16h8v-2L3,14v2zM17,6v8.18c-0.31,-0.11 -0.65,-0.18 -1,-0.18 -1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3L19,8h3L22,6h-5z"/>
+</vector>
diff --git a/samples/SupportCarDemos/src/main/res/drawable/ic_skip_next.xml b/samples/SupportCarDemos/src/main/res/drawable/ic_skip_next.xml
new file mode 100644
index 0000000..81abf37
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/drawable/ic_skip_next.xml
@@ -0,0 +1,4 @@
+<vector android:height="44dp" android:viewportHeight="24.0"
+    android:viewportWidth="24.0" android:width="44dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#000000" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
+</vector>
diff --git a/samples/SupportCarDemos/src/main/res/drawable/ic_skip_previous.xml b/samples/SupportCarDemos/src/main/res/drawable/ic_skip_previous.xml
new file mode 100644
index 0000000..6b3b55d
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/drawable/ic_skip_previous.xml
@@ -0,0 +1,4 @@
+<vector android:height="44dp" android:viewportHeight="24.0"
+    android:viewportWidth="24.0" android:width="44dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#000000" android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/>
+</vector>
diff --git a/samples/SupportCarDemos/src/main/res/layout/activity_action_bar.xml b/samples/SupportCarDemos/src/main/res/layout/activity_action_bar.xml
new file mode 100644
index 0000000..f0215a9
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/layout/activity_action_bar.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout 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="@color/cardview_dark_background">
+
+    <androidx.car.widget.ActionBar
+        android:id="@+id/action_panel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="@dimen/car_margin"
+        android:layout_marginRight="@dimen/car_margin"
+        android:layout_marginBottom="@dimen/car_padding_2"
+        android:layout_alignParentBottom="true"
+        app:columns="5" />
+
+</RelativeLayout>
\ No newline at end of file