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 633a4bdf57)
This commit is contained in:
Tracy Zhou
2020-06-24 12:48:11 -07:00
parent 9d69370095
commit f957ff9123
4 changed files with 50 additions and 139 deletions
@@ -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.");
@@ -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<Future<Bitmap>> BITMAP_WRITER =
new PipeDataWriter<Future<Bitmap>>() {
@Override
public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String s,
Bundle bundle, Future<Bitmap> 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<String> 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<String> 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",
@@ -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<Bitmap> {
public class LauncherPreviewRenderer {
private static final String TAG = "LauncherPreviewRenderer";
@@ -213,15 +205,17 @@ public class LauncherPreviewRenderer implements Callable<Bitmap> {
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<Bitmap> {
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<Bitmap> {
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<Bitmap> {
// 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) {
@@ -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);
}
}