DO NOT MERGE: Merge Oreo MR1 into master

Exempt-From-Owner-Approval: Changes already landed internally
Change-Id: Id90b1b88a9de34a4003f0d9192e0ac5bdb862e6f
diff --git a/car-stream-ui-lib/car-stream-ui-lib.mk b/car-stream-ui-lib/car-stream-ui-lib.mk
index 86ad7a6..7f3db8e 100644
--- a/car-stream-ui-lib/car-stream-ui-lib.mk
+++ b/car-stream-ui-lib/car-stream-ui-lib.mk
@@ -52,6 +52,13 @@
 LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
 endif
 
+# Include support-v7-recyclerview, if not already included
+ifeq (,$(findstring android-support-v7-recyclerview,$(LOCAL_STATIC_JAVA_LIBRARIES)))
+LOCAL_RESOURCE_DIR += frameworks/support/v7/recyclerview/res
+LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.recyclerview
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-recyclerview
+endif
+
 # Include car-stream-ui-lib
 ifeq (,$(findstring car-stream-ui-lib, $(LOCAL_STATIC_JAVA_LIBRARIES)))
 LOCAL_RESOURCE_DIR += \
diff --git a/car-stream-ui-lib/res/layout/car_drawer_activity.xml b/car-stream-ui-lib/res/layout/car_drawer_activity.xml
index 17feb76..4fb9292 100644
--- a/car-stream-ui-lib/res/layout/car_drawer_activity.xml
+++ b/car-stream-ui-lib/res/layout/car_drawer_activity.xml
@@ -64,9 +64,9 @@
         <!-- This keeps the toolbar centered within lens_header_height -->
         <android.support.v7.widget.Toolbar
             android:id="@+id/main_toolbar"
-            android:layout_width="match_parent"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
-            style="@style/CarToolbarTheme" /> 
+            style="@style/CarToolbarTheme" />
     </FrameLayout>
 </FrameLayout>
diff --git a/car-stream-ui-lib/res/values-h480dp/dimens.xml b/car-stream-ui-lib/res/values-h480dp/dimens.xml
index 77f1c76..4da60ed 100644
--- a/car-stream-ui-lib/res/values-h480dp/dimens.xml
+++ b/car-stream-ui-lib/res/values-h480dp/dimens.xml
@@ -18,4 +18,8 @@
     <dimen name="action_panel_height">128dp</dimen>
     <dimen name="stream_fab_size">100dp</dimen>
     <dimen name="stream_button_size">96dp</dimen>
+
+    <!-- Height of items in a list. -->
+    <dimen name="double_line_item_height">96dp</dimen>
+    <dimen name="single_line_item_height">76dp</dimen>
 </resources>
diff --git a/car-stream-ui-lib/res/values-h552dp/dimens.xml b/car-stream-ui-lib/res/values-h552dp/dimens.xml
new file mode 100644
index 0000000..66daa2d
--- /dev/null
+++ b/car-stream-ui-lib/res/values-h552dp/dimens.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<resources>
+    <!-- Height of items in a list. -->
+    <dimen name="double_line_item_height">128dp</dimen>
+    <dimen name="single_line_item_height">128dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/car-stream-ui-lib/res/values/attrs.xml b/car-stream-ui-lib/res/values/attrs.xml
index 344b1a5..911f891 100644
--- a/car-stream-ui-lib/res/values/attrs.xml
+++ b/car-stream-ui-lib/res/values/attrs.xml
@@ -22,8 +22,17 @@
         <attr name="glowColor" format="color" />
         <!-- Whether offsetting the list view by the amount of left scroll bar -->
         <attr name="offsetScrollBar" format="boolean" />
-        <!-- Whether or not the list view is offset by the width of the scroll bar. -->
+        <!-- Whether or not to show a diving line between each item of the list. -->
         <attr name="showDivider" format="boolean" />
+        <!-- An optional id that specifies a child View whose starting edge will be used to
+             determine the start position of the dividing line. -->
+        <attr name="alignDividerStartTo" format="reference" />
+        <!-- An optional id that specifies a child View whose ending edge will be used to
+             determine the end position of the dividing line. -->
+        <attr name="alignDividerEndTo" format="reference" />
+        <!-- A starting margin before the drawing of the dividing line. This margin will be an
+             offset from the view specified by "alignDividerStartTo" if given. -->
+        <attr name="dividerStartMargin" format="dimension" />
         <!-- The width of the container for the scroll -->
         <attr name="scrollbarContainerWidth" format="dimension" />
         <!-- The width of the margin on the right side of the list -->
