[go: nahoru, domu]

Merge "Pane Template changes - deprecate title, headerAction, actionStrip, replace them with Header model" into androidx-main
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/common/PlaceDetailsScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/common/PlaceDetailsScreen.java
index d0f0d11..28d1644 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/common/PlaceDetailsScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/common/PlaceDetailsScreen.java
@@ -17,7 +17,6 @@
 package androidx.car.app.sample.showcase.common.common;
 
 import static androidx.car.app.CarToast.LENGTH_LONG;
-import static androidx.car.app.model.Action.BACK;
 
 import android.content.Intent;
 import android.net.Uri;
@@ -29,6 +28,7 @@
 import androidx.car.app.Screen;
 import androidx.car.app.model.Action;
 import androidx.car.app.model.CarColor;
+import androidx.car.app.model.Header;
 import androidx.car.app.model.Pane;
 import androidx.car.app.model.PaneTemplate;
 import androidx.car.app.model.Row;
@@ -79,8 +79,10 @@
                                         .build());
 
         return new PaneTemplate.Builder(paneBuilder.build())
-                .setTitle(mPlace.title)
-                .setHeaderAction(BACK)
+                .setHeader(new Header.Builder()
+                        .setTitle(mPlace.title)
+                        .setStartHeaderAction(Action.BACK)
+                        .build())
                 .build();
     }
 
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/settings/CarHardwareInfoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/settings/CarHardwareInfoScreen.java
index 8a14d77..6a1e783 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/settings/CarHardwareInfoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/settings/CarHardwareInfoScreen.java
@@ -30,6 +30,7 @@
 import androidx.car.app.hardware.info.EnergyProfile;
 import androidx.car.app.hardware.info.Model;
 import androidx.car.app.model.Action;
+import androidx.car.app.model.Header;
 import androidx.car.app.model.Pane;
 import androidx.car.app.model.PaneTemplate;
 import androidx.car.app.model.Row;
@@ -207,8 +208,10 @@
             paneBuilder.setLoading(true);
         }
         return new PaneTemplate.Builder(paneBuilder.build())
-                .setHeaderAction(Action.BACK)
-                .setTitle(getCarContext().getString(R.string.car_hardware_info))
+                .setHeader(new Header.Builder()
+                        .setStartHeaderAction(Action.BACK)
+                        .setTitle(getCarContext().getString(R.string.car_hardware_info))
+                        .build())
                 .build();
     }
 
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/PaneTemplateDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/PaneTemplateDemoScreen.java
index baac535..4a6ef14 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/PaneTemplateDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/PaneTemplateDemoScreen.java
@@ -30,9 +30,9 @@
 import androidx.car.app.Screen;
 import androidx.car.app.constraints.ConstraintManager;
 import androidx.car.app.model.Action;
-import androidx.car.app.model.ActionStrip;
 import androidx.car.app.model.CarColor;
 import androidx.car.app.model.CarIcon;
+import androidx.car.app.model.Header;
 import androidx.car.app.model.Pane;
 import androidx.car.app.model.PaneTemplate;
 import androidx.car.app.model.Row;
@@ -135,26 +135,25 @@
                                 .build());
 
         return new PaneTemplate.Builder(paneBuilder.build())
-                .setHeaderAction(Action.BACK)
-                .setActionStrip(
-                        new ActionStrip.Builder()
-                                .addAction(new Action.Builder()
-                                        .setTitle(getCarContext().getString(
-                                                R.string.commute_action_title))
-                                        .setIcon(
-                                                new CarIcon.Builder(mCommuteIcon)
-                                                        .setTint(CarColor.BLUE)
-                                                        .build())
-                                        .setOnClickListener(
-                                                () -> CarToast.makeText(
-                                                                getCarContext(),
-                                                                getCarContext().getString(
-                                                                        R.string.commute_toast_msg),
-                                                                LENGTH_SHORT)
-                                                        .show())
-                                        .build())
+                .setHeader(new Header.Builder()
+                        .setTitle(getCarContext().getString(R.string.pane_template_demo_title))
+                        .setStartHeaderAction(Action.BACK)
+                        .addEndHeaderAction(new Action.Builder()
+                                .setTitle(getCarContext().getString(
+                                        R.string.commute_action_title))
+                                .setIcon(
+                                        new CarIcon.Builder(mCommuteIcon)
+                                                .setTint(CarColor.BLUE)
+                                                .build())
+                                .setOnClickListener(
+                                        () -> CarToast.makeText(
+                                                        getCarContext(),
+                                                        getCarContext().getString(
+                                                                R.string.commute_toast_msg),
+                                                        LENGTH_SHORT)
+                                                .show())
                                 .build())
-                .setTitle(getCarContext().getString(R.string.pane_template_demo_title))
+                        .build())
                 .build();
     }
 }
