Add BottomSheetBehavior for picker launch animation

* Add photopicker launch animation to transition from bottom screen to
top. This happens full screen for multiselect, and half screen for
single select.
* Swiping down the PhotoPicker activity closes the activity for
multi-select, and takes the screen back to partial screen for
single-select.
* Selecting an image in half screen opens full screen.

TODO: More transition effect CL to follow to match motion specs

Bug: 185800839
Test: Manual (video attached to the bug)

Change-Id: I33b41f06b674731c7e69218ec38f439788da86ff
Merged-In: I33b41f06b674731c7e69218ec38f439788da86ff
(cherry picked from commit fcd7132bf4fec4572df3aca76ff915a4ea710316)
diff --git a/res/layout/activity_photo_picker.xml b/res/layout/activity_photo_picker.xml
index 54ed321..ce9b7d0 100644
--- a/res/layout/activity_photo_picker.xml
+++ b/res/layout/activity_photo_picker.xml
@@ -15,46 +15,62 @@
   ~ limitations under the License.
   -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:app="http://schemas.android.com/apk/res-auto"
-              xmlns:tools="http://schemas.android.com/tools"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              tools:context=".MainActivity">
+<!-- CoordinatorLayout is necessary for various components (e.g. Snackbars, and
+     BottomSheet) to operate correctly. -->
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity">
 
-    <com.google.android.material.appbar.AppBarLayout
+    <LinearLayout
+        android:orientation="vertical"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="match_parent"
+        android:id="@+id/bottom_sheet"
+        android:background="?android:attr/colorBackground"
+        android:clipToOutline="true"
+        app:behavior_hideable="true"
+        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
 
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
+        <com.google.android.material.appbar.AppBarLayout
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"
-            android:background="?android:attr/colorBackground">
+            android:layout_height="wrap_content">
 
-            <LinearLayout
-                android:id="@+id/chip_container"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_gravity="center"
-                android:orientation="horizontal"/>
+            <androidx.appcompat.widget.Toolbar
+                android:id="@+id/toolbar"
+                android:layout_width="match_parent"
+                android:layout_height="?attr/actionBarSize"
+                android:background="?android:attr/colorBackground">
 
-        </androidx.appcompat.widget.Toolbar>
+                <LinearLayout
+                    android:id="@+id/chip_container"
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:layout_gravity="center"
+                    android:orientation="horizontal"/>
 
-    </com.google.android.material.appbar.AppBarLayout>
+            </androidx.appcompat.widget.Toolbar>
 
-    <Switch
-        android:visibility="gone"
-        android:text="Work Profile"
-        android:id="@+id/workprofile"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"/>
+        </com.google.android.material.appbar.AppBarLayout>
 
-    <androidx.fragment.app.FragmentContainerView
-        android:id="@+id/fragment_container"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1"/>
+        <Switch
+            android:visibility="gone"
+            android:text="Work Profile"
+            android:id="@+id/workprofile"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
 
-</LinearLayout>
+        <androidx.fragment.app.FragmentContainerView
+            android:id="@+id/fragment_container"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
+
+    </LinearLayout>
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
+
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 28332ce..c911972 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -21,6 +21,7 @@
     <dimen name="dialog_space">20dp</dimen>
 
     <!-- PhotoPicker -->
+    <dimen name="picker_top_corner_radius">16dp</dimen>
     <dimen name="picker_photo_size">118dp</dimen>
     <dimen name="picker_album_size">156dp</dimen>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 59886bd..60e9fae 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -56,9 +56,11 @@
         <item name="android:colorBackground">@color/picker_background_color</item>
 
         <!-- System | Widget section -->
-        <item name="android:statusBarColor">?android:colorBackground</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
         <item name="android:navigationBarColor">?android:colorBackground</item>
-        <item name="android:windowBackground">?android:colorBackground</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:backgroundDimEnabled">true</item>
     </style>
 
 </resources>
diff --git a/src/com/android/providers/media/photopicker/PhotoPickerActivity.java b/src/com/android/providers/media/photopicker/PhotoPickerActivity.java
index 260ab70..1f05c3f 100644
--- a/src/com/android/providers/media/photopicker/PhotoPickerActivity.java
+++ b/src/com/android/providers/media/photopicker/PhotoPickerActivity.java
@@ -22,8 +22,8 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Configuration;
 import android.graphics.Color;
+import android.graphics.Outline;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -31,10 +31,11 @@
 import android.provider.MediaStore;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowInsetsController;