diff --git a/car-stream-ui-lib/res/values/dimens.xml b/car-stream-ui-lib/res/values/dimens.xml
index 3425277..3555501 100644
--- a/car-stream-ui-lib/res/values/dimens.xml
+++ b/car-stream-ui-lib/res/values/dimens.xml
@@ -99,7 +99,7 @@
     <!-- Keylines for content within a card. -->
     <dimen name="stream_card_keyline_1">24dp</dimen>
     <dimen name="stream_card_keyline_2">96dp</dimen>
-    <dimen name="stream_card_keyline_3">176dp</dimen>
+    <dimen name="stream_card_keyline_3">128dp</dimen>
 
     <!-- The top margin before the start of content in an application. -->
     <dimen name="lens_header_height">96dp</dimen>
@@ -138,4 +138,18 @@
     <dimen name="search_suggestion_height">64dp</dimen>
     <dimen name="searchview_margin_left">152dp</dimen>
     <dimen name="searchview_margin_right">264dp</dimen>
+
+    <!-- The space on each side of the screen. Some common function widgets, like scroll bar,
+         can go into this space -->
+    <dimen name="side_margin">148dp</dimen>
+
+    <!-- Common icon size for car app -->
+    <dimen name="car_icon_size">44dp</dimen>
+
+    <!-- Touch target size for round or square affordance -->
+    <dimen name="car_touch_target">106dp</dimen>
+
+    <!-- Height of items in a list. -->
+    <dimen name="double_line_item_height">256dp</dimen>
+    <dimen name="single_line_item_height">256dp</dimen>
 </resources>
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 c8bf22a..2c67562 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
@@ -94,6 +94,12 @@
         setupDrawerToggling();
     }
 
