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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user