Merge "Update title of bottom widgets tray" into sc-dev
diff --git a/go/AndroidManifest.xml b/go/AndroidManifest.xml
index f36439d..2671604 100644
--- a/go/AndroidManifest.xml
+++ b/go/AndroidManifest.xml
@@ -24,6 +24,8 @@
 
     <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
 
+    <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
+
     <application
         android:backupAgent="com.android.launcher3.LauncherBackupAgent"
         android:fullBackupOnly="true"
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index b102a39..36a4e7f 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -20,11 +20,21 @@
 import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
 
 import android.annotation.SuppressLint;
+import android.app.ActivityTaskManager;
+import android.app.IAssistDataReceiver;
+import android.app.assist.AssistContent;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Bitmap;
 import android.graphics.Matrix;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
 import android.os.SystemClock;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.launcher3.R;
 import com.android.quickstep.views.OverviewActionsView;
@@ -40,6 +50,8 @@
     public static final String ACTION_TRANSLATE = "com.android.quickstep.ACTION_TRANSLATE";
     public static final String ACTION_SEARCH = "com.android.quickstep.ACTION_SEARCH";
     public static final String ELAPSED_NANOS = "niu_actions_elapsed_realtime_nanos";
+    public static final String ACTIONS_URL = "niu_actions_app_url";
+    private static final String TAG = "TaskOverlayFactoryGo";
 
     // Empty constructor required for ResourceBasedOverride
     public TaskOverlayFactoryGo(Context context) {}
@@ -56,11 +68,16 @@
      * @param <T> The type of View in which the overlay will be placed
      */
     public static final class TaskOverlayGo<T extends OverviewActionsView> extends TaskOverlay {
+        private static final String ASSIST_KEY_CONTENT = "content";
 
-        private String mPackageName;
+        private String mNIUPackageName;
+        private int mTaskId;
+        private Bundle mAssistData;
+        private final Handler mMainThreadHandler;
 
         private TaskOverlayGo(TaskThumbnailView taskThumbnailView) {
             super(taskThumbnailView);
+            mMainThreadHandler = new Handler(Looper.getMainLooper());
         }
 
         /**
@@ -70,16 +87,39 @@
         public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
                 boolean rotated) {
             getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
-            mPackageName =
+            mNIUPackageName =
                     mApplicationContext.getResources().getString(R.string.niu_actions_package);
 
-            if (thumbnail == null || TextUtils.isEmpty(mPackageName)) {
+            if (thumbnail == null || TextUtils.isEmpty(mNIUPackageName)) {
                 return;
             }
 
             getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
             boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
             getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
+
+            mTaskId = task.key.id;
+            AssistDataReceiverImpl receiver = new AssistDataReceiverImpl();
+            receiver.setOverlay(this);
+
+            try {
+                ActivityTaskManager.getService().requestAssistDataForTask(receiver, mTaskId,
+                        mApplicationContext.getPackageName());
+            } catch (RemoteException e) {
+                Log.e(TAG, "Unable to request AssistData");
+            }
+        }
+
+        /**
+         * Called when AssistDataReceiverImpl receives data from ActivityTaskManagerService's
+         * AssistDataRequester
+         */
+        public void onAssistDataReceived(Bundle data) {
+            mMainThreadHandler.post(() -> {
+                if (data != null) {
+                    mAssistData = data;
+                }
+            });
         }
 
         private void sendNIUIntent(String actionType) {
@@ -88,11 +128,21 @@
         }
 
         private Intent createNIUIntent(String actionType) {
-            return new Intent(actionType)
+            Intent intent = new Intent(actionType)
                     .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
                     .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
-                    .setPackage(mPackageName)
+                    .setPackage(mNIUPackageName)
                     .putExtra(ELAPSED_NANOS, SystemClock.elapsedRealtimeNanos());
+
+            if (mAssistData != null) {
+                final AssistContent content = mAssistData.getParcelable(ASSIST_KEY_CONTENT);
+                Uri webUri = (content == null) ? null : content.getWebUri();
+                if (webUri != null) {
+                    intent.putExtra(ACTIONS_URL, webUri.toString());
+                }
+            }
+
+            return intent;
         }
 
         protected class OverlayUICallbacksGoImpl extends OverlayUICallbacksImpl
@@ -131,6 +181,26 @@
     }
 
     /**
+     * Basic AssistDataReceiver. This is passed to ActivityTaskManagerService, which then requests
+     * the data.
+     */
+    private static final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
+        private TaskOverlayGo mOverlay;
+
+        public void setOverlay(TaskOverlayGo overlay) {
+            mOverlay = overlay;
+        }
+
+        @Override
+        public void onHandleAssistData(Bundle data) {
+            mOverlay.onAssistDataReceived(data);
+        }
+
+        @Override
+        public void onHandleAssistScreenshot(Bitmap screenshot) {}
+    }
+
+    /**
      * Callbacks the Ui can generate. This is the only way for a Ui to call methods on the
      * controller.
      */
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index b1b4d70..df3657d 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -73,6 +73,7 @@
 
     public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
     private static final String LAST_SNAPSHOT_TIME_MILLIS = "LAST_SNAPSHOT_TIME_MILLIS";