+    @Override
+    protected void onStop() {
+        super.onStop();
+        mDrawerLayout.closeDrawer(Gravity.LEFT, false /* animation */);
+    }
+
     private void setToolbarTitleFrom(CarDrawerAdapter adapter) {
         if (adapter.getTitle() != null) {
             mToolbar.setTitle(adapter.getTitle());
diff --git a/car-stream-ui-lib/src/com/android/car/view/PagedListView.java b/car-stream-ui-lib/src/com/android/car/view/PagedListView.java
index f0e93cd..6f5c294 100644
--- a/car-stream-ui-lib/src/com/android/car/view/PagedListView.java
+++ b/car-stream-ui-lib/src/com/android/car/view/PagedListView.java
@@ -16,11 +16,13 @@
 package com.android.car.view;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.os.Handler;
+import android.support.annotation.IdRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v7.widget.RecyclerView;
@@ -29,9 +31,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
-import android.widget.TextView;
 
 import com.android.car.stream.ui.R;
 
@@ -48,6 +48,7 @@
      * user holds down a pagination button.
      */
     private static final int PAGINATION_HOLD_DELAY_MS = 400;
+    private static final int INVALID_RESOURCE_ID = -1;
 
     private final CarRecyclerView mRecyclerView;
     private final CarLayoutManager mLayoutManager;
@@ -85,7 +86,7 @@
      * </pre>
      */
     public interface ItemCap {
-        public static final int UNLIMITED = -1;
+        int UNLIMITED = -1;
 
         /**
          * Sets the maximum number of items available in the adapter. A value less than '0'
@@ -125,19 +126,13 @@
             FrameLayout maxWidthLayout = (FrameLayout) findViewById(R.id.max_width_layout);
             LayoutParams params = (LayoutParams) maxWidthLayout.getLayoutParams();
             params.leftMargin = scrollContainerWidth;
-            int rightMargin = a.getDimensionPixelSize(R.styleable.PagedListView_rightMargin, 0);
-            params.rightMargin = rightMargin;
+            params.rightMargin = a.getDimensionPixelSize(R.styleable.PagedListView_rightMargin, 0);
             maxWidthLayout.setLayoutParams(params);
         }
-        boolean showDivider = a.getBoolean(R.styleable.PagedListView_showDivider, true);
-        mDecor = showDivider
-                ? new DividerDecoration(getContext()) : new NoDividerDecoration(getContext());
-
         mRecyclerView = (CarRecyclerView) findViewById(R.id.recycler_view);
         boolean fadeLastItem = a.getBoolean(R.styleable.PagedListView_fadeLastItem, false);
         mRecyclerView.setFadeLastItem(fadeLastItem);
         boolean offsetRows = a.getBoolean(R.styleable.PagedListView_offsetRows, false);
-        a.recycle();
 
         mMaxPages = getDefaultMaxPages();
 
@@ -145,11 +140,22 @@
         mLayoutManager.setOffsetRows(offsetRows);
         mLayoutManager.setItemsChangedListener(mItemsChangedListener);
         mRecyclerView.setLayoutManager(mLayoutManager);
-        mRecyclerView.addItemDecoration(mDecor);
         mRecyclerView.setOnScrollListener(mOnScrollListener);
         mRecyclerView.getRecycledViewPool().setMaxRecycledViews(0, 12);
         mRecyclerView.setItemAnimator(new CarItemAnimator(mLayoutManager));
 
+        if (a.getBoolean(R.styleable.PagedListView_showDivider, true)) {
+            int dividerStartMargin = a.getDimensionPixelSize(
+                    R.styleable.PagedListView_dividerStartMargin, 0);
+            int dividerStartId = a.getResourceId(R.styleable.PagedListView_alignDividerStartTo,
+                    INVALID_RESOURCE_ID);
+            int dividerEndId = a.getResourceId(R.styleable.PagedListView_alignDividerEndTo,
+                    INVALID_RESOURCE_ID);
+
+            mRecyclerView.addItemDecoration(new DividerDecoration(context, dividerStartMargin,
+                    dividerStartId, dividerEndId));
+        }
+
         mScrollBarView = (PagedScrollBarView) findViewById(R.id.paged_scroll_view);
         mScrollBarView.setPaginationListener(new PagedScrollBarView.PaginationListener() {
             @Override
@@ -166,6 +172,8 @@
 
         setAutoDayNightMode();
         updatePaginationButtons(false /*animate*/);
+
+        a.recycle();
     }
 
     @Override
@@ -253,16 +261,6 @@
         mMaxPages = getDefaultMaxPages();
     }
 
-    public void setDefaultItemDecoration(DividerDecoration decor) {
-        removeDefaultItemDecoration();
-        mDecor = decor;
-        addItemDecoration(mDecor);
-    }
-
-    public void removeDefaultItemDecoration() {
-        mRecyclerView.removeItemDecoration(mDecor);
-    }
-
     public void addItemDecoration(@NonNull RecyclerView.ItemDecoration decor) {
         mRecyclerView.addItemDecoration(decor);
     }
@@ -271,19 +269,26 @@
         mRecyclerView.removeItemDecoration(decor);
     }
 
+    /**
+     * Sets the scrollbars of this PagedListView to change from light to dark colors depending on
+     * whether or not device is in night mode.
+     */
     public void setAutoDayNightMode() {
         mScrollBarView.setAutoDayNightMode();
-        mDecor.updateDividerColor();
     }
 
+    /**
+     * Sets the scrollbars of this PagedListView to be light colors.
+     */
     public void setLightMode() {
         mScrollBarView.setLightMode();
-        mDecor.updateDividerColor();
     }
 
+    /**
+     * Sets the scrollbars of this PagedListView to be dark colors.
+     */
     public void setDarkMode() {
         mScrollBarView.setDarkMode();
-        mDecor.updateDividerColor();
     }
 
     public void setOnScrollBarListener(OnScrollBarListener listener) {
@@ -474,96 +479,67 @@
         public void onLeaveBottom() {}
     }
 
