Merge "Fixing findNearestArea to account for the padding." into tm-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index dc5c22d..48fde8f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -22,6 +22,7 @@
 import android.view.InsetsState
 import android.view.WindowManager
 import android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD
+import android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION
 import com.android.launcher3.AbstractFloatingView
 import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS
 import com.android.launcher3.DeviceProfile
@@ -88,11 +89,17 @@
             }
         }
 
-        var imeInsetsSize = Insets.of(0, 0, 0, taskbarHeightForIme)
-        var insetsSizeOverride = arrayOf(
+        val imeInsetsSize = Insets.of(0, 0, 0, taskbarHeightForIme)
+        // Use 0 insets for the VoiceInteractionWindow (assistant) when gesture nav is enabled.
+        val visInsetsSize = Insets.of(0, 0, 0, if (context.isGestureNav) 0 else tappableHeight)
+        val insetsSizeOverride = arrayOf(
             InsetsFrameProvider.InsetsSizeOverride(
                 TYPE_INPUT_METHOD,
                 imeInsetsSize
+            ),
+            InsetsFrameProvider.InsetsSizeOverride(
+                TYPE_VOICE_INTERACTION,
+                visInsetsSize
             )
         )
         for (provider in windowLayoutParams.providedInsets) {
@@ -153,7 +160,8 @@
                     + " insetsSize=" + provider.insetsSize)
             if (provider.insetsSizeOverrides != null) {
                 pw.print(" insetsSizeOverrides={")
-                for (overrideSize in provider.insetsSizeOverrides) {
+                for ((i, overrideSize) in provider.insetsSizeOverrides.withIndex()) {
+                    if (i > 0) pw.print(", ")
                     pw.print(overrideSize)
                 }
                 pw.print("})")
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 4b4a017..fbb0a57 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -24,6 +24,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 
@@ -68,22 +69,6 @@
 
     private final View[] mDragHandles = new View[HANDLE_COUNT];
     private final List<Rect> mSystemGestureExclusionRects = new ArrayList<>(HANDLE_COUNT);
-    private final OnAttachStateChangeListener mWidgetViewAttachStateChangeListener =
-            new OnAttachStateChangeListener() {
-                @Override
-                public void onViewAttachedToWindow(View view) {
-                    // Do nothing
-                }
-
-                @Override
-                public void onViewDetachedFromWindow(View view) {
-                    // When the app widget view is detached, we should close the resize frame.
-                    // An example is when the dragging starts, the widget view is detached from
-                    // CellLayout and then reattached to DragLayout.
-                    close(false);
-                }
-            };
-
 
     private LauncherAppWidgetHostView mWidgetView;
     private CellLayout mCellLayout;
@@ -221,11 +206,7 @@
     private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
             DragLayer dragLayer) {
         mCellLayout = cellLayout;
-        if (mWidgetView != null) {
-            mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
-        }
         mWidgetView = widgetView;
-        mWidgetView.addOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
         LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo)
                 widgetView.getAppWidgetInfo();
         mDragLayer = dragLayer;
@@ -423,6 +404,10 @@
      *  Based on the current deltas, we determine if and how to resize the widget.
      */
     private void resizeWidgetIfNeeded(boolean onDismiss) {
+        ViewGroup.LayoutParams wlp = mWidgetView.getLayoutParams();
+        if (!(wlp instanceof CellLayout.LayoutParams)) {
+            return;
+        }
         DeviceProfile dp = mLauncher.getDeviceProfile();
         float xThreshold = mCellLayout.getCellWidth() + dp.cellLayoutBorderSpacePx.x;
         float yThreshold = mCellLayout.getCellHeight() + dp.cellLayoutBorderSpacePx.y;
@@ -435,7 +420,7 @@
         mDirectionVector[0] = 0;
         mDirectionVector[1] = 0;
 
-        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams();
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) wlp;
 
         int spanX = lp.cellHSpan;
         int spanY = lp.cellVSpan;
@@ -687,9 +672,6 @@
     @Override
     protected void handleClose(boolean animate) {
         mDragLayer.removeView(this);
-        if (mWidgetView != null) {
-            mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
-        }
     }
 
     private void updateInvalidResizeEffect(CellLayout cellLayout, CellLayout pairedCellLayout,
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index d5bcb0c..a8546e8 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -43,6 +43,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.util.AttributeSet;
+import android.util.Size;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -53,6 +55,8 @@
 import android.view.WindowManager;
 import android.widget.TextClock;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DeviceProfile;
@@ -177,10 +181,12 @@
     private final Map<Integer, CellLayout> mWorkspaceScreens = new HashMap<>();
     private final AppWidgetHost mAppWidgetHost;
     private final SparseIntArray mWallpaperColorResources;
+    private final SparseArray<Size> mLauncherWidgetSpanInfo;
 
     public LauncherPreviewRenderer(Context context,
             InvariantDeviceProfile idp,
-            WallpaperColors wallpaperColorsOverride) {
+            WallpaperColors wallpaperColorsOverride,
+            @Nullable final SparseArray<Size> launcherWidgetSpanInfo) {
 
         super(context);
         mUiHandler = new Handler(Looper.getMainLooper());
@@ -224,6 +230,9 @@
         mHotseat = mRootView.findViewById(R.id.hotseat);
         mHotseat.resetLayout(false);
 
+        mLauncherWidgetSpanInfo = launcherWidgetSpanInfo == null ? new SparseArray<>() :
+                launcherWidgetSpanInfo;
+
         CellLayout firstScreen = mRootView.findViewById(R.id.workspace);
         firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingPx.left,
                 mDp.workspacePadding.top + mDp.cellLayoutPaddingPx.top,
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index fd11b37..287b976 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -22,10 +22,13 @@
 import android.app.WallpaperColors;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
+import android.database.Cursor;
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.util.Log;
+import android.util.Size;
+import android.util.SparseArray;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.SurfaceControlViewHost;
@@ -34,6 +37,8 @@
 import android.view.WindowManager.LayoutParams;
 import android.view.animation.AccelerateDecelerateInterpolator;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 import androidx.annotation.WorkerThread;
 
@@ -124,6 +129,45 @@
     }
 
     /**
+     * A function that queries for the launcher app widget span info
+     *
+     * @param context The context to get the content resolver from, should be related to launcher
+     * @return A SparseArray with the app widget id being the key and the span info being the values
+     */
+    @WorkerThread
+    @Nullable
+    public SparseArray<Size> getLoadedLauncherWidgetInfo(
+            @NonNull final Context context) {
+        final SparseArray<Size> widgetInfo = new SparseArray<>();
+        final String query = LauncherSettings.Favorites.ITEM_TYPE + " = "
+                + LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+
+        try (Cursor c = context.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+                new String[] {
+                        LauncherSettings.Favorites.APPWIDGET_ID,
+                        LauncherSettings.Favorites.SPANX,
+                        LauncherSettings.Favorites.SPANY
+                }, query, null, null)) {
+            final int appWidgetIdIndex = c.getColumnIndexOrThrow(
+                    LauncherSettings.Favorites.APPWIDGET_ID);
+            final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
+            final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
+            while (c.moveToNext()) {
+                final int appWidgetId = c.getInt(appWidgetIdIndex);
+                final int spanX = c.getInt(spanXIndex);
+                final int spanY = c.getInt(spanYIndex);
+
+                widgetInfo.append(appWidgetId, new Size(spanX, spanY));
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error querying for launcher widget info", e);
+            return null;
+        }
+
+        return widgetInfo;
+    }
+
+    /**
      * Generates the preview in background
      */
     public void loadAsync() {
@@ -174,8 +218,11 @@
                     loadWorkspace(new ArrayList<>(), LauncherSettings.Favorites.PREVIEW_CONTENT_URI,
                             query);
 
+                    final SparseArray<Size> spanInfo =
+                            getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
+
                     MAIN_EXECUTOR.execute(() -> {
-                        renderView(previewContext, mBgDataModel, mWidgetProvidersMap);
+                        renderView(previewContext, mBgDataModel, mWidgetProvidersMap, spanInfo);
                         mOnDestroyCallbacks.add(previewContext::onDestroy);
                     });
                 }
@@ -183,7 +230,8 @@
         } else {
             LauncherAppState.getInstance(inflationContext).getModel().loadAsync(dataModel -> {
                 if (dataModel != null) {
-                    MAIN_EXECUTOR.execute(() -> renderView(inflationContext, dataModel, null));
+                    MAIN_EXECUTOR.execute(() -> renderView(inflationContext, dataModel, null,
+                            null));
                 } else {
                     Log.e(TAG, "Model loading failed");
                 }
@@ -201,12 +249,13 @@
 
     @UiThread
     private void renderView(Context inflationContext, BgDataModel dataModel,
-            Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) {
+            Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap,
+            @Nullable final SparseArray<Size> launcherWidgetSpanInfo) {
         if (mDestroyed) {
             return;
         }
-        View view = new LauncherPreviewRenderer(inflationContext, mIdp, mWallpaperColors)
-                .getRenderedView(dataModel, widgetProviderInfoMap);
+        View view = new LauncherPreviewRenderer(inflationContext, mIdp, mWallpaperColors,
+                launcherWidgetSpanInfo).getRenderedView(dataModel, widgetProviderInfoMap);
         // This aspect scales the view to fit in the surface and centers it
         final float scale = Math.min(mWidth / (float) view.getMeasuredWidth(),
                 mHeight / (float) view.getMeasuredHeight());