CarDrawerAdapter changes for Media app

- CarDrawerAdapter now owns title string and support setting.
  CarDrawerActivity monitors for title changes and updates Toolbar.
  Media app needs this flexibility.

Bug: 34352155
Test: Manually
Change-Id: If13c564af94275abf0e28efdf9b46a8538f5dbab
diff --git a/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java b/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java
index e1198d4..8812c42 100644
--- a/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java
+++ b/car-stream-ui-lib/src/com/android/car/app/CarDrawerActivity.java
@@ -19,6 +19,7 @@
 import android.content.res.Configuration;
 import android.os.Bundle;
 import android.support.annotation.LayoutRes;
+import android.support.annotation.NonNull;
 import android.support.car.ui.PagedListView;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
@@ -92,14 +93,13 @@
     }
 
     private void setToolbarTitleFrom(CarDrawerAdapter adapter) {
-        if (adapter.getTitleResId() != CarDrawerAdapter.INVALID_STRING_RES_ID) {
-            mToolbar.setTitle(adapter.getTitleResId());
-        } else if (adapter.getTitleString() != null) {
-            mToolbar.setTitle(adapter.getTitleString());
+        if (adapter.getTitle() != null) {
+            mToolbar.setTitle(adapter.getTitle());
         } else {
-            throw new RuntimeException("CarDrawerAdapter must supply title via " +
-                " getTitleResId() or getTitleString()");
+            throw new RuntimeException("CarDrawerAdapter subclass must supply title via " +
+                " setTitle()");
         }
+        adapter.setTitleChangeListener(mToolbar::setTitle);
     }
 
     /**
@@ -139,6 +139,7 @@
      * @param adapter Adapter for next level of content in the drawer.
      */
     public final void switchToAdapter(CarDrawerAdapter adapter) {
+        mAdapterStack.peek().setTitleChangeListener(null);
         mAdapterStack.push(adapter);
         setTitleAndSwitchToAdapter(adapter);
     }
@@ -153,13 +154,36 @@
     }
 
     /**
+     * Used to open the drawer.
+     */
+    public void openDrawer() {
+        if (!mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
+            mDrawerLayout.openDrawer(Gravity.LEFT);
+        }
+    }
+
+    /**
+     * @param listener Listener to be notified of Drawer events.
+     */
+    public void addDrawerListener(@NonNull DrawerLayout.DrawerListener listener) {
+        mDrawerLayout.addDrawerListener(listener);
+    }
+
+    /**
+     * @param listener Listener to be notified of Drawer events.
+     */
+    public void removeDrawerListener(@NonNull DrawerLayout.DrawerListener listener) {
+        mDrawerLayout.removeDrawerListener(listener);
+    }
+
+    /**
      * Used to switch between the Drawer PagedListView and the "loading" progress-bar while the next
      * level's adapter contents are being fetched.
      *
      * @param enable If true, the progress-bar is displayed. If false, the Drawer PagedListView is
      *               added.
      */
-    protected void showLoadingProgressBar(boolean enable) {
+    public void showLoadingProgressBar(boolean enable) {
         mDrawerList.setVisibility(enable ? View.INVISIBLE : View.VISIBLE);
         mProgressBar.setVisibility(enable ? View.VISIBLE : View.GONE);
     }
@@ -259,6 +283,7 @@
     private boolean maybeHandleUpClick() {
         if (mAdapterStack.size() > 1) {
             CarDrawerAdapter adapter = mAdapterStack.pop();
+            adapter.setTitleChangeListener(null);
             adapter.cleanup();
             setTitleAndSwitchToAdapter(mAdapterStack.peek());
             return true;
@@ -270,6 +295,7 @@
     private void cleanupStackAndShowRoot() {
         while (mAdapterStack.size() > 1) {
             CarDrawerAdapter adapter = mAdapterStack.pop();
+            adapter.setTitleChangeListener(null);
             adapter.cleanup();
         }
         setTitleAndSwitchToAdapter(mAdapterStack.peek());
diff --git a/car-stream-ui-lib/src/com/android/car/app/CarDrawerAdapter.java b/car-stream-ui-lib/src/com/android/car/app/CarDrawerAdapter.java
index 1f2c04f..ad9fe1c 100644
--- a/car-stream-ui-lib/src/com/android/car/app/CarDrawerAdapter.java
+++ b/car-stream-ui-lib/src/com/android/car/app/CarDrawerAdapter.java
@@ -3,6 +3,8 @@
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.car.ui.PagedListView;
 import android.support.v7.widget.RecyclerView;
@@ -15,8 +17,8 @@
 /**
  * Base Adapter for displaying items in the CarDrawerActivity's Drawer which uses a PagedListView.
  * <p>
- * Implementors must return the title that will be displayed when displaying the contents of the
- * Drawer. They should either override {@link #getTitleResId()} or {@link #getTitleString()}. The
+ * Subclasses must set the title that will be displayed when displaying the contents of the
+ * Drawer via {@link #setTitle(CharSequence)}. The title can be updated at any point later. The
  * title of the root-adapter will also be the main title showed in the toolbar when the drawer is
  * closed.
  * <p>
@@ -26,12 +28,16 @@
 public abstract class CarDrawerAdapter extends RecyclerView.Adapter<DrawerItemViewHolder> implements
         PagedListView.ItemCap,
         DrawerItemClickListener {
-    static final int INVALID_STRING_RES_ID = -1;
+    interface TitleChangeListener {
+        void onTitleChanged(CharSequence newTitle);
+    }
 
     private final boolean mShowDisabledListOnEmpty;
     private final boolean mUseSmallLayout;
     private final Drawable mEmptyListDrawable;
     private int mMaxItems = -1;
+    private CharSequence mTitle;
+    private TitleChangeListener mTitleChangeListener;
 
     protected CarDrawerAdapter(
             Context context, boolean showDisabledListOnEmpty,boolean useSmallLayout) {
@@ -42,24 +48,27 @@
         mEmptyListDrawable.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
     }
 
-    /**
-     * Subclasses should override this method or {@link #getTitleString()}.
-     *
-     * @return String resource to display in the toolbar title when displaying this adapter's
-     * contents.
-     */
-    @StringRes
-    protected int getTitleResId() {
-        return INVALID_STRING_RES_ID;
+    CharSequence getTitle() {
+        return mTitle;
     }
 
     /**
-     * Subclasses should override this method or {@link #getTitleResId()}.
+     * Updates the title to display in the toolbar for this Adapter.
      *
-     * @return String to display in the toolbar title when displaying this adapter's contents.
+     * @param title Title string.
      */
-    protected CharSequence getTitleString() {
-        return null;
+    public final void setTitle(@NonNull CharSequence title) {
+        if (title == null) {
+            throw new IllegalArgumentException("title is null!");
+        }
+        mTitle = title;
+        if (mTitleChangeListener != null) {
+            mTitleChangeListener.onTitleChanged(mTitle);
+        }
+    }
+
+    void setTitleChangeListener(@Nullable TitleChangeListener listener) {
+        mTitleChangeListener = listener;
     }
 
     // ItemCap implementation.
@@ -124,5 +133,5 @@
      * Called when this adapter has been popped off the stack and is no longer needed. Subclasses
      * can override to do any necessary cleanup.
      */
-    protected void cleanup() {}
-}
\ No newline at end of file
+    public void cleanup() {}
+}