Add action chips to corner screenshot flow

In the corner screenshot flow, add a LinearLayout with action chips
(share/edit/scroll) that pops up once the actions are available.

Note that the 'scroll' button currently does nothing.

Bug: 144918886
Test: manual; tested that 'edit' and 'share' chips open the
appropriate apps and make the screenshot disappear; tested that
current notification flow is unchanged.

Change-Id: I6952b76aa3bb479c49b1905275d5fcdc0eeaf2df
diff --git a/packages/SystemUI/res/drawable/action_chip_background.xml b/packages/SystemUI/res/drawable/action_chip_background.xml
new file mode 100644
index 0000000..fc3dfeb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/action_chip_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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.
+  -->
+<ripple
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/global_screenshot_button_ripple">
+    <item android:id="@android:id/background">
+        <shape android:shape="rectangle">
+            <stroke android:width="1dp" android:color="@color/global_screenshot_button_text"/>
+            <solid android:color="@color/global_screenshot_button_background"/>
+            <corners android:radius="@dimen/screenshot_button_corner_radius"/>
+        </shape>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/action_chip_container_background.xml b/packages/SystemUI/res/drawable/action_chip_container_background.xml
new file mode 100644
index 0000000..095213e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/action_chip_container_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="@color/global_screenshot_button_background"/>
+    <corners android:radius="@dimen/screenshot_action_container_corner_radius"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 59952e0..6ac9da4 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -39,4 +39,13 @@
         android:layout_height="match_parent"
         android:visibility="gone"
         android:pointerIcon="crosshair"/>
+    <LinearLayout
+        android:id="@+id/global_screenshot_actions"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|center"
+        android:gravity="center"
+        android:paddingVertical="@dimen/screenshot_action_container_padding"
+        android:visibility="gone"
+        android:background="@drawable/action_chip_container_background"/>
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
new file mode 100644
index 0000000..6b42400
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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.
+  -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:id="@+id/global_screenshot_action_chip"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_marginHorizontal="@dimen/screenshot_action_chip_margin_horizontal"
+          android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
+          android:paddingHorizontal="@dimen/screenshot_action_chip_padding_horizontal"
+          android:background="@drawable/action_chip_background"
+          android:textColor="@color/global_screenshot_button_text"/>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 0febc8e..9a66e8b 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -78,6 +78,11 @@
     <!-- The color of the text in the Global Actions menu -->
     <color name="global_actions_alert_text">@color/GM2_red_300</color>
 
+    <!-- Global screenshot actions -->
+    <color name="global_screenshot_button_background">@color/GM2_grey_900</color>
+    <color name="global_screenshot_button_ripple">#42FFFFFF</color>
+    <color name="global_screenshot_button_text">@color/GM2_blue_300</color>
+
     <!-- Biometric dialog colors -->
     <color name="biometric_dialog_gray">#ff888888</color>
     <color name="biometric_dialog_accent">#ff80cbc4</color> <!-- light teal -->
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bda1c52..92c7477 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -180,6 +180,11 @@
     <!-- Color for the Assistant invocation lights -->
     <color name="default_invocation_lights_color">#ffffffff</color>         <!-- white -->
 
+    <!-- Global screenshot actions -->
+    <color name="global_screenshot_button_background">#F5F5F5</color>
+    <color name="global_screenshot_button_ripple">#1f000000</color>
+    <color name="global_screenshot_button_text">@color/GM2_blue_500</color>
+
     <!-- GM2 colors -->
     <color name="GM2_grey_50">#F8F9FA</color>
     <color name="GM2_grey_100">#F1F3F4</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 64b2892..f7b92b5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -285,8 +285,18 @@
     <!-- the padding between dots in the icon overflow -->
     <dimen name="overflow_icon_dot_padding">3dp</dimen>
 
+    <!-- Dimensions related to screenshots -->
+
     <!-- The padding on the global screenshot background image -->
     <dimen name="global_screenshot_bg_padding">20dp</dimen>
+    <dimen name="screenshot_action_container_corner_radius">10dp</dimen>
+    <dimen name="screenshot_action_container_padding">20dp</dimen>
+    <!-- Radius of the chip background on global screenshot actions -->
+    <dimen name="screenshot_button_corner_radius">20dp</dimen>
+    <dimen name="screenshot_action_chip_margin_horizontal">10dp</dimen>
+    <dimen name="screenshot_action_chip_padding_vertical">10dp</dimen>
+    <dimen name="screenshot_action_chip_padding_horizontal">15dp</dimen>
+
 
     <!-- The width of the view containing navigation buttons -->
     <dimen name="navigation_key_width">70dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 66cd919..fedd855 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -19,6 +19,7 @@
 import static android.content.Context.NOTIFICATION_SERVICE;
 import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
 import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