diff --git a/car/app/app/api/current.txt b/car/app/app/api/current.txt
index 435326a..8d4fd0f 100644
--- a/car/app/app/api/current.txt
+++ b/car/app/app/api/current.txt
@@ -1505,18 +1505,20 @@
   }
 
   @SuppressCompatibility @androidx.car.app.annotations.CarProtocol public final class PaneTemplate implements androidx.car.app.model.Template {
-    method public androidx.car.app.model.ActionStrip? getActionStrip();
-    method public androidx.car.app.model.Action? getHeaderAction();
+    method @Deprecated public androidx.car.app.model.ActionStrip? getActionStrip();
+    method @androidx.car.app.annotations.RequiresCarApi(7) public androidx.car.app.model.Header? getHeader();
+    method @Deprecated public androidx.car.app.model.Action? getHeaderAction();
     method public androidx.car.app.model.Pane getPane();
-    method public androidx.car.app.model.CarText? getTitle();
+    method @Deprecated public androidx.car.app.model.CarText? getTitle();
   }
 
   public static final class PaneTemplate.Builder {
     ctor public PaneTemplate.Builder(androidx.car.app.model.Pane);
     method public androidx.car.app.model.PaneTemplate build();
-    method public androidx.car.app.model.PaneTemplate.Builder setActionStrip(androidx.car.app.model.ActionStrip);
-    method public androidx.car.app.model.PaneTemplate.Builder setHeaderAction(androidx.car.app.model.Action);
-    method public androidx.car.app.model.PaneTemplate.Builder setTitle(CharSequence);
+    method @Deprecated public androidx.car.app.model.PaneTemplate.Builder setActionStrip(androidx.car.app.model.ActionStrip);
+    method @androidx.car.app.annotations.RequiresCarApi(7) public androidx.car.app.model.PaneTemplate.Builder setHeader(androidx.car.app.model.Header);
+    method @Deprecated public androidx.car.app.model.PaneTemplate.Builder setHeaderAction(androidx.car.app.model.Action);
+    method @Deprecated public androidx.car.app.model.PaneTemplate.Builder setTitle(CharSequence);
   }
 
   @SuppressCompatibility @androidx.car.app.annotations.CarProtocol public final class ParkedOnlyOnClickListener implements androidx.car.app.model.OnClickListener {
diff --git a/car/app/app/api/restricted_current.txt b/car/app/app/api/restricted_current.txt
index 435326a..8d4fd0f 100644
--- a/car/app/app/api/restricted_current.txt
+++ b/car/app/app/api/restricted_current.txt
@@ -1505,18 +1505,20 @@
   }
 
   @SuppressCompatibility @androidx.car.app.annotations.CarProtocol public final class PaneTemplate implements androidx.car.app.model.Template {
-    method public androidx.car.app.model.ActionStrip? getActionStrip();
-    method public androidx.car.app.model.Action? getHeaderAction();
+    method @Deprecated public androidx.car.app.model.ActionStrip? getActionStrip();
+    method @androidx.car.app.annotations.RequiresCarApi(7) public androidx.car.app.model.Header? getHeader();
+    method @Deprecated public androidx.car.app.model.Action? getHeaderAction();
     method public androidx.car.app.model.Pane getPane();
-    method public androidx.car.app.model.CarText? getTitle();
+    method @Deprecated public androidx.car.app.model.CarText? getTitle();
   }
 
   public static final class PaneTemplate.Builder {
     ctor public PaneTemplate.Builder(androidx.car.app.model.Pane);
     method public androidx.car.app.model.PaneTemplate build();
-    method public androidx.car.app.model.PaneTemplate.Builder setActionStrip(androidx.car.app.model.ActionStrip);
-    method public androidx.car.app.model.PaneTemplate.Builder setHeaderAction(androidx.car.app.model.Action);
-    method public androidx.car.app.model.PaneTemplate.Builder setTitle(CharSequence);
+    method @Deprecated public androidx.car.app.model.PaneTemplate.Builder setActionStrip(androidx.car.app.model.ActionStrip);
+    method @androidx.car.app.annotations.RequiresCarApi(7) public androidx.car.app.model.PaneTemplate.Builder setHeader(androidx.car.app.model.Header);
+    method @Deprecated public androidx.car.app.model.PaneTemplate.Builder setHeaderAction(androidx.car.app.model.Action);
+    method @Deprecated public androidx.car.app.model.PaneTemplate.Builder setTitle(CharSequence);
   }
 
   @SuppressCompatibility @androidx.car.app.annotations.CarProtocol public final class ParkedOnlyOnClickListener implements androidx.car.app.model.OnClickListener {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/PaneTemplate.java b/car/app/app/src/main/java/androidx/car/app/model/PaneTemplate.java
index 3a1a8e6..bacbf416 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/PaneTemplate.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/PaneTemplate.java
@@ -26,8 +26,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.car.app.annotations.CarProtocol;
-import androidx.car.app.model.constraints.CarTextConstraints;
 import androidx.car.app.annotations.KeepFields;
+import androidx.car.app.annotations.RequiresCarApi;
+import androidx.car.app.model.constraints.CarTextConstraints;
 
 import java.util.Collections;
 import java.util.Objects;
@@ -50,22 +51,55 @@
 @CarProtocol
 @KeepFields
 public final class PaneTemplate implements Template {
+
+    /**
+     * @deprecated use {@link Header.Builder#setTitle(CarText)}; mHeader replaces the need
+     * for this field.
+     */
+    @Deprecated
     @Nullable
     private final CarText mTitle;
     @Nullable
     private final Pane mPane;
+    /**
+     * @deprecated use {@link Header.Builder#setStartHeaderAction(Action)}; mHeader replaces the
+     * need for this field.
+     */
+    @Deprecated
     @Nullable
     private final Action mHeaderAction;
+    /**
+     * @deprecated use {@link Header.Builder#addEndHeaderAction(Action)} for each action; mHeader
+     * replaces the need for this field.
+     */
+    @Deprecated
     @Nullable
     private final ActionStrip mActionStrip;
 
     /**
+     * Represents a Header object to set the startHeaderAction, the title and the endHeaderActions
+     *
+     * @see MessageTemplate.Builder#setHeader(Header)
+     */
+    @Nullable
+    @RequiresCarApi(7)
+    private final Header mHeader;
+
+
+    /**
      * Returns the title of the template or {@code null} if not set.
      *
      * @see Builder#setTitle(CharSequence)
+     *
+     * @deprecated use {@link Header.Builder#setTitle(CarText)}; mHeader replaces the need
+     * for this field.
      */
+    @Deprecated
     @Nullable
     public CarText getTitle() {
+        if (mHeader != null && mHeader.getTitle() != null) {
+            return mHeader.getTitle();
+        }
         return mTitle;
     }
 
@@ -74,9 +108,16 @@
      * {@code null} if not set.
      *
      * @see Builder#setHeaderAction(Action)
+     *
+     * @deprecated use {@link Header.Builder#setStartHeaderAction(Action)}; mHeader replaces the
+     * need for this field.
      */
+    @Deprecated
     @Nullable
     public Action getHeaderAction() {
+        if (mHeader != null && mHeader.getStartHeaderAction() != null) {
+            return mHeader.getStartHeaderAction();
+        }
         return mHeaderAction;
     }
 
@@ -84,9 +125,20 @@
      * Returns the {@link ActionStrip} for this template or {@code null} if not set.
      *
      * @see Builder#setActionStrip(ActionStrip)
+     *
+     * @deprecated use {@link Header.Builder#addEndHeaderAction(Action) for each action}; mHeader
+     * replaces the need for this field.
      */
+    @Deprecated
     @Nullable
     public ActionStrip getActionStrip() {
+        if (mHeader != null && !mHeader.getEndHeaderActions().isEmpty()) {
+            ActionStrip.Builder actionStripBuilder = new ActionStrip.Builder();
+            for (Action action: mHeader.getEndHeaderActions()) {
+                actionStripBuilder.addAction(action);
+            }
+            return actionStripBuilder.build();
+        }
         return mActionStrip;
     }
 
@@ -100,6 +152,17 @@
         return requireNonNull(mPane);
     }
 
+    /**
+     * Returns the {@link Header} to display in this template.
+     *
+     * @see PaneTemplate.Builder#setHeader(Header)
+     */
+    @RequiresCarApi(7)
+    @Nullable
+    public Header getHeader() {
+        return mHeader;
+    }
+
     @NonNull
     @Override
     public String toString() {
@@ -108,7 +171,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mTitle, mPane, mHeaderAction, mActionStrip);
+        return Objects.hash(mTitle, mPane, mHeaderAction, mActionStrip, mHeader);
     }
 
     @Override
@@ -124,7 +187,8 @@
         return Objects.equals(mTitle, otherTemplate.mTitle)
                 && Objects.equals(mPane, otherTemplate.mPane)
                 && Objects.equals(mHeaderAction, otherTemplate.mHeaderAction)
-                && Objects.equals(mActionStrip, otherTemplate.mActionStrip);
+                && Objects.equals(mActionStrip, otherTemplate.mActionStrip)
+                && Objects.equals(mHeader, otherTemplate.mHeader);
     }
 
     PaneTemplate(Builder builder) {
@@ -132,6 +196,7 @@
         mPane = builder.mPane;
         mHeaderAction = builder.mHeaderAction;
         mActionStrip = builder.mActionStrip;
+        mHeader = builder.mHeader;
     }
 
     /** Constructs an empty instance, used by serialization code. */
@@ -140,6 +205,7 @@
         mPane = null;
         mHeaderAction = null;
         mActionStrip = null;
+        mHeader = null;
     }
 
     /** A builder of {@link PaneTemplate}. */