+    private static final int NUM_OF_RECOMMENDED_WIDGETS_PREDICATION = 20;
 
     private static final boolean IS_DEBUG = false;
     private static final String TAG = "QuickstepModelDelegate";
@@ -217,7 +218,7 @@
         registerWidgetsPredictor(apm.createAppPredictionSession(
                 new AppPredictionContext.Builder(context)
                         .setUiSurface("widgets")
-                        .setPredictedTargetCount(mIDP.numColumns)
+                        .setPredictedTargetCount(NUM_OF_RECOMMENDED_WIDGETS_PREDICATION)
                         .build()));
     }
 
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 3094500..b492825 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -617,7 +617,7 @@
         final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
         if (passed != mPassedOverviewThreshold) {
             mPassedOverviewThreshold = passed;
-            if (!mDeviceState.isTwoButtonNavMode()) {
+            if (mDeviceState.isTwoButtonNavMode()) {
                 performHapticFeedback();
             }
         }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 809adcb..2b7e6fd 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -298,7 +298,6 @@
     private boolean mEndQuickswitchCuj;
 
     private View mContextualChipWrapper;
-    private View mContextualChip;
     private final float[] mIconCenterCoords = new float[2];
     private final float[] mChipCenterCoords = new float[2];
 
@@ -447,9 +446,9 @@
         }
         mModalness = modalness;
         mIconView.setAlpha(comp(modalness));
