Give the toolbar back button default behavior and split up listeners

Both of these changes are to be more consistant with existing styles.

Fixes: 141322737
Test: Manually
Change-Id: I05ad987d6979c3d0b8ec970b921b297c7106ee94
diff --git a/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedRecyclerView.java b/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedRecyclerView.java
index e9ed91f..c700d76 100644
--- a/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedRecyclerView.java
+++ b/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedRecyclerView.java
@@ -53,7 +53,7 @@
  * similar to a {@code RecyclerView} as it takes the same adapter and the layout manager.
  */
 public final class PagedRecyclerView extends RecyclerView implements
-        Toolbar.OnToolbarHeightChangeListener {
+        Toolbar.OnHeightChangedListener {
 
     private static final boolean DEBUG = false;
     private static final String TAG = "PagedRecyclerView";
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/SearchView.java b/car-ui-lib/src/com/android/car/ui/toolbar/SearchView.java
index daa7154..2e534f7 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/SearchView.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/SearchView.java
@@ -41,8 +41,7 @@
 public class SearchView extends ConstraintLayout {
     private final ImageView mIcon;
     private final EditText mSearchText;
-
-    private Set<Toolbar.Listener> mListeners = new HashSet<>();
+    private final Set<Toolbar.OnSearchListener> mListeners = new HashSet<>();
 
     public SearchView(Context context) {
         this(context, null);
@@ -101,18 +100,18 @@
 
     /**
      * Adds a listener for the search text changing.
-     * See also {@link #removeToolbarListener(Toolbar.Listener)}
+     * See also {@link #unregisterOnSearchListener(Toolbar.OnSearchListener)}
      */
-    public void addToolbarListener(Toolbar.Listener listener) {
+    public void registerOnSearchListener(Toolbar.OnSearchListener listener) {
         mListeners.add(listener);
     }
 
     /**
      * Removes a listener.
-     * See also {@link #addToolbarListener(Toolbar.Listener)}
+     * See also {@link #registerOnSearchListener(Toolbar.OnSearchListener)}
      */
-    public void removeToolbarListener(Toolbar.Listener listener) {
-        mListeners.remove(listener);
+    public boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener) {
+        return mListeners.remove(listener);
     }
 
     /**
@@ -153,7 +152,7 @@
     }
 
     private void onSearch(String query) {
-        for (Toolbar.Listener listener : mListeners) {
+        for (Toolbar.OnSearchListener listener : mListeners) {
             listener.onSearch(query);
         }
     }
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java b/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
index 258c0b8..8f309f3 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
@@ -15,8 +15,10 @@
  */
 package com.android.car.ui.toolbar;
 
+import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
@@ -52,11 +54,8 @@
  */
 public class Toolbar extends FrameLayout {
 
-    /**
-     * Callback that will be issued whenever the height of toolbar is changed.
-     */
-    public interface OnToolbarHeightChangeListener {
-
+    /** Callback that will be issued whenever the height of toolbar is changed. */
+    public interface OnHeightChangedListener {
         /**
          * Will be called when the height of the toolbar is changed.
          * @param height new height of the toolbar
@@ -64,6 +63,33 @@
         void onHeightChanged(int height);
     }
 
+    /** Back button listener */
+    public interface OnBackListener {
+        /**
+         * Invoked when the user clicks on the back button. By default, the toolbar will call
+         * the Activity's {@link android.app.Activity#onBackPressed()}. Returning true from
+         * this method will absorb the back press and prevent that behavior.
+         */
+        boolean onBack();
+    }
+
+    /** Tab selection listener */
+    public interface OnTabSelectedListener {
+        /** Called when a {@link TabLayout.Tab} is selected */
+        void onTabSelected(TabLayout.Tab tab);
+    }
+
+    /** Search listener */
+    public interface OnSearchListener {
+        /**
+         * Invoked when the user submits a search query.
+         *
+         * <p>This is called for every letter the user types, and also empty strings if the user
+         * erases everything.
+         */
+        void onSearch(String query);
+    }
+
     private static final String TAG = "CarUiToolbar";
 
     /** Enum of states the toolbar can be in. Controls what elements of the toolbar are displayed */
@@ -98,7 +124,9 @@
     private LinearLayout mMenuItemsContainer;
     private FrameLayout mCustomViewContainer;
     private View mOverflowButton;
-    private Set<Listener> mListeners = new HashSet<>();
+    private final Set<OnBackListener> mOnBackListeners = new HashSet<>();
+    private final Set<OnTabSelectedListener> mOnTabSelectedListeners = new HashSet<>();
+    private final Set<OnHeightChangedListener> mOnHeightChangedListeners = new HashSet<>();
     private SearchView mSearchView;
     private boolean mHasLogo = false;
     private boolean mShowMenuItemsWhileSearching;
@@ -115,8 +143,7 @@
     };
     private AlertDialog mOverflowDialog;
 
-    private final List<OnToolbarHeightChangeListener> mOnToolbarHeightChangeListeners =
-            new ArrayList<>();
+
 
     public Toolbar(Context context) {
         this(context, null);
@@ -201,7 +228,7 @@
         mTabLayout.addListener(new TabLayout.Listener() {
             @Override
             public void onTabSelected(TabLayout.Tab tab) {
-                forEachListener(listener -> listener.onTabSelected(tab));
+                mOnTabSelectedListeners.forEach(listener -> listener.onTabSelected(tab));
             }
         });
 
@@ -243,7 +270,7 @@
 
     /**
      * Adds a tab to this toolbar. You can listen for when it is selected via
-     * {@link #addListener(Listener)}.
+     * {@link #registerOnTabSelectedListener(OnTabSelectedListener)}.
      */
     public void addTab(TabLayout.Tab tab) {
         mTabLayout.addTab(tab);
@@ -295,7 +322,7 @@
 
     /**
      * An enum of possible styles the nav button could be in. All styles will still call
-     * {@link Listener#onBack()}.
+     * {@link OnBackListener#onBack()}.
      */
     public enum NavButtonMode {
         /** Display the nav button as a back button */
@@ -328,33 +355,11 @@
     }
 
     /**
-     * Registers a new {@link OnToolbarHeightChangeListener} to the list of listeners. Register a
-     * {@link com.android.car.ui.pagedrecyclerview.PagedRecyclerView} only if there is a toolbar at
-     * the top and a {@link com.android.car.ui.pagedrecyclerview.PagedRecyclerView} in the view and
-     * nothing else. {@link com.android.car.ui.pagedrecyclerview.PagedRecyclerView} will
-     * automatically adjust its height according to the height of the Toolbar.
-     */
-    public void registerToolbarHeightChangeListener(
-            OnToolbarHeightChangeListener listener) {
-        if (!mOnToolbarHeightChangeListeners.contains(listener)) {
-            mOnToolbarHeightChangeListeners.add(listener);
-        }
-    }
-
-    /**
-     * Unregisters a {@link OnToolbarHeightChangeListener} from the list of listeners.
-     */
-    public void unregisterToolbarHeightChangeListener(
-            OnToolbarHeightChangeListener listener) {
-        mOnToolbarHeightChangeListeners.remove(listener);
-    }
-
-    /**
      * Invokes all OnToolbarHeightChangeListener handlers registered in {@link
-     * OnToolbarHeightChangeListener}s array.
+     * OnHeightChangedListener}s array.
      */
     private void handleToolbarHeightChangeListeners(int height) {
-        mOnToolbarHeightChangeListeners.forEach(
+        mOnHeightChangedListeners.forEach(
                 listener -> listener.onHeightChanged(height));
     }
 
@@ -465,6 +470,17 @@
         return v;
     }
 
+    private Activity getActivity() {
+        Context context = getContext();
+        while (context instanceof ContextWrapper) {
+            if (context instanceof Activity) {
+                return (Activity) context;
+            }
+            context = ((ContextWrapper) context).getBaseContext();
+        }
+        return null;
+    }
+
     /**
      * Sets the state of the toolbar. This will show/hide the appropriate elements of the toolbar
      * for the desired state.
@@ -472,7 +488,20 @@
     public void setState(State state) {
         mState = state;
 
-        View.OnClickListener backClickListener = (v) -> forEachListener(Listener::onBack);
+        View.OnClickListener backClickListener = (v) -> {
+            boolean absorbed = false;
+            List<OnBackListener> listenersCopy = new ArrayList<>(mOnBackListeners);
+            for (OnBackListener listener : listenersCopy) {
+                absorbed = absorbed || listener.onBack();
+            }
+
+            if (!absorbed) {
+                Activity activity = getActivity();
+                if (activity != null) {
+                    activity.onBackPressed();
+                }
+            }
+        };
         mNavIcon.setVisibility(state != State.HOME ? VISIBLE : INVISIBLE);
         mNavIcon.setImageResource(mNavButtonMode == NavButtonMode.BACK
                 ? R.drawable.car_ui_icon_arrow_back
@@ -502,55 +531,50 @@
     }
 
     /**
-     * Toolbar listener.
+     * Registers a new {@link OnHeightChangedListener} to the list of listeners. Register a
+     * {@link com.android.car.ui.pagedrecyclerview.PagedRecyclerView} only if there is a toolbar at
+     * the top and a {@link com.android.car.ui.pagedrecyclerview.PagedRecyclerView} in the view and
+     * nothing else. {@link com.android.car.ui.pagedrecyclerview.PagedRecyclerView} will
+     * automatically adjust its height according to the height of the Toolbar.
      */
-    public interface Listener {
-        /**
-         * Invoked when the user selects an item from the tabs
-         */
-        default void onTabSelected(TabLayout.Tab item) {
-        }
-
-        /**
-         * Invoked when the user clicks on the back button
-         */
-        default void onBack() {
-        }
-
-        /**
-         * Invoked when the user submits a search query.
-         */
-        default void onSearch(String query) {
-        }
+    public void registerToolbarHeightChangeListener(
+            OnHeightChangedListener listener) {
+        mOnHeightChangedListeners.add(listener);
     }
 
-    /**
-     * Adds a {@link Listener} to this toolbar.
-     */
-    public void addListener(Listener listener) {
-        mListeners.add(listener);
-        mSearchView.addToolbarListener(listener);
+    /** Unregisters a {@link OnHeightChangedListener} from the list of listeners. */
+    public boolean unregisterToolbarHeightChangeListener(
+            OnHeightChangedListener listener) {
+        return mOnHeightChangedListeners.remove(listener);
     }
 
-    /**
-     * Removes a {@link Listener} from this toolbar.
-     */
-    public boolean removeListener(Listener listener) {
-        mSearchView.removeToolbarListener(listener);
-        return mListeners.remove(listener);
+    /** Registers a new {@link OnTabSelectedListener} to the list of listeners. */
+    public void registerOnTabSelectedListener(OnTabSelectedListener listener) {
+        mOnTabSelectedListeners.add(listener);
     }
 
-    /**
-     * {@link java.util.function.Consumer} is not available for non-java8 enabled Android targets.
-     */
-    private interface Consumer<T> {
-        void accept(T value);
+    /** Unregisters a new {@link OnTabSelectedListener} from the list of listeners. */
+    public boolean unregisterOnTabSelectedListener(OnTabSelectedListener listener) {
+        return mOnTabSelectedListeners.remove(listener);
     }
 
-    private void forEachListener(Consumer<Listener> callback) {
-        List<Listener> listenersCopy = new ArrayList<>(mListeners);
-        for (Listener listener : listenersCopy) {
-            callback.accept(listener);
-        }
+    /** Registers a new {@link OnSearchListener} to the list of listeners. */
+    public void registerOnSearchListener(OnSearchListener listener) {
+        mSearchView.registerOnSearchListener(listener);
+    }
+
+    /** Unregisters a new {@link OnSearchListener} from the list of listeners. */
+    public boolean unregisterOnSearchListener(OnSearchListener listener) {
+        return mSearchView.unregisterOnSearchListener(listener);
+    }
+
+    /** Registers a new {@link OnBackListener} to the list of listeners. */
+    public void registerOnBackListener(OnBackListener listener) {
+        mOnBackListeners.add(listener);
+    }
+
+    /** Unregisters a new {@link OnTabSelectedListener} from the list of listeners. */
+    public boolean unregisterOnBackListener(OnBackListener listener) {
+        return mOnBackListeners.remove(listener);
     }
 }
diff --git a/car-ui-lib/tests/paintbooth/res/layout/dialogs_activity.xml b/car-ui-lib/tests/paintbooth/res/layout/dialogs_activity.xml
index 46914ac..65fc43f 100644
--- a/car-ui-lib/tests/paintbooth/res/layout/dialogs_activity.xml
+++ b/car-ui-lib/tests/paintbooth/res/layout/dialogs_activity.xml
@@ -27,7 +27,8 @@
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       app:layout_constraintTop_toTopOf="parent"
-      app:title="@string/app_name"/>
+      app:title="@string/app_name"
+      app:state="subpage"/>
 
   <Button
       android:id="@+id/show_dialog_bt"
diff --git a/car-ui-lib/tests/paintbooth/res/layout/paged_recycler_view_samples.xml b/car-ui-lib/tests/paintbooth/res/layout/paged_recycler_view_samples.xml
index c965ebb..6f26d70 100644
--- a/car-ui-lib/tests/paintbooth/res/layout/paged_recycler_view_samples.xml
+++ b/car-ui-lib/tests/paintbooth/res/layout/paged_recycler_view_samples.xml
@@ -26,7 +26,8 @@
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        app:title="@string/app_name"/>
+        app:title="@string/app_name"
+        app:state="subpage"/>
 
     <com.android.car.ui.pagedrecyclerview.PagedRecyclerView
         android:id="@+id/list"
@@ -34,4 +35,4 @@
         android:layout_height="match_parent"
         android:paddingTop="100dp"/>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/DialogsActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/DialogsActivity.java
index e8ee652..a4cc271 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/DialogsActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/DialogsActivity.java
@@ -21,7 +21,6 @@
 import android.widget.Toast;
 
 import com.android.car.ui.AlertDialogBuilder;
-import com.android.car.ui.toolbar.Toolbar;
 
 /**
  * Activity that shows different dialogs from the device default theme.
@@ -50,14 +49,6 @@
 
         Button showToast = findViewById(R.id.show_toast);
         showToast.setOnClickListener(v -> showToast());
-        Toolbar toolbar = findViewById(R.id.toolbar);
-        toolbar.setState(Toolbar.State.SUBPAGE);
-        toolbar.addListener(new Toolbar.Listener() {
-            @Override
-            public void onBack() {
-                finish();
-            }
-        });
     }
 
     private void openDialog(boolean showCheckbox) {
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/PagedRecyclerViewSamples.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/PagedRecyclerViewSamples.java
index 4781f8d..0ac2aa9 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/PagedRecyclerViewSamples.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/PagedRecyclerViewSamples.java
@@ -22,7 +22,6 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 
 import com.android.car.ui.pagedrecyclerview.PagedRecyclerView;
-import com.android.car.ui.toolbar.Toolbar;
 
 import java.util.ArrayList;
 
@@ -43,15 +42,6 @@
 
         RecyclerViewAdapter adapter = new RecyclerViewAdapter(generateDummyData());
         recyclerView.setAdapter(adapter);
-
-        Toolbar toolbar = findViewById(R.id.toolbar);
-        toolbar.setState(Toolbar.State.SUBPAGE);
-        toolbar.addListener(new Toolbar.Listener() {
-            @Override
-            public void onBack() {
-                finish();
-            }
-        });
     }
 
     private ArrayList<String> generateDummyData() {