@@ -151,6 +217,8 @@
         Action mHeaderAction;
         @Nullable
         ActionStrip mActionStrip;
+        @Nullable
+        Header mHeader;
 
         /**
          * Sets the title of the template.
@@ -163,7 +231,10 @@
          * @throws NullPointerException     if {@code title} is {@code null}
          * @throws IllegalArgumentException if {@code title} contains unsupported spans
          * @see CarText
+         *
+         * @deprecated Use {@link Header.Builder#setTitle(CarText)}
          */
+        @Deprecated
         @NonNull
         public Builder setTitle(@NonNull CharSequence title) {
             mTitle = CarText.create(requireNonNull(title));
@@ -172,6 +243,34 @@
         }
 
         /**
+         * Sets the {@link Header} for this template.
+         *
+         * <p>The end header actions will show up differently inside vs outside of a map template.
+         * See {@link Header.Builder#addEndHeaderAction} for more details.</p>
+         *
+         * @throws NullPointerException if {@code header} is null
+         */
+        @NonNull
+        @RequiresCarApi(7)
+        public Builder setHeader(@NonNull Header header) {
+            if (header.getStartHeaderAction() != null) {
+                mHeaderAction = header.getStartHeaderAction();
+            }
+            if (header.getTitle() != null) {
+                mTitle = header.getTitle();
+            }
+            if (!header.getEndHeaderActions().isEmpty()) {
+                ActionStrip.Builder actionStripBuilder = new ActionStrip.Builder();
+                for (Action action: header.getEndHeaderActions()) {
+                    actionStripBuilder.addAction(action);
+                }
+                mActionStrip = actionStripBuilder.build();
+            }
+            mHeader = header;
+            return this;
+        }
+
+        /**
          * Sets the {@link Action} that will be displayed in the header of the template.
          *
          * <p>Unless set with this method, the template will not have a header action.
@@ -184,7 +283,10 @@
          * @throws IllegalArgumentException if {@code headerAction} does not meet the template's
          *                                  requirements
          * @throws NullPointerException     if {@code headerAction} is {@code null}
+         *
+         * @deprecated Use {@link Header.Builder#setStartHeaderAction(Action)}
          */