+    /**
+     * A {@link android.support.v7.widget.RecyclerView.ItemDecoration} that will draw a dividing
+     * line between each item in the RecyclerView that it is added to.
+     */
     public static class DividerDecoration extends RecyclerView.ItemDecoration {
-        protected final Paint mPaint;
-        protected final int mDividerHeight;
-        protected final Context mContext;
+        private final Paint mPaint;
+        private final int mDividerHeight;
+        private final int mDividerStartMargin;
+        @IdRes private final int mDividerStartId;
+        @IdRes private final int mDvidierEndId;
 
+        /**
+         * @param dividerStartMargin The start offset of the dividing line. This offset will be
+         *                           relative to {@code dividerStartId} if that value is given.
+         * @param dividerStartId A child view id whose starting edge will be used as the starting
+         *                       edge of the dividing line. If this value is
+         *                       {@link #INVALID_RESOURCE_ID}, the the top container of each
+         *                       child view will be used.
+         * @param dividerEndId A child view id whose ending edge will be used as the starting edge
+         *                     of the dividing lin.e If this value is {@link #INVALID_RESOURCE_ID},
+         *                     then the top container view of each child will be used.
+         */
+        private DividerDecoration(Context context, int dividerStartMargin,
+                @IdRes int dividerStartId, @IdRes int dividerEndId) {
+            mDividerStartMargin = dividerStartMargin;
+            mDividerStartId = dividerStartId;
+            mDvidierEndId = dividerEndId;
 
-        public DividerDecoration(Context context) {
-            mContext = context;
+            Resources res = context.getResources();
             mPaint = new Paint();
-            updateDividerColor();
-            mDividerHeight = mContext.getResources()
-                    .getDimensionPixelSize(R.dimen.car_divider_height);
+            mPaint.setColor(res.getColor(R.color.car_list_divider));
+            mDividerHeight = res.getDimensionPixelSize(R.dimen.car_divider_height);
         }
 
         @Override
         public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
-            final int left = getLeft(parent.getChildAt(0));
-            final int right = parent.getWidth() - parent.getPaddingRight();
-            int top;
-            int bottom;
+            for (int i = 0, childCount = parent.getChildCount(); i < childCount; i++) {
+                View container = parent.getChildAt(i);
+                View startChild = mDividerStartId != INVALID_RESOURCE_ID
+                        ? container.findViewById(mDividerStartId)
+                        : container;
 
-            c.drawRect(left, 0, right, mDividerHeight, mPaint);
+                View endChild = mDvidierEndId != INVALID_RESOURCE_ID
+                        ? container.findViewById(mDvidierEndId)
+                        : container;
 
-            final int childCount = parent.getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                final View child = parent.getChildAt(i);
-                final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
-                        .getLayoutParams();
-                bottom = child.getBottom() - params.bottomMargin;
-                top = bottom - mDividerHeight;
-                if (top > 0) {
+                if (startChild == null || endChild == null) {
+                    continue;
+                }
+
+                int left = mDividerStartMargin + startChild.getLeft();
+                int right = endChild.getRight();
+                int bottom = container.getBottom();
+                int top = bottom - mDividerHeight;
+
+                // Draw a divider line between each item. No need to draw the line for the last
+                // item.
+                if (i != childCount - 1) {
                     c.drawRect(left, top, right, bottom, mPaint);
                 }
             }
         }
-
-        /**
-         * Updates the list divider color which may have changed due to a day night transition.
-         */
-        public void updateDividerColor() {
-            mPaint.setColor(mContext.getResources().getColor(R.color.car_list_divider));
-        }
-
-        /**
-         * Find the left edge of the decoration line. It should be left aligned with the left edge
-         * of the first {@link android.widget.TextView}.
-         */
-        private int getLeft(View root) {
-            if (root == null) {
-                return 0;
-            }
-            View view = findTextView(root);
-            if (view == null) {
-                view = root;
-            }
-            int left = 0;
-            while (view != null && view != root) {
-                left += view.getLeft();
-                view = (View) view.getParent();
-            }
-            return left;
-        }
-
-        private TextView findTextView(View root) {
-            if (root == null) {
-                return null;
-            }
-            if (root instanceof TextView) {
-                return (TextView) root;
-            }
-            if (root instanceof ViewGroup) {
-                ViewGroup parent = (ViewGroup) root;
-                final int childCount = parent.getChildCount();
-                for(int i = 0; i < childCount; i++) {
-                    TextView tv = findTextView(parent.getChildAt(i));
-                    if (tv != null) {
-                        return tv;
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
-    public static class NoDividerDecoration extends DividerDecoration {
-        public NoDividerDecoration(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {}
     }
 }