+import android.view.ViewOutlineProvider;
 import android.widget.CompoundButton;
 import android.widget.Switch;
 import android.widget.Toast;
@@ -55,6 +56,8 @@
 import com.android.providers.media.photopicker.util.CrossProfileUtils;
 import com.android.providers.media.photopicker.viewmodel.PickerViewModel;
 
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback;
 import com.google.android.material.chip.Chip;
 
 import java.lang.annotation.Retention;
@@ -87,6 +90,8 @@
     private Chip mAlbumsTabChip;
     @TabChipType
     private int mSelectedTabChipType;
+    private BottomSheetBehavior mBottomSheetBehavior;
+    private View mBottomSheetView;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -115,6 +120,41 @@
             profileSwitch.setVisibility(View.VISIBLE);
             setUpWorkProfileToggleSwitch(profileSwitch);
         }
+        mBottomSheetView = findViewById(R.id.bottom_sheet);
+        mBottomSheetBehavior = BottomSheetBehavior.from(mBottomSheetView);
+        if (mPickerViewModel.canSelectMultiple()) {
+            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
+            mBottomSheetBehavior.setSkipCollapsed(true);
+        } else {
+            //TODO(b/185800839): Compute this dynamically such that 2 photos rows is shown
+            mBottomSheetBehavior.setPeekHeight(1200);
+            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
+        }
+
+        mBottomSheetBehavior.addBottomSheetCallback(new BottomSheetCallback() {
+            @Override
+            public void onStateChanged(@NonNull View bottomSheet, int newState) {
+                if (newState == BottomSheetBehavior.STATE_HIDDEN) {
+                    finish();
+                }
+            }
+
+            @Override
+            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
+            }
+        });
+
+        final float cornerRadiusDP = getResources().getDimension(R.dimen.picker_top_corner_radius);
+        final float cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
+                cornerRadiusDP, getResources().getDisplayMetrics());
+        final ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() {
+            @Override
+            public void getOutline(final View view, final Outline outline) {
+                outline.setRoundRect(0, 0, view.getWidth(),
+                        (int)(view.getHeight() + cornerRadius), cornerRadius);
+            }
+        };
+        mBottomSheetView.setOutlineProvider(viewOutlineProvider);
     }
 
     @Override
@@ -334,24 +374,28 @@
     }
 
     private void updateStatusBarAndNavBar(boolean isLightBackgroundMode) {
-        final int mask = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
-                | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
         final int backgroundColor;
+        final boolean isPreview = !isLightBackgroundMode;
         if (isLightBackgroundMode) {
             backgroundColor = getColor(R.color.picker_background_color);
-
-            final int uiModeNight =
-                    getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
-
-            // if the system is not in Dark theme, set the system bars to light mode.
-            if (uiModeNight == Configuration.UI_MODE_NIGHT_NO) {
-                getWindow().getInsetsController().setSystemBarsAppearance(mask, mask);
-            }
         } else {
             backgroundColor = getColor(R.color.preview_default_black);
-            getWindow().getInsetsController().setSystemBarsAppearance(/* appearance= */ 0, mask);
         }
-        getWindow().setStatusBarColor(backgroundColor);
         getWindow().setNavigationBarColor(backgroundColor);
+        getWindow().setStatusBarColor(isPreview ? backgroundColor : android.R.color.transparent);
+        if (mBottomSheetView != null) {
+            mBottomSheetView.setClipToOutline(!isPreview);
+            // TODO(b/185800839): downward swipe for bottomsheet should go back to photos grid
+            mBottomSheetBehavior.setDraggable(!isPreview);
+        }
+    }
+
+    /**
+     * Set full screen if the state is not full screen
+     */
+    public void setFullScreen() {
+        if (mBottomSheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED) {
+            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
+        }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/providers/media/photopicker/ui/PreviewFragment.java b/src/com/android/providers/media/photopicker/ui/PreviewFragment.java
index 661004d..7f8c569 100644
--- a/src/com/android/providers/media/photopicker/ui/PreviewFragment.java
+++ b/src/com/android/providers/media/photopicker/ui/PreviewFragment.java
@@ -63,6 +63,10 @@
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        // TODO(b/185800839): Add animation preview to full screen and back transition to partial
+        //  screen
+        ((PhotoPickerActivity)getActivity()).setFullScreen();
+
         // Warning: The below code assumes that getSelectedItems will never return null.
         // We are creating a new ArrayList with selected items, this list used as data for the
         // adapter. If activity gets killed and recreated, we will lose items that were deselected.