+        @Deprecated
         @NonNull
         public Builder setHeaderAction(@NonNull Action headerAction) {
             ACTIONS_CONSTRAINTS_HEADER.validateOrThrow(
@@ -206,7 +308,10 @@
          *
          * @throws IllegalArgumentException if {@code actionStrip} does not meet the requirements
          * @throws NullPointerException     if {@code actionStrip} is {@code null}
+         *
+         * @deprecated Use {@link Header.Builder#addEndHeaderAction(Action) for each action}
          */
+        @Deprecated
         @NonNull
         public Builder setActionStrip(@NonNull ActionStrip actionStrip) {
             ACTIONS_CONSTRAINTS_SIMPLE.validateOrThrow(requireNonNull(actionStrip).getActions());
diff --git a/car/app/app/src/test/java/androidx/car/app/model/PaneTemplateTest.java b/car/app/app/src/test/java/androidx/car/app/model/PaneTemplateTest.java
index 6907a96..272e5ef 100644
--- a/car/app/app/src/test/java/androidx/car/app/model/PaneTemplateTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/model/PaneTemplateTest.java
@@ -33,39 +33,43 @@
 @RunWith(RobolectricTestRunner.class)
 @DoNotInstrument
 public class PaneTemplateTest {
+    Header mHeader = new Header.Builder()
+            .setTitle("Title")
+            .setStartHeaderAction(Action.BACK)
+            .addEndHeaderAction(Action.APP_ICON)
+            .build();
 
     @Test
     public void pane_moreThanMaxActions_throws() {
         assertThrows(
                 IllegalArgumentException.class,
-                () -> new PaneTemplate.Builder(TestUtils.createPane(2, 3)).setTitle(
-                        "Title").build());
+                () -> new PaneTemplate.Builder(TestUtils.createPane(2, 3))
+                        .setHeader(mHeader).build());
 
         // Positive cases.
-        new PaneTemplate.Builder(TestUtils.createPane(2, 2)).setTitle("Title").build();
+        new PaneTemplate.Builder(TestUtils.createPane(2, 2))
+                .setHeader(mHeader).build();
     }
 
     @Test
     public void paneTemplate_title_unsupportedSpans_throws() {
         CharSequence title1 = TestUtils.getCharSequenceWithClickableSpan("Title");
+
         assertThrows(
                 IllegalArgumentException.class,
-                () -> new PaneTemplate.Builder(TestUtils.createPane(2, 2)).setTitle(
-                        title1).build());
+                () -> new PaneTemplate.Builder(TestUtils.createPane(2, 2))
+                        .setHeader(createHeaderWithCustomTitle(title1)).build());
 
         CharSequence title2 = TestUtils.getCharSequenceWithColorSpan("Title");
         assertThrows(
                 IllegalArgumentException.class,
-                () -> new PaneTemplate.Builder(TestUtils.createPane(2, 2)).setTitle(
-                        title2).build());
-
-        // CarIconSpan assert no exceptions
-        CharSequence title3 = TestUtils.getCharSequenceWithIconSpan("Title");
-        new PaneTemplate.Builder(TestUtils.createPane(2, 2)).setTitle(title3).build();
+                () -> new PaneTemplate.Builder(TestUtils.createPane(2, 2))
+                        .setHeader(createHeaderWithCustomTitle(title2)).build());
 
         // DistanceSpan and DurationSpan assert no exceptions
         CharSequence title4 = TestUtils.getCharSequenceWithDistanceAndDurationSpans("Title");
-        new PaneTemplate.Builder(TestUtils.createPane(2, 2)).setTitle(title4).build();
+        new PaneTemplate.Builder(TestUtils.createPane(2, 2))
+                .setHeader(createHeaderWithCustomTitle(title4)).build();
     }
 
     @Test
@@ -75,25 +79,25 @@
         Pane pane1 = getPane().addAction(action1).build();
         assertThrows(
                 IllegalArgumentException.class,
-                () -> new PaneTemplate.Builder(pane1).setTitle("Title").build());
+                () -> new PaneTemplate.Builder(pane1).setHeader(mHeader).build());
 
         CarText title2 = TestUtils.getCarTextVariantsWithDistanceAndDurationSpans("Title");
         Action action2 = new Action.Builder().setTitle(title2).build();
         Pane pane2 = getPane().addAction(action2).build();
         assertThrows(
                 IllegalArgumentException.class,
-                () -> new PaneTemplate.Builder(pane2).setTitle("Title").build());
+                () -> new PaneTemplate.Builder(pane2).setHeader(mHeader).build());
 
         // DurationSpan and DistanceSpan do not throw
         CharSequence title3 = TestUtils.getCharSequenceWithColorSpan("Title");
         Action action3 = new Action.Builder().setTitle(title3).build();
         Pane pane3 = getPane().addAction(action3).build();