-        if (mContextualChip != null) {
-            mContextualChip.setScaleX(comp(modalness));
-            mContextualChip.setScaleY(comp(modalness));
+        if (mContextualChipWrapper != null) {
+            mContextualChipWrapper.setScaleX(comp(modalness));
+            mContextualChipWrapper.setScaleY(comp(modalness));
         }
         mDigitalWellBeingToast.updateBannerOffset(modalness,
                 mCurrentFullscreenParams.mCurrentDrawnInsets.top
@@ -689,10 +688,10 @@
                 .getInterpolation(progress);
         mIconView.setScaleX(scale);
         mIconView.setScaleY(scale);
-        if (mContextualChip != null && mContextualChipWrapper != null) {
+        if (mContextualChipWrapper != null && mContextualChipWrapper != null) {
             mContextualChipWrapper.setAlpha(scale);
-            mContextualChip.setScaleX(scale);
-            mContextualChip.setScaleY(scale);
+            mContextualChipWrapper.setScaleX(Math.min(scale, comp(mModalness)));
+            mContextualChipWrapper.setScaleY(Math.min(scale, comp(mModalness)));
         }
         mDigitalWellBeingToast.updateBannerOffset(1f - scale,
                 mCurrentFullscreenParams.mCurrentDrawnInsets.top
@@ -797,14 +796,12 @@
             int expectedChipHeight = getExpectedViewHeight(view);
             float chipOffset = getResources().getDimension(R.dimen.chip_hint_vertical_offset);
             layoutParams.bottomMargin = -expectedChipHeight - (int) chipOffset;
-            mContextualChip = ((FrameLayout) mContextualChipWrapper).getChildAt(0);
-            mContextualChip.setScaleX(0f);
-            mContextualChip.setScaleY(0f);
+            mContextualChipWrapper.setScaleX(0f);
+            mContextualChipWrapper.setScaleY(0f);
             addView(view, getChildCount(), layoutParams);
-            if (mContextualChip != null) {
-                mContextualChip.animate().scaleX(1f).scaleY(1f).setDuration(50);
-            }
             if (mContextualChipWrapper != null) {
+                float scale = comp(mModalness);
+                mContextualChipWrapper.animate().scaleX(scale).scaleY(scale).setDuration(50);
                 mChipTouchDelegate = new TransformingTouchDelegate(mContextualChipWrapper);
             }
         }
@@ -825,7 +822,6 @@
         }
         View oldContextualChipWrapper = mContextualChipWrapper;
         mContextualChipWrapper = null;
-        mContextualChip = null;
         mChipTouchDelegate = null;
         return oldContextualChipWrapper;
     }
diff --git a/res/drawable/middle_item_primary.xml b/res/drawable/middle_item_primary.xml
index c975714..0c04ea1 100644
--- a/res/drawable/middle_item_primary.xml
+++ b/res/drawable/middle_item_primary.xml
@@ -16,5 +16,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <solid android:color="?attr/popupColorPrimary"/>
-    <corners android:radius="@dimen/popup_middle_item_radius" />
+    <corners android:radius="@dimen/popup_smaller_radius" />
 </shape>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 64c07d0..9d6c936 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -193,7 +193,7 @@
     <dimen name="deep_shortcut_icon_size">32dp</dimen>
     <dimen name="popup_margin">2dp</dimen>
     <dimen name="popup_single_item_radius">100dp</dimen>
-    <dimen name="popup_middle_item_radius">4dp</dimen>
+    <dimen name="popup_smaller_radius">4dp</dimen>
     <dimen name="deep_shortcut_drawable_padding">12dp</dimen>
     <dimen name="deep_shortcut_drag_handle_size">16dp</dimen>
     <dimen name="popup_padding_start">10dp</dimen>
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 8071782..d02efb0 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -100,6 +100,8 @@
     private int mRunningVInc;
     private int mMinHSpan;
     private int mMinVSpan;
+    private int mMaxHSpan;
+    private int mMaxVSpan;
     private int mDeltaX;
     private int mDeltaY;
     private int mDeltaXAddOn;
@@ -183,6 +185,8 @@
 
         mMinHSpan = info.minSpanX;
         mMinVSpan = info.minSpanY;
+        mMaxHSpan = info.maxSpanX;
+        mMaxVSpan = info.maxSpanY;
 
         mWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(getContext(),
                 widgetView.getAppWidgetInfo().provider, null);
@@ -314,7 +318,7 @@
         // expandability.
         mTempRange1.set(cellX, spanX + cellX);
         int hSpanDelta = mTempRange1.applyDeltaAndBound(mLeftBorderActive, mRightBorderActive,
-                hSpanInc, mMinHSpan, mCellLayout.getCountX(), mTempRange2);
+                hSpanInc, mMinHSpan, mMaxHSpan, mCellLayout.getCountX(), mTempRange2);
         cellX = mTempRange2.start;
         spanX = mTempRange2.size();
         if (hSpanDelta != 0) {
@@ -323,7 +327,7 @@
 
         mTempRange1.set(cellY, spanY + cellY);
         int vSpanDelta = mTempRange1.applyDeltaAndBound(mTopBorderActive, mBottomBorderActive,
-                vSpanInc, mMinVSpan, mCellLayout.getCountY(), mTempRange2);
+                vSpanInc, mMinVSpan, mMaxVSpan, mCellLayout.getCountY(), mTempRange2);
         cellY = mTempRange2.start;
         spanY = mTempRange2.size();
         if (vSpanDelta != 0) {
@@ -642,12 +646,15 @@
          * @param minSize minimum size after with the moving edge should not be shifted any further.
          *                For eg, if delta = -3 when moving the endEdge brings the size to less than
          *                minSize, only delta = -2 will applied
+         * @param maxSize maximum size after with the moving edge should not be shifted any further.
+         *                For eg, if delta = -3 when moving the endEdge brings the size to greater
+         *                than maxSize, only delta = -2 will applied
          * @param maxEnd The maximum value to the end edge (start edge is always restricted to 0)
          * @return the amount of increase when endEdge was moves and the amount of decrease when
          * the start edge was moved.
          */
         public int applyDeltaAndBound(boolean moveStart, boolean moveEnd, int delta,
-                int minSize, int maxEnd, IntRange out) {
+                int minSize, int maxSize, int maxEnd, IntRange out) {
             applyDelta(moveStart, moveEnd, delta, out);
             if (out.start < 0) {
                 out.start = 0;
@@ -662,6 +669,13 @@
                     out.end = out.start + minSize;
                 }
             }
+            if (out.size() > maxSize) {
+                if (moveStart) {
+                    out.start = out.end - maxSize;
+                } else if (moveEnd) {
+                    out.end = out.start + maxSize;
+                }
+            }
             return moveEnd ? out.size() - size() : size() - out.size();
         }
     }
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index a53fe1f..3736538 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -130,13 +130,14 @@
                 R.dimen.popup_arrow_horizontal_center_offset) - (mArrowWidth / 2);
         mArrowPointRadius = resources.getDimensionPixelSize(R.dimen.popup_arrow_corner_radius);
 
