From dfd8bfc7e0540a4f166e07e46b8cdd7d9cac44b1 Mon Sep 17 00:00:00 2001 From: Sihua Ma Date: Tue, 12 Jul 2022 13:19:41 -0700 Subject: [PATCH] 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());