-        new PaneTemplate.Builder(pane3).setTitle("Title").build();
+        new PaneTemplate.Builder(pane3).setHeader(mHeader).build();
 
         CarText title4 = TestUtils.getCarTextVariantsWithColorSpan("Title");
         Action action4 = new Action.Builder().setTitle(title4).build();
         Pane pane4 = getPane().addAction(action4).build();
-        new PaneTemplate.Builder(pane4).setTitle("Title").build();
+        new PaneTemplate.Builder(pane4).setHeader(mHeader).build();
     }
 
     @Test
@@ -108,12 +112,12 @@
                 () ->
                         new PaneTemplate.Builder(
                                 new Pane.Builder().addRow(rowExceedsMaxTexts).build())
-                                .setTitle("Title")
+                                .setHeader(mHeader)
                                 .build());
 
         // Positive cases.
         new PaneTemplate.Builder(new Pane.Builder().addRow(rowMeetingMaxTexts).build())
-                .setTitle("Title")
+                .setHeader(mHeader)
                 .build();
     }
 
@@ -136,7 +140,7 @@
         assertThrows(
                 IllegalArgumentException.class,
                 () -> new PaneTemplate.Builder(paneExceedsMaxPrimaryAction)
-                        .setTitle("Title")
+                        .setHeader(mHeader)
                         .build());
     }
 