+import static android.view.View.VISIBLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_CORNER_FLOW;
@@ -69,6 +70,8 @@
 import android.view.WindowManager;
 import android.view.animation.Interpolator;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 import android.widget.Toast;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -89,7 +92,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
-import java.util.function.Function;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -110,7 +112,7 @@
         public Bitmap image;
         public Uri imageUri;
         public Consumer<Uri> finisher;
-        public Function<PendingIntent, Void> onEditReady;
+        public GlobalScreenshot.ActionsReadyListener mActionsReadyListener;
         public int iconSize;
         public int previewWidth;
         public int previewheight;
@@ -127,6 +129,10 @@
         }
     }
 
+    abstract static class ActionsReadyListener {
+        abstract void onActionsReady(PendingIntent shareAction, PendingIntent editAction);
+    }
+
     // These strings are used for communicating the action invoked to
     // ScreenshotNotificationSmartActionsProvider.
     static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
@@ -175,6 +181,10 @@
     private ImageView mBackgroundView;
     private ImageView mScreenshotView;
     private ImageView mScreenshotFlash;
+    private LinearLayout mActionsView;
+    private TextView mShareAction;
+    private TextView mEditAction;
+    private TextView mScrollAction;
 
     private AnimatorSet mScreenshotAnimation;
 
@@ -211,17 +221,31 @@
         mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
         mBackgroundView = mScreenshotLayout.findViewById(R.id.global_screenshot_background);
         mScreenshotView = mScreenshotLayout.findViewById(R.id.global_screenshot);
+        mActionsView = mScreenshotLayout.findViewById(R.id.global_screenshot_actions);
+
+        mShareAction = (TextView) layoutInflater.inflate(
+                R.layout.global_screenshot_action_chip, mActionsView, false);
+        mEditAction = (TextView) layoutInflater.inflate(
+                R.layout.global_screenshot_action_chip, mActionsView, false);
+        mScrollAction = (TextView) layoutInflater.inflate(
+                R.layout.global_screenshot_action_chip, mActionsView, false);
+
+        mShareAction.setText(com.android.internal.R.string.share);
+        mEditAction.setText(com.android.internal.R.string.screenshot_edit);
+        mScrollAction.setText("Scroll"); // TODO (mkephart): Add to resources and translate
+
+        mActionsView.addView(mShareAction);
+        mActionsView.addView(mEditAction);
+        mActionsView.addView(mScrollAction);
+
         mScreenshotFlash = mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
         mScreenshotSelectorView = mScreenshotLayout.findViewById(R.id.global_screenshot_selector);
         mScreenshotLayout.setFocusable(true);
         mScreenshotSelectorView.setFocusable(true);
         mScreenshotSelectorView.setFocusableInTouchMode(true);
