From 6b79a3767dd7b64642269d288aae6d954a64d8b3 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Wed, 24 Jun 2020 12:48:11 -0700 Subject: [PATCH] Do preview grid migration in a worker thread Also remove USE_SURFACE_VIEW_FOR_PREVIEW flag Fixes: 159755324 Test: manual Change-Id: I6517c34911e217a69063226b01e4583194902f9c (cherry picked from commit 633a4bdf5724517509f6d40635cd16f14452e4e8) --- .../launcher3/config/FeatureFlags.java | 3 - .../graphics/GridOptionsProvider.java | 61 ---------------- .../graphics/LauncherPreviewRenderer.java | 55 ++------------- .../graphics/PreviewSurfaceRenderer.java | 70 ++++++++++++------- 4 files changed, 50 insertions(+), 139 deletions(-) diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 4f53d45c73..5c4a4922fd 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -138,9 +138,6 @@ public final class FeatureFlags { public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag( "ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", true, "Show launcher preview in grid picker"); - public static final BooleanFlag USE_SURFACE_VIEW_FOR_GRID_PREVIEW = getDebugFlag( - "USE_SURFACE_VIEW_FOR_GRID_PREVIEW", true, "Use surface view for grid preview"); - public static final BooleanFlag ENABLE_OVERVIEW_ACTIONS = getDebugFlag( "ENABLE_OVERVIEW_ACTIONS", true, "Show app actions instead of the shelf in Overview." + " As part of this decoupling, also distinguish swipe up from nav bar vs above it."); diff --git a/src/com/android/launcher3/graphics/GridOptionsProvider.java b/src/com/android/launcher3/graphics/GridOptionsProvider.java index 9bfd5bab87..08d7e4c65e 100644 --- a/src/com/android/launcher3/graphics/GridOptionsProvider.java +++ b/src/com/android/launcher3/graphics/GridOptionsProvider.java @@ -1,21 +1,14 @@ package com.android.launcher3.graphics; -import static com.android.launcher3.config.FeatureFlags.USE_SURFACE_VIEW_FOR_GRID_PREVIEW; -import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; - import android.content.ContentProvider; import android.content.ContentValues; import android.content.pm.PackageManager; import android.content.res.XmlResourceParser; import android.database.Cursor; import android.database.MatrixCursor; -import android.graphics.Bitmap; import android.net.Uri; import android.os.Binder; import android.os.Bundle; -import android.os.ParcelFileDescriptor; -import android.os.ParcelFileDescriptor.AutoCloseOutputStream; -import android.text.TextUtils; import android.util.Log; import android.util.Xml; @@ -26,12 +19,10 @@ import com.android.launcher3.R; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.Future; /** * Exposes various launcher grid options and allows the caller to change them. @@ -62,24 +53,7 @@ public class GridOptionsProvider extends ContentProvider { private static final String KEY_LIST_OPTIONS = "/list_options"; private static final String KEY_DEFAULT_GRID = "/default_grid"; - private static final String KEY_PREVIEW = "preview"; - private static final String MIME_TYPE_PNG = "image/png"; - private static final String METHOD_GET_PREVIEW = "get_preview"; - private static final String METADATA_KEY_PREVIEW_VERSION = "preview_version"; - - public static final PipeDataWriter> BITMAP_WRITER = - new PipeDataWriter>() { - @Override - public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String s, - Bundle bundle, Future bitmap) { - try (AutoCloseOutputStream os = new AutoCloseOutputStream(output)) { - bitmap.get().compress(Bitmap.CompressFormat.PNG, 100, os); - } catch (Exception e) { - Log.w(TAG, "fail to write to pipe", e); - } - } - }; @Override public boolean onCreate() { @@ -104,10 +78,6 @@ public class GridOptionsProvider extends ContentProvider { .add(KEY_IS_DEFAULT, idp.numColumns == gridOption.numColumns && idp.numRows == gridOption.numRows); } - Bundle metadata = new Bundle(); - metadata.putString(METADATA_KEY_PREVIEW_VERSION, - USE_SURFACE_VIEW_FOR_GRID_PREVIEW.get() ? "V2" : "V1"); - cursor.setExtras(metadata); return cursor; } @@ -132,10 +102,6 @@ public class GridOptionsProvider extends ContentProvider { @Override public String getType(Uri uri) { - List segments = uri.getPathSegments(); - if (segments.size() > 0 && KEY_PREVIEW.equals(segments.get(0))) { - return MIME_TYPE_PNG; - } return "vnd.android.cursor.dir/launcher_grid"; } @@ -172,33 +138,6 @@ public class GridOptionsProvider extends ContentProvider { return 1; } - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - List segments = uri.getPathSegments(); - if (segments.size() < 2 || !KEY_PREVIEW.equals(segments.get(0))) { - throw new FileNotFoundException("Invalid preview url"); - } - String profileName = segments.get(1); - if (TextUtils.isEmpty(profileName)) { - throw new FileNotFoundException("Invalid preview url"); - } - - InvariantDeviceProfile idp; - try { - idp = new InvariantDeviceProfile(getContext(), profileName); - } catch (Exception e) { - throw new FileNotFoundException(e.getMessage()); - } - - try { - return openPipeHelper(uri, MIME_TYPE_PNG, null, - UI_HELPER_EXECUTOR.submit(new LauncherPreviewRenderer(getContext(), idp)), - BITMAP_WRITER); - } catch (Exception e) { - throw new FileNotFoundException(e.getMessage()); - } - } - @Override public Bundle call(String method, String arg, Bundle extras) { if (getContext().checkPermission("android.permission.BIND_WALLPAPER", diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index 15f4e3fcec..885fb6698b 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -20,7 +20,6 @@ import static android.view.View.MeasureSpec.makeMeasureSpec; import static android.view.View.VISIBLE; import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER; -import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks; import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially; @@ -34,8 +33,6 @@ import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ShortcutInfo; import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.AdaptiveIconDrawable; @@ -63,20 +60,16 @@ import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; -import com.android.launcher3.Utilities; import com.android.launcher3.WorkspaceLayoutManager; import com.android.launcher3.allapps.SearchUiManager; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BitmapInfo; -import com.android.launcher3.icons.BitmapRenderer; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.AllAppsList; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.BgDataModel.Callbacks; -import com.android.launcher3.model.GridSizeMigrationTask; -import com.android.launcher3.model.GridSizeMigrationTaskV2; import com.android.launcher3.model.LoaderResults; import com.android.launcher3.model.LoaderTask; import com.android.launcher3.model.WidgetItem; @@ -105,7 +98,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.FutureTask; @@ -121,7 +113,7 @@ import java.util.concurrent.TimeoutException; * 4) Measure and draw the view on a canvas */ @TargetApi(Build.VERSION_CODES.O) -public class LauncherPreviewRenderer implements Callable { +public class LauncherPreviewRenderer { private static final String TAG = "LauncherPreviewRenderer"; @@ -213,15 +205,17 @@ public class LauncherPreviewRenderer implements Callable { private final Context mContext; private final InvariantDeviceProfile mIdp; private final DeviceProfile mDp; + private final boolean mMigrated; private final Rect mInsets; private final WorkspaceItemInfo mWorkspaceItemInfo; - public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp) { + public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) { mUiHandler = new Handler(Looper.getMainLooper()); mContext = context; mIdp = idp; mDp = idp.portraitProfile.copy(context); + mMigrated = migrated; // TODO: get correct insets once display cutout API is available. mInsets = new Rect(); @@ -243,28 +237,6 @@ public class LauncherPreviewRenderer implements Callable { context.getString(R.string.label_application); } - @Override - public Bitmap call() { - return BitmapRenderer.createHardwareBitmap(mDp.widthPx, mDp.heightPx, c -> { - - if (Looper.myLooper() == Looper.getMainLooper()) { - new MainThreadRenderer(mContext).renderScreenShot(c); - } else { - CountDownLatch latch = new CountDownLatch(1); - Utilities.postAsyncCallback(mUiHandler, () -> { - new MainThreadRenderer(mContext).renderScreenShot(c); - latch.countDown(); - }); - - try { - latch.await(); - } catch (Exception e) { - Log.e(TAG, "Error drawing on main thread", e); - } - } - }); - } - /** Populate preview and render it. */ public View getRenderedView() { MainThreadRenderer renderer = new MainThreadRenderer(mContext); @@ -407,20 +379,9 @@ public class LauncherPreviewRenderer implements Callable { private void populate() { if (ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER.get()) { - boolean needsToMigrate = - MULTI_DB_GRID_MIRATION_ALGO.get() - ? GridSizeMigrationTaskV2.needsToMigrate(mContext, mIdp) - : GridSizeMigrationTask.needsToMigrate(mContext, mIdp); - boolean success = false; - if (needsToMigrate) { - success = MULTI_DB_GRID_MIRATION_ALGO.get() - ? GridSizeMigrationTaskV2.migrateGridIfNeeded(mContext, mIdp) - : GridSizeMigrationTask.migrateGridIfNeeded(mContext, mIdp); - } - WorkspaceFetcher fetcher; PreviewContext previewContext = null; - if (needsToMigrate && success) { + if (mMigrated) { previewContext = new PreviewContext(mContext, mIdp); LauncherAppState appForPreview = new LauncherAppState( previewContext, null /* iconCacheFileName */); @@ -535,12 +496,6 @@ public class LauncherPreviewRenderer implements Callable { // Additional measure for views which use auto text size API measureView(mRootView, mDp.widthPx, mDp.heightPx); } - - private void renderScreenShot(Canvas canvas) { - populate(); - mRootView.draw(canvas); - dispatchVisibilityAggregated(mRootView, false); - } } private static void measureView(View view, int width, int height) { diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java index 350f221c97..fdc3a947a3 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -16,7 +16,9 @@ package com.android.launcher3.graphics; +import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.content.Context; import android.hardware.display.DisplayManager; @@ -32,6 +34,8 @@ import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.model.GridSizeMigrationTask; +import com.android.launcher3.model.GridSizeMigrationTaskV2; import java.util.concurrent.TimeUnit; @@ -93,32 +97,35 @@ public class PreviewSurfaceRenderer implements IBinder.DeathRecipient { return null; } - MAIN_EXECUTOR.execute(() -> { - // If mSurfaceControlViewHost is null due to any reason (e.g. binder died, - // happening when user leaves the preview screen before preview rendering finishes), - // we should return here. - SurfaceControlViewHost host = mSurfaceControlViewHost; - if (host == null) { - return; - } + MODEL_EXECUTOR.post(() -> { + final boolean success = doGridMigrationIfNecessary(); - View view = new LauncherPreviewRenderer(mContext, mIdp).getRenderedView(); - // 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()); - view.setScaleX(scale); - view.setScaleY(scale); - view.setPivotX(0); - view.setPivotY(0); - view.setTranslationX((mWidth - scale * view.getWidth()) / 2); - view.setTranslationY((mHeight - scale * view.getHeight()) / 2); - view.setAlpha(0); - view.animate().alpha(1) - .setInterpolator(new AccelerateDecelerateInterpolator()) - .setDuration(FADE_IN_ANIMATION_DURATION) - .start(); - host.setView(view, view.getMeasuredWidth(), - view.getMeasuredHeight()); + MAIN_EXECUTOR.post(() -> { + // If mSurfaceControlViewHost is null due to any reason (e.g. binder died, + // happening when user leaves the preview screen before preview rendering finishes), + // we should return here. + SurfaceControlViewHost host = mSurfaceControlViewHost; + if (host == null) { + return; + } + + View view = new LauncherPreviewRenderer(mContext, mIdp, success).getRenderedView(); + // 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()); + view.setScaleX(scale); + view.setScaleY(scale); + view.setPivotX(0); + view.setPivotY(0); + view.setTranslationX((mWidth - scale * view.getWidth()) / 2); + view.setTranslationY((mHeight - scale * view.getHeight()) / 2); + view.setAlpha(0); + view.animate().alpha(1) + .setInterpolator(new AccelerateDecelerateInterpolator()) + .setDuration(FADE_IN_ANIMATION_DURATION) + .start(); + host.setView(view, view.getMeasuredWidth(), view.getMeasuredHeight()); + }); }); Bundle result = new Bundle(); @@ -145,4 +152,17 @@ public class PreviewSurfaceRenderer implements IBinder.DeathRecipient { } mHostToken.unlinkToDeath(this, 0); } + + private boolean doGridMigrationIfNecessary() { + boolean needsToMigrate = + MULTI_DB_GRID_MIRATION_ALGO.get() + ? GridSizeMigrationTaskV2.needsToMigrate(mContext, mIdp) + : GridSizeMigrationTask.needsToMigrate(mContext, mIdp); + if (!needsToMigrate) { + return false; + } + return MULTI_DB_GRID_MIRATION_ALGO.get() + ? GridSizeMigrationTaskV2.migrateGridIfNeeded(mContext, mIdp) + : GridSizeMigrationTask.migrateGridIfNeeded(mContext, mIdp); + } }