@@ -155,26 +159,23 @@
                 () ->
                         new PaneTemplate.Builder(
                                 new Pane.Builder().addRow(rowWithClickListener).build())
-                                .setTitle("Title")
+                                .setHeader(mHeader)
                                 .build());
 
         // Positive cases.
         new PaneTemplate.Builder(new Pane.Builder().addRow(rowWithToggle).build())
-                                .setTitle("Title")
+                                .setHeader(mHeader)
                                 .build();
 
         new PaneTemplate.Builder(new Pane.Builder().addRow(rowMeetingRestrictions).build())
-                .setTitle("Title")
+                .setHeader(mHeader)
                 .build();
     }
 
     @Test
     public void createInstance_emptyHeader() {
         PaneTemplate template = new PaneTemplate.Builder(getPane().build()).build();
-
-        assertThat(template.getTitle()).isNull();
-        assertThat(template.getHeaderAction()).isNull();
-        assertThat(template.getActionStrip()).isNull();
+        assertThat(template.getHeader()).isNull();
     }
 
     @Test
@@ -182,17 +183,19 @@
         CharSequence title = TestUtils.getCharSequenceWithColorSpan("Title");
         assertThrows(
                 IllegalArgumentException.class,
-                () -> new PaneTemplate.Builder(getPane().build()).setTitle(title));
+                () -> new PaneTemplate.Builder(getPane().build())
+                        .setHeader(createHeaderWithCustomTitle(title)));
 
         // DurationSpan and DistanceSpan do not throw
         CharSequence title2 = TestUtils.getCharSequenceWithDistanceAndDurationSpans("Title");
-        new PaneTemplate.Builder(getPane().build()).setTitle(title2).build();
+        new PaneTemplate.Builder(getPane().build()).setHeader(createHeaderWithCustomTitle(title2))
+                .build();
     }
 
     @Test
     public void createInstance_setPane() {
         Pane pane = getPane().build();
-        PaneTemplate template = new PaneTemplate.Builder(pane).setTitle("Title").build();
+        PaneTemplate template = new PaneTemplate.Builder(pane).setHeader(mHeader).build();
         assertThat(template.getPane()).isEqualTo(pane);
     }
 