-        mScreenshotLayout.setOnTouchListener(new View.OnTouchListener() {
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                // Intercept and ignore all touch events
-                return true;
-            }
+        mScreenshotLayout.setOnTouchListener((v, event) -> {
+            // Intercept and ignore all touch events
+            return true;
         });
 
         // Setup the window that we are going to use
@@ -271,13 +295,13 @@
      * Creates a new worker thread and saves the screenshot to the media store.
      */
     private void saveScreenshotInWorkerThread(
-            Consumer<Uri> finisher, @Nullable Function<PendingIntent, Void> onEditReady) {
+            Consumer<Uri> finisher, @Nullable ActionsReadyListener actionsReadyListener) {
         SaveImageInBackgroundData data = new SaveImageInBackgroundData();
         data.context = mContext;
         data.image = mScreenBitmap;
         data.iconSize = mNotificationIconSize;
         data.finisher = finisher;
-        data.onEditReady = onEditReady;
+        data.mActionsReadyListener = actionsReadyListener;
         data.previewWidth = mPreviewWidth;
         data.previewheight = mPreviewHeight;
         if (mSaveInBgTask != null) {
@@ -395,6 +419,7 @@
         // Clear any references to the bitmap
         mScreenBitmap = null;
         mScreenshotView.setImageBitmap(null);
+        mActionsView.setVisibility(View.GONE);
         mBackgroundView.setVisibility(View.GONE);
         mScreenshotView.setVisibility(View.GONE);
         mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
@@ -441,24 +466,13 @@
                     saveScreenshotInWorkerThread(finisher);
                     clearScreenshot();
                 } else {
-                    mScreenshotView.requestFocus();
-                    mScreenshotView.setOnClickListener((v) -> {
-                        // TODO: remove once we have a better UI to show that we aren't ready yet
-                        Toast notReadyToast = Toast.makeText(
-                                mContext, "Screenshot is not ready yet", Toast.LENGTH_SHORT);
-                        notReadyToast.show();
-                    });
-                    saveScreenshotInWorkerThread(finisher, intent -> {
-                        mScreenshotHandler.post(() -> mScreenshotView.setOnClickListener(v -> {
-                            try {
-                                intent.send();
-                                clearScreenshot();
-                            } catch (PendingIntent.CanceledException e) {
-                                Log.e(TAG, "Edit intent cancelled", e);
-                            }
-                            mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
-                        }));
-                        return null;
+                    saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {
+                        @Override
+                        void onActionsReady(PendingIntent shareAction, PendingIntent editAction) {
+                            mScreenshotHandler.post(() ->
+                                    createScreenshotActionsShadeAnimation(shareAction, editAction)
+                                            .start());
+                        }
                     });
                     mScreenshotHandler.sendMessageDelayed(
                             mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT),
@@ -664,6 +678,49 @@
         return anim;
     }
 
+    private ValueAnimator createScreenshotActionsShadeAnimation(
+            PendingIntent shareAction, PendingIntent editAction) {
+        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+        mActionsView.setY(mDisplayMetrics.heightPixels);
+        mActionsView.setVisibility(VISIBLE);
+        mActionsView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+        float actionsViewHeight = mActionsView.getMeasuredHeight();
+        float screenshotStartHeight = mScreenshotView.getTranslationY();
+
+        animator.addUpdateListener(animation -> {
+            float t = animation.getAnimatedFraction();
+            mScreenshotView.setTranslationY(screenshotStartHeight - actionsViewHeight * t);
+            mActionsView.setY(mDisplayMetrics.heightPixels - actionsViewHeight * t);
+        });
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                mScreenshotView.requestFocus();
+                mShareAction.setOnClickListener(v -> {
+                    try {
+                        shareAction.send();
+                        clearScreenshot();
+                    } catch (PendingIntent.CanceledException e) {
+                        Log.e(TAG, "Share intent cancelled", e);
+                    }
+                });
+                mEditAction.setOnClickListener(v -> {
+                    try {
+                        editAction.send();
+                        clearScreenshot();
+                    } catch (PendingIntent.CanceledException e) {
+                        Log.e(TAG, "Edit intent cancelled", e);
+                    }
+                });
+                Toast scrollNotImplemented = Toast.makeText(
+                        mContext, "Not implemented", Toast.LENGTH_SHORT);
+                mScrollAction.setOnClickListener(v -> scrollNotImplemented.show());
+            }
+        });
+        return animator;
+    }
+
     static void notifyScreenshotError(Context context, NotificationManager nManager, int msgResId) {
         Resources r = context.getResources();
         String errorMsg = r.getString(msgResId);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index 5e5cf74..d2268e1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -434,8 +434,8 @@
                 R.drawable.ic_screenshot_edit,
                 r.getString(com.android.internal.R.string.screenshot_edit), editAction);
         notificationBuilder.addAction(editActionBuilder.build());
-        if (editAction != null && mParams.onEditReady != null) {
-            mParams.onEditReady.apply(editAction);
+        if (mParams.mActionsReadyListener != null) {
+            mParams.mActionsReadyListener.onActionsReady(shareAction, editAction);
         }
 
         // Create a delete action for the notification
@@ -472,7 +472,7 @@
             GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
                     mParams.errorMsgResId);
         } else {
-            if (mParams.onEditReady != null) {
+            if (mParams.mActionsReadyListener != null) {
                 // Cancel the "saving screenshot" notification
                 mNotificationManager.cancel(
                         SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index 3f32c66b..6d85d37 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -175,7 +175,7 @@
         data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
         data.iconSize = 10;
         data.finisher = null;
-        data.onEditReady = null;
+        data.mActionsReadyListener = null;
         data.previewWidth = 10;
         data.previewheight = 10;
         SaveImageInBackgroundTask task = new SaveImageInBackgroundTask(mContext, data,