+        int smallerRadius = resources.getDimensionPixelSize(R.dimen.popup_smaller_radius);
         mRoundedTop = new GradientDrawable();
         mRoundedTop.setCornerRadii(new float[] { mOutlineRadius, mOutlineRadius, mOutlineRadius,
-                mOutlineRadius, 0, 0, 0, 0});
+                mOutlineRadius, smallerRadius, smallerRadius, smallerRadius, smallerRadius});
 
         mRoundedBottom = new GradientDrawable();
-        mRoundedBottom.setCornerRadii(new float[] { 0, 0, 0, 0, mOutlineRadius, mOutlineRadius,
-                mOutlineRadius, mOutlineRadius});
+        mRoundedBottom.setCornerRadii(new float[] { smallerRadius, smallerRadius, smallerRadius,
+                smallerRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius});
 
         int primaryColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
         int secondaryColor = Themes.getAttrColor(context, R.attr.popupColorSecondary);
@@ -272,7 +273,6 @@
         }
         onInflationComplete(reverseOrder);
         assignMarginsAndBackgrounds();
-        orientAboutObject();
         if (shouldAddArrow()) {
             addArrow();
         }
@@ -286,7 +286,6 @@
         setupForDisplay();
         onInflationComplete(false);
         assignMarginsAndBackgrounds();
-        orientAboutObject();
         if (shouldAddArrow()) {
             addArrow();
         }
@@ -383,10 +382,18 @@
     private void orientAboutObject(boolean allowAlignLeft, boolean allowAlignRight) {
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
 
-        int width = getMeasuredWidth();
         int extraVerticalSpace = mArrowHeight + mArrowOffsetVertical
                 + getResources().getDimensionPixelSize(R.dimen.popup_vertical_padding);
-        int height = getMeasuredHeight() + extraVerticalSpace;
+        // The margins are added after we call this method, so we need to account for them here.
+        int numVisibleChildren = 0;
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            if (getChildAt(i).getVisibility() == VISIBLE) {
+                numVisibleChildren++;
+            }
+        }
+        int childMargins = (numVisibleChildren - 1) * mMargin;
+        int height = getMeasuredHeight() + extraVerticalSpace + childMargins;
+        int width = getMeasuredWidth();
 
         getTargetObjectLocation(mTempRect);
         InsettableFrameLayout dragLayer = getPopupContainer();