@@ -201,113 +204,139 @@
         assertThrows(
                 IllegalArgumentException.class,
                 () ->
-                        new PaneTemplate.Builder(getPane().build())
-                                .setHeaderAction(
-                                        new Action.Builder().setTitle("Action").setOnClickListener(
-                                                () -> {
-                                                }).build()));
+                    new PaneTemplate.Builder(getPane().build())
+                            .setHeader(new Header.Builder()
+                                    .setStartHeaderAction(
+                                            new Action.Builder()
+                                                    .setTitle("Action")
+                                                    .setOnClickListener(() -> {})
+                                                    .build())
+                                    .build())
+                            .build());
+
     }
 
     @Test
     public void createInstance_setHeaderAction() {
-        PaneTemplate template = new PaneTemplate.Builder(getPane().build()).setHeaderAction(
-                Action.BACK).build();
-        assertThat(template.getHeaderAction()).isEqualTo(Action.BACK);
+        PaneTemplate template = new PaneTemplate.Builder(getPane().build())
+                .setHeader(new Header.Builder()
+                .setStartHeaderAction(Action.BACK).build())
+                .build();
+        assertThat(template.getHeader().getStartHeaderAction()).isEqualTo(Action.BACK);
     }
 
     @Test
     public void createInstance_setActionStrip() {
-        ActionStrip actionStrip = new ActionStrip.Builder().addAction(Action.BACK).build();
         PaneTemplate template =
-                new PaneTemplate.Builder(getPane().build()).setTitle("Title").setActionStrip(
-                        actionStrip).build();
-        assertThat(template.getActionStrip()).isEqualTo(actionStrip);
+                new PaneTemplate.Builder(getPane().build())
+                        .setHeader(new Header.Builder()
+                                .setTitle("Title")
+                                .addEndHeaderAction(Action.BACK)
+                                .build())
+                        .build();
+        assertThat(template.getHeader().getEndHeaderActions().get(0)).isEqualTo(Action.BACK);
     }
 
     @Test
     public void equals() {
         Pane pane = new Pane.Builder().addRow(new Row.Builder().setTitle("Title").build()).build();
-        ActionStrip actionStrip = new ActionStrip.Builder().addAction(Action.BACK).build();
-        String title = "foo";
-
         PaneTemplate template =
                 new PaneTemplate.Builder(pane)
-                        .setHeaderAction(Action.BACK)
-                        .setActionStrip(actionStrip)
-                        .setTitle(title)
+                        .setHeader(new Header.Builder()
+                                .setTitle("foo")
+                                .setStartHeaderAction(Action.BACK)
+                                .addEndHeaderAction(Action.BACK)
+                                .build())
                         .build();
 
         assertThat(template)
                 .isEqualTo(
                         new PaneTemplate.Builder(pane)
-                                .setHeaderAction(Action.BACK)
-                                .setActionStrip(actionStrip)
-                                .setTitle(title)
+                                .setHeader(new Header.Builder()
+                                        .setTitle("foo")
+                                        .setStartHeaderAction(Action.BACK)
+                                        .addEndHeaderAction(Action.BACK)
+                                        .build())
                                 .build());
     }
 
     @Test
     public void notEquals_differentPane() {
         Pane pane = new Pane.Builder().addRow(new Row.Builder().setTitle("Title").build()).build();
-        ActionStrip actionStrip = new ActionStrip.Builder().addAction(Action.BACK).build();
-        String title = "foo";
 
         PaneTemplate template =
-                new PaneTemplate.Builder(pane).setActionStrip(actionStrip).setTitle(title).build();
+                new PaneTemplate.Builder(pane)
+                        .setHeader(new Header.Builder()
+                                .setTitle("foo")
+                                .build()).build();
 
         assertThat(template)
                 .isNotEqualTo(
                         new PaneTemplate.Builder(
                                 new Pane.Builder().addRow(
                                         new Row.Builder().setTitle("Title2").build()).build())
-                                .setActionStrip(actionStrip)
-                                .setTitle(title)
-                                .build());
+                                .setHeader(new Header.Builder()
+                                        .setTitle("foo")
+                                        .addEndHeaderAction(Action.BACK)
+                                        .build()).build());
     }
 
     @Test
     public void notEquals_differentHeaderAction() {
         Pane pane = new Pane.Builder().addRow(new Row.Builder().setTitle("Title").build()).build();
 
-        PaneTemplate template = new PaneTemplate.Builder(pane).setHeaderAction(Action.BACK).build();
+        PaneTemplate template = new PaneTemplate.Builder(pane)
+                .setHeader(new Header.Builder()
+                        .setStartHeaderAction(Action.BACK)
+                        .build()).build();
 
         assertThat(template)
-                .isNotEqualTo(new PaneTemplate.Builder(pane).setHeaderAction(
-                        Action.APP_ICON).build());
+                .isNotEqualTo(new PaneTemplate.Builder(pane)
+                        .setHeader(new Header.Builder()
+                                .setStartHeaderAction(Action.APP_ICON)
+                                .build()).build());
     }
 
     @Test
