From fd170e25cb65afa9a5948ad98364987c001d608e Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 13 Jul 2022 10:33:12 -0700 Subject: [PATCH 1/4] Provide 0 insets to VoiceInteractionWindow in gesture nav Test: Invoke assistant on tablet on both geture nav and 3 button mode; In gesture nav mode: assistant shows at the very bottom of the screen, layered on top of the taskbar background (in z order) In 3 button mode: assistant shows right above the taskbar, which only shows the 3 buttons (no taskbar icons) while assistant is showing Fixes: 225200928 Change-Id: I2fbc05e696b58e8801e704092aa2741cb57c05c4 --- .../launcher3/taskbar/TaskbarInsetsController.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index dc5c22d017..48fde8f26e 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.ITYPE_BOTTOM_MANDATORY_GESTURES 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 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask } } - 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 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask + " 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("})") From b57c0b2762c18dbdc1997931b0ea2ca65d0b7ff8 Mon Sep 17 00:00:00 2001 From: Sebastian Franco Date: Tue, 28 Jun 2022 13:54:35 -0700 Subject: [PATCH 2/4] Fixing findNearestArea to account for the padding. The function findNearestArea calculates the corner of the cell but in that calculation it doesn't account for the padding in the cells. Also, change ignoreOccupied because the name says one thing and the code does the oposite so I change all true calls for false calls and change the if to !ignoreOccupied so the description of the parameter match the behaviour of the method. Also, removing unused method. Fix: 236134208 Fix: 236129504 Test: visualizing the components of findNearestArea in ag/19248816. Change-Id: Iac50fbc76b4fa2acda21894ecb976ba612d468fe --- src/com/android/launcher3/CellLayout.java | 43 +++++++++-------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 52dfcd40a9..52960a9e8e 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -829,8 +829,8 @@ public class CellLayout extends ViewGroup { final int hStartPadding = getPaddingLeft(); final int vStartPadding = getPaddingTop(); - result[0] = (x - hStartPadding) / mCellWidth; - result[1] = (y - vStartPadding) / mCellHeight; + result[0] = (x - hStartPadding) / (mCellWidth + mBorderSpace.x); + result[1] = (y - vStartPadding) / (mCellHeight + mBorderSpace.y); final int xAxis = mCountX; final int yAxis = mCountY; @@ -841,16 +841,6 @@ public class CellLayout extends ViewGroup { if (result[1] >= yAxis) result[1] = yAxis - 1; } - /** - * Given a point, return the cell that most closely encloses that point - * @param x X coordinate of the point - * @param y Y coordinate of the point - * @param result Array of 2 ints to hold the x and y coordinate of the cell - */ - void pointToCellRounded(int x, int y, int[] result) { - pointToCellExact(x + (mCellWidth / 2), y + (mCellHeight / 2), result); - } - /** * Given a cell coordinate, return the point that represents the upper left corner of that cell * @@ -1240,7 +1230,7 @@ public class CellLayout extends ViewGroup { */ int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY, int[] result, int[] resultSpan) { - return findNearestArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, true, + return findNearestArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, false, result, resultSpan); } @@ -1262,9 +1252,10 @@ public class CellLayout extends ViewGroup { /** * Find a vacant area that will fit the given bounds nearest the requested * cell location. Uses Euclidean distance to score multiple vacant areas. - * - * @param pixelX The X location at which you want to search for a vacant area. - * @param pixelY The Y location at which you want to search for a vacant area. + * @param relativeXPos The X location relative to the Cell layout at which you want to search + * for a vacant area. + * @param relativeYPos The Y location relative to the Cell layout at which you want to search + * for a vacant area. * @param minSpanX The minimum horizontal span required * @param minSpanY The minimum vertical span required * @param spanX Horizontal span of the object. @@ -1275,15 +1266,15 @@ public class CellLayout extends ViewGroup { * @return The X, Y cell of a vacant area that can contain this object, * nearest the requested location. */ - private int[] findNearestArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, - int spanY, boolean ignoreOccupied, int[] result, int[] resultSpan) { + private int[] findNearestArea(int relativeXPos, int relativeYPos, int minSpanX, int minSpanY, + int spanX, int spanY, boolean ignoreOccupied, int[] result, int[] resultSpan) { lazyInitTempRectStack(); - // For items with a spanX / spanY > 1, the passed in point (pixelX, pixelY) corresponds - // to the center of the item, but we are searching based on the top-left cell, so - // we translate the point over to correspond to the top-left. - pixelX -= mCellWidth * (spanX - 1) / 2f; - pixelY -= mCellHeight * (spanY - 1) / 2f; + // For items with a spanX / spanY > 1, the passed in point (relativeXPos, relativeYPos) + // corresponds to the center of the item, but we are searching based on the top-left cell, + // so we translate the point over to correspond to the top-left. + relativeXPos = (int) (relativeXPos - (mCellWidth + mBorderSpace.x) * (spanX - 1) / 2f); + relativeYPos = (int) (relativeYPos - (mCellHeight + mBorderSpace.y) * (spanY - 1) / 2f); // Keep track of best-scoring drop area final int[] bestXY = result != null ? result : new int[2]; @@ -1304,7 +1295,7 @@ public class CellLayout extends ViewGroup { for (int x = 0; x < countX - (minSpanX - 1); x++) { int ySize = -1; int xSize = -1; - if (ignoreOccupied) { + if (!ignoreOccupied) { // First, let's see if this thing fits anywhere for (int i = 0; i < minSpanX; i++) { for (int j = 0; j < minSpanY; j++) { @@ -1368,7 +1359,7 @@ public class CellLayout extends ViewGroup { } } validRegions.push(currentRect); - double distance = Math.hypot(cellXY[0] - pixelX, cellXY[1] - pixelY); + double distance = Math.hypot(cellXY[0] - relativeXPos, cellXY[1] - relativeYPos); if ((distance <= bestDistance && !contained) || currentRect.contains(bestRect)) { @@ -2629,7 +2620,7 @@ public class CellLayout extends ViewGroup { * nearest the requested location. */ public int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, int[] result) { - return findNearestArea(pixelX, pixelY, spanX, spanY, spanX, spanY, false, result, null); + return findNearestArea(pixelX, pixelY, spanX, spanY, spanX, spanY, true, result, null); } boolean existsEmptyCell() { From 4c05fa3fba4162b614a2b5fa0a387f79139e9e57 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 14 Jul 2022 18:51:18 +0000 Subject: [PATCH 3/4] Replacing deprecated method Bug: 219861883 Test: Builds Change-Id: I8e008c042cb7fe74ced512b6a074892743ef25f8 --- quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index d7fea371f3..8f1872b11e 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1629,7 +1629,8 @@ public abstract class AbsSwipeUpHandler, // Cleanup when switching handlers mInputConsumerProxy.unregisterCallback(); mActivityInitListener.unregister(); - ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mActivityRestartListener); + TaskStackChangeListeners.getInstance().unregisterTaskStackListener( + mActivityRestartListener); mTaskSnapshot = null; } From dfd8bfc7e0540a4f166e07e46b8cdd7d9cac44b1 Mon Sep 17 00:00:00 2001 From: Sihua Ma Date: Tue, 12 Jul 2022 13:19:41 -0700 Subject: [PATCH 4/4] Added functions to pass launcher widget span info to preview To calculate the widget scales correctly for the launcher preview in different grids, the span info of the widgets in the launcher is necessary. Querying the launcher widget info in the database and passing it to the preview render. Test: Verified that no exceptions were happening when changing preview grid layouts Bug: 228328759 Change-Id: I681d21b176c8fe5208431a79009d9ba8279cda6a --- .../graphics/LauncherPreviewRenderer.java | 11 +++- .../graphics/PreviewSurfaceRenderer.java | 59 +++++++++++++++++-- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index d5bcb0cbcb..a8546e8448 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -43,6 +43,8 @@ import android.os.Build; 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.WindowInsets; 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 @@ public class LauncherPreviewRenderer extends ContextWrapper private final Map mWorkspaceScreens = new HashMap<>(); private final AppWidgetHost mAppWidgetHost; private final SparseIntArray mWallpaperColorResources; + private final SparseArray mLauncherWidgetSpanInfo; public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp, - WallpaperColors wallpaperColorsOverride) { + WallpaperColors wallpaperColorsOverride, + @Nullable final SparseArray launcherWidgetSpanInfo) { super(context); mUiHandler = new Handler(Looper.getMainLooper()); @@ -224,6 +230,9 @@ public class LauncherPreviewRenderer extends ContextWrapper 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 fd11b37795..287b9760fe 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -22,10 +22,13 @@ import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; 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.View; 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; @@ -123,6 +128,45 @@ public class PreviewSurfaceRenderer { mOnDestroyCallbacks.executeAllAndDestroy(); } + /** + * 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 getLoadedLauncherWidgetInfo( + @NonNull final Context context) { + final SparseArray 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 */ @@ -174,8 +218,11 @@ public class PreviewSurfaceRenderer { loadWorkspace(new ArrayList<>(), LauncherSettings.Favorites.PREVIEW_CONTENT_URI, query); + final SparseArray spanInfo = + getLoadedLauncherWidgetInfo(previewContext.getBaseContext()); + MAIN_EXECUTOR.execute(() -> { - renderView(previewContext, mBgDataModel, mWidgetProvidersMap); + renderView(previewContext, mBgDataModel, mWidgetProvidersMap, spanInfo); mOnDestroyCallbacks.add(previewContext::onDestroy); }); } @@ -183,7 +230,8 @@ public class PreviewSurfaceRenderer { } 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 @@ public class PreviewSurfaceRenderer { @UiThread private void renderView(Context inflationContext, BgDataModel dataModel, - Map widgetProviderInfoMap) { + Map widgetProviderInfoMap, + @Nullable final SparseArray 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());