-    public void notEquals_differentActionStrip() {
+    public void notEquals_differentEndHeaderActions() {
         Pane pane = new Pane.Builder().addRow(new Row.Builder().setTitle("Title").build()).build();
-        ActionStrip actionStrip = new ActionStrip.Builder().addAction(Action.BACK).build();
-        String title = "foo";
 
         PaneTemplate template =
-                new PaneTemplate.Builder(pane).setActionStrip(actionStrip).setTitle(title).build();
+                new PaneTemplate.Builder(pane)
+                        .setHeader(new Header.Builder()
+                                .setTitle("foo")
+                                .addEndHeaderAction(Action.BACK)
+                                .build())
+                        .build();
 
         assertThat(template)
                 .isNotEqualTo(
                         new PaneTemplate.Builder(pane)
-                                .setActionStrip(
-                                        new ActionStrip.Builder().addAction(
-                                                Action.APP_ICON).build())
-                                .setTitle(title)
+                                .setHeader(new Header.Builder()
+                                        .setTitle("foo")
+                                        .addEndHeaderAction(Action.APP_ICON)
+                                        .build())
                                 .build());
     }
 
     @Test
     public void notEquals_differentTitle() {
         Pane pane = new Pane.Builder().addRow(new Row.Builder().setTitle("Title").build()).build();
-        ActionStrip actionStrip = new ActionStrip.Builder().addAction(Action.BACK).build();
-        String title = "foo";
 
         PaneTemplate template =
-                new PaneTemplate.Builder(pane).setActionStrip(actionStrip).setTitle(title).build();
+                new PaneTemplate.Builder(pane)
+                        .setHeader(new Header.Builder()
+                                .setTitle("foo")
+                                .addEndHeaderAction(Action.BACK)
+                                .build()).build();
 
         assertThat(template)
                 .isNotEqualTo(
-                        new PaneTemplate.Builder(pane).setActionStrip(actionStrip).setTitle(
-                                "bar").build());
+                        new PaneTemplate.Builder(pane)
+                                .setHeader(new Header.Builder()
+                                        .setTitle("bar")
+                                        .addEndHeaderAction(Action.BACK)
+                                        .build()).build());
     }
 
     private static Pane.Builder getPane() {
@@ -315,4 +344,8 @@
         Row row2 = new Row.Builder().setTitle("Oranges").build();
         return new Pane.Builder().addRow(row1).addRow(row2);
     }
+
+    private Header createHeaderWithCustomTitle(CharSequence title) {
+        return new Header.Builder().setTitle(title).build();
+    }
 }
diff --git a/car/app/app/src/test/java/androidx/car/app/navigation/model/MapWithContentTemplateTest.java b/car/app/app/src/test/java/androidx/car/app/navigation/model/MapWithContentTemplateTest.java
index 38bf9e0..8a01460 100644
--- a/car/app/app/src/test/java/androidx/car/app/navigation/model/MapWithContentTemplateTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/navigation/model/MapWithContentTemplateTest.java
@@ -77,8 +77,11 @@
         return new PaneTemplate.Builder(new Pane.Builder()
                 .addRow(row1)
                 .build())
-                .setTitle("Title")
-                .setHeaderAction(Action.BACK)
+                .setHeader(
+                        new Header.Builder()
+                                .setTitle("Title")
+                                .setStartHeaderAction(Action.BACK)
+                                .build())
                 .build();
     }