Merge "Adding support for generating a preview bitmap with an optional delay to allow widgets to be rendered" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
d506f0154b
@@ -26,14 +26,18 @@ import android.content.pm.ActivityInfo
|
||||
import android.content.pm.LauncherActivityInfo
|
||||
import android.content.pm.LauncherApps
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.os.Flags.allowPrivateProfile
|
||||
import android.os.IBinder
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.util.ArrayMap
|
||||
import android.view.SurfaceControlViewHost
|
||||
import android.widget.Toast
|
||||
import android.window.RemoteTransition
|
||||
import android.window.ScreenCapture
|
||||
import com.android.launcher3.Flags.enablePrivateSpace
|
||||
import com.android.launcher3.Flags.privateSpaceSysAppsSeparation
|
||||
import com.android.launcher3.R
|
||||
@@ -193,4 +197,15 @@ open class SystemApiWrapper @Inject constructor(@ApplicationContext context: Con
|
||||
|
||||
override fun isFileDrawable(shortcutInfo: ShortcutInfo) =
|
||||
shortcutInfo.hasIconFile() || shortcutInfo.hasIconUri()
|
||||
|
||||
override fun captureSnapshot(host: SurfaceControlViewHost, width: Int, height: Int): Bitmap =
|
||||
ScreenCapture.captureLayers(
|
||||
ScreenCapture.LayerCaptureArgs.Builder(host.surfacePackage!!.surfaceControl)
|
||||
.setSourceCrop(Rect(0, 0, width, height))
|
||||
.setAllowProtected(true)
|
||||
.setHintForSeamlessTransition(true)
|
||||
.build()
|
||||
)
|
||||
.asBitmap()
|
||||
.copy(Bitmap.Config.ARGB_8888, true)
|
||||
}
|
||||
|
||||
@@ -42,8 +42,6 @@ public interface WorkspaceLayoutManager {
|
||||
|
||||
// The is the first screen. It is always present, even if its empty.
|
||||
int FIRST_SCREEN_ID = 0;
|
||||
// This is the second page. On two panel home it is always present, even if its empty.
|
||||
int SECOND_SCREEN_ID = 1;
|
||||
|
||||
/**
|
||||
* At bind time, we use the rank (screenId) to compute x and y for hotseat items.
|
||||
|
||||
@@ -15,19 +15,25 @@
|
||||
*/
|
||||
package com.android.launcher3.graphics;
|
||||
|
||||
|
||||
import static com.android.launcher3.BuildConfig.IS_DEBUG_DEVICE;
|
||||
import static com.android.launcher3.Flags.enableLauncherIconShapes;
|
||||
import static com.android.launcher3.graphics.PreviewSurfaceRenderer.KEY_BITMAP_GENERATION_DELAY_MS;
|
||||
import static com.android.launcher3.graphics.PreviewSurfaceRenderer.KEY_VIEW_HEIGHT;
|
||||
import static com.android.launcher3.graphics.PreviewSurfaceRenderer.KEY_VIEW_WIDTH;
|
||||
import static com.android.launcher3.graphics.PreviewSurfaceRenderer.MIN_BITMAP_GENERATION_DELAY_MS;
|
||||
import static com.android.launcher3.graphics.ThemeManager.PREF_ICON_SHAPE;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
import static java.util.concurrent.CompletableFuture.delayedExecutor;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@@ -50,6 +56,7 @@ import com.android.launcher3.dagger.LauncherAppSingleton;
|
||||
import com.android.launcher3.model.BgDataModel;
|
||||
import com.android.launcher3.shapes.IconShapeModel;
|
||||
import com.android.launcher3.shapes.ShapesProvider;
|
||||
import com.android.launcher3.util.ApiWrapper;
|
||||
import com.android.launcher3.util.ContentProviderProxy.ProxyProvider;
|
||||
import com.android.launcher3.util.DaggerSingletonTracker;
|
||||
import com.android.launcher3.util.Executors;
|
||||
@@ -118,6 +125,7 @@ public class GridCustomizationsProxy implements ProxyProvider {
|
||||
private static final String SET_SHAPE = "/shape";
|
||||
|
||||
private static final String METHOD_GET_PREVIEW = "get_preview";
|
||||
public static final String METHOD_GET_PREVIEW_BITMAP = "get_preview_bitmap";
|
||||
|
||||
private static final String GET_ICON_THEMED = "/get_icon_themed";
|
||||
private static final String SET_ICON_THEMED = "/set_icon_themed";
|
||||
@@ -128,6 +136,7 @@ public class GridCustomizationsProxy implements ProxyProvider {
|
||||
private static final String KEY_CALLBACK = "callback";
|
||||
public static final String KEY_HIDE_BOTTOM_ROW = "hide_bottom_row";
|
||||
public static final String KEY_GRID_NAME = "grid_name";
|
||||
public static final String KEY_IMAGE = "image";
|
||||
|
||||
private static final int MESSAGE_ID_UPDATE_PREVIEW = 1337;
|
||||
private static final int MESSAGE_ID_UPDATE_SHAPE = 2586;
|
||||
@@ -309,18 +318,45 @@ public class GridCustomizationsProxy implements ProxyProvider {
|
||||
|
||||
@Override
|
||||
public Bundle call(@NonNull String method, String arg, Bundle extras) {
|
||||
if (METHOD_GET_PREVIEW.equals(method)) {
|
||||
return getPreview(extras);
|
||||
} else {
|
||||
return null;
|
||||
return switch (method) {
|
||||
case METHOD_GET_PREVIEW -> getPreview(extras);
|
||||
case METHOD_GET_PREVIEW_BITMAP -> getPreviewBitmap(extras);
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private Bundle getPreviewBitmap(Bundle request) {
|
||||
RunnableList lifeCycleTracker = new RunnableList();
|
||||
try {
|
||||
int width = request.getInt(KEY_VIEW_WIDTH);
|
||||
int height = request.getInt(KEY_VIEW_HEIGHT);
|
||||
long previewDelay = Math.max(request.getLong(KEY_BITMAP_GENERATION_DELAY_MS, 0),
|
||||
MIN_BITMAP_GENERATION_DELAY_MS);
|
||||
|
||||
PreviewSurfaceRenderer renderer = new PreviewSurfaceRenderer(
|
||||
mContext, lifeCycleTracker, request, Binder.getCallingPid(),
|
||||
true /* skip animations */);
|
||||
renderer.loadAsync().thenRunAsync(
|
||||
() -> { }, delayedExecutor(previewDelay, MILLISECONDS, MAIN_EXECUTOR)).get();
|
||||
Bitmap previewBitmap = ApiWrapper.INSTANCE.get(mContext)
|
||||
.captureSnapshot(renderer.getHost(), width, height);
|
||||
|
||||
Bundle result = new Bundle();
|
||||
result.putParcelable(KEY_IMAGE, previewBitmap);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to generate preview", e);
|
||||
}
|
||||
MAIN_EXECUTOR.execute(lifeCycleTracker::executeAllAndDestroy);
|
||||
return null;
|
||||
}
|
||||
|
||||
private synchronized Bundle getPreview(Bundle request) {
|
||||
RunnableList lifeCycleTracker = new RunnableList();
|
||||
try {
|
||||
PreviewSurfaceRenderer renderer = new PreviewSurfaceRenderer(
|
||||
mContext, lifeCycleTracker, request, Binder.getCallingPid());
|
||||
mContext, lifeCycleTracker, request, Binder.getCallingPid(),
|
||||
false /* skip animations */);
|
||||
PreviewLifecycleObserver observer =
|
||||
new PreviewLifecycleObserver(lifeCycleTracker, renderer);
|
||||
|
||||
@@ -333,7 +369,7 @@ public class GridCustomizationsProxy implements ProxyProvider {
|
||||
renderer.getHostToken().linkToDeath(observer, 0);
|
||||
|
||||
Bundle result = new Bundle();
|
||||
result.putParcelable(KEY_SURFACE_PACKAGE, renderer.getSurfacePackage());
|
||||
result.putParcelable(KEY_SURFACE_PACKAGE, renderer.getHost().getSurfacePackage());
|
||||
|
||||
mActivePreviews.add(observer);
|
||||
lifeCycleTracker.add(() -> mActivePreviews.remove(observer));
|
||||
|
||||
@@ -68,7 +68,6 @@ import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.ProxyPrefs;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.WorkspaceLayoutManager;
|
||||
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
|
||||
import com.android.launcher3.celllayout.CellPosMapper;
|
||||
@@ -165,7 +164,11 @@ public class LauncherPreviewRenderer extends BaseContext
|
||||
emptyDbDir();
|
||||
mDbDir.mkdirs();
|
||||
builder.bindParserFactory(new XmlLayoutParserFactory(this, layoutXml))
|
||||
.bindWidgetsFactory(c -> new LauncherWidgetHolder(c, widgetHostId));
|
||||
.bindWidgetsFactory(c -> {
|
||||
LauncherWidgetHolder holder = new LauncherWidgetHolder(c, widgetHostId);
|
||||
holder.startListening();
|
||||
return holder;
|
||||
});
|
||||
}
|
||||
initDaggerComponent(builder);
|
||||
|
||||
@@ -212,14 +215,17 @@ public class LauncherPreviewRenderer extends BaseContext
|
||||
public LauncherPreviewRenderer(Context context,
|
||||
InvariantDeviceProfile idp,
|
||||
WallpaperColors wallpaperColorsOverride,
|
||||
int workspaceScreenId,
|
||||
@Nullable final SparseArray<Size> launcherWidgetSpanInfo) {
|
||||
this(context, idp, null, wallpaperColorsOverride, launcherWidgetSpanInfo);
|
||||
this(context, idp, null, wallpaperColorsOverride, workspaceScreenId,
|
||||
launcherWidgetSpanInfo);
|
||||
}
|
||||
|
||||
public LauncherPreviewRenderer(Context context,
|
||||
InvariantDeviceProfile idp,
|
||||
SparseIntArray previewColorOverride,
|
||||
WallpaperColors wallpaperColorsOverride,
|
||||
int workspaceScreenId,
|
||||
@Nullable final SparseArray<Size> launcherWidgetSpanInfo) {
|
||||
|
||||
super(context, Themes.getActivityThemeRes(context));
|
||||
@@ -262,7 +268,6 @@ public class LauncherPreviewRenderer extends BaseContext
|
||||
: (mDp.workspacePadding.right + mDp.cellLayoutPaddingPx.right),
|
||||
mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
|
||||
);
|
||||
mWorkspaceScreens.put(FIRST_SCREEN_ID, firstScreen);
|
||||
|
||||
if (mDp.isTwoPanels) {
|
||||
CellLayout rightPanel = mRootView.findViewById(R.id.workspace_right);
|
||||
@@ -272,7 +277,12 @@ public class LauncherPreviewRenderer extends BaseContext
|
||||
mDp.workspacePadding.right + mDp.cellLayoutPaddingPx.right,
|
||||
mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
|
||||
);
|
||||
mWorkspaceScreens.put(Workspace.SECOND_SCREEN_ID, rightPanel);
|
||||
|
||||
int closestEvenPageId = workspaceScreenId - (workspaceScreenId % 2);
|
||||
mWorkspaceScreens.put(closestEvenPageId, firstScreen);
|
||||
mWorkspaceScreens.put(closestEvenPageId + 1, rightPanel);
|
||||
} else {
|
||||
mWorkspaceScreens.put(workspaceScreenId, firstScreen);
|
||||
}
|
||||
|
||||
SparseIntArray wallpaperColorResources;
|
||||
@@ -462,12 +472,15 @@ public class LauncherPreviewRenderer extends BaseContext
|
||||
// Add first page QSB
|
||||
if (BuildConfig.QSB_ON_FIRST_SCREEN) {
|
||||
CellLayout firstScreen = mWorkspaceScreens.get(FIRST_SCREEN_ID);
|
||||
View qsb = mHomeElementInflater.inflate(R.layout.qsb_preview, firstScreen, false);
|
||||
// TODO: set bgHandler on qsb when it is BaseTemplateCard, which requires API changes.
|
||||
CellLayoutLayoutParams lp = new CellLayoutLayoutParams(
|
||||
0, 0, firstScreen.getCountX(), 1);
|
||||
lp.canReorder = false;
|
||||
firstScreen.addViewToCellLayout(qsb, 0, R.id.search_container_workspace, lp, true);
|
||||
if (firstScreen != null) {
|
||||
View qsb = mHomeElementInflater.inflate(R.layout.qsb_preview, firstScreen, false);
|
||||
// TODO: set bgHandler on qsb when it is BaseTemplateCard, which requires API
|
||||
// changes.
|
||||
CellLayoutLayoutParams lp = new CellLayoutLayoutParams(
|
||||
0, 0, firstScreen.getCountX(), 1);
|
||||
lp.canReorder = false;
|
||||
firstScreen.addViewToCellLayout(qsb, 0, R.id.search_container_workspace, lp, true);
|
||||
}
|
||||
}
|
||||
|
||||
measureView(mRootView, mDp.widthPx, mDp.heightPx);
|
||||
|
||||
@@ -24,7 +24,6 @@ import static com.android.launcher3.Flags.extendibleThemeManager;
|
||||
import static com.android.launcher3.LauncherPrefs.GRID_NAME;
|
||||
import static com.android.launcher3.LauncherPrefs.NON_FIXED_LANDSCAPE_GRID_NAME;
|
||||
import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
|
||||
import static com.android.launcher3.WorkspaceLayoutManager.SECOND_SCREEN_ID;
|
||||
import static com.android.launcher3.graphics.ThemeManager.PREF_ICON_SHAPE;
|
||||
import static com.android.launcher3.graphics.ThemeManager.THEMED_ICONS;
|
||||
import static com.android.launcher3.provider.LauncherDbUtils.selectionForWorkspaceScreen;
|
||||
@@ -48,7 +47,6 @@ import android.util.SparseIntArray;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.Display;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
import android.view.SurfaceControlViewHost.SurfacePackage;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -77,6 +75,7 @@ import com.android.launcher3.widget.LocalColorExtractor;
|
||||
import com.android.systemui.shared.Flags;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** Render preview using surface view. */
|
||||
@@ -84,17 +83,21 @@ import java.util.concurrent.TimeUnit;
|
||||
public class PreviewSurfaceRenderer {
|
||||
|
||||
private static final String TAG = "PreviewSurfaceRenderer";
|
||||
private static final int FADE_IN_ANIMATION_DURATION = 200;
|
||||
private static final String KEY_HOST_TOKEN = "host_token";
|
||||
private static final String KEY_VIEW_WIDTH = "width";
|
||||
private static final String KEY_VIEW_HEIGHT = "height";
|
||||
private static final String KEY_DISPLAY_ID = "display_id";
|
||||
private static final String KEY_COLORS = "wallpaper_colors";
|
||||
private static final String KEY_COLOR_RESOURCE_IDS = "color_resource_ids";
|
||||
private static final String KEY_COLOR_VALUES = "color_values";
|
||||
private static final String KEY_DARK_MODE = "use_dark_mode";
|
||||
private static final String KEY_LAYOUT_XML = "layout_xml";
|
||||
public static final String KEY_SKIP_ANIMATIONS = "skip_animations";
|
||||
public static final int FADE_IN_ANIMATION_DURATION = 200;
|
||||
public static final String KEY_HOST_TOKEN = "host_token";
|
||||
public static final String KEY_VIEW_WIDTH = "width";
|
||||
public static final String KEY_VIEW_HEIGHT = "height";
|
||||
public static final String KEY_DISPLAY_ID = "display_id";
|
||||
public static final String KEY_COLORS = "wallpaper_colors";
|
||||
public static final String KEY_COLOR_RESOURCE_IDS = "color_resource_ids";
|
||||
public static final String KEY_COLOR_VALUES = "color_values";
|
||||
public static final String KEY_DARK_MODE = "use_dark_mode";
|
||||
public static final String KEY_LAYOUT_XML = "layout_xml";
|
||||
public static final String KEY_BITMAP_GENERATION_DELAY_MS = "bitmap_delay_ms";
|
||||
// Wait for some time before capturing screenshot to allow the surface to be laid out
|
||||
public static final long MIN_BITMAP_GENERATION_DELAY_MS = 100L;
|
||||
|
||||
public static final String KEY_WORKSPACE_PAGE_ID = "workspace_page_id";
|
||||
public static final String FIXED_LANDSCAPE_GRID = "fixed_landscape_mode";
|
||||
|
||||
private final Context mContext;
|
||||
@@ -103,6 +106,7 @@ public class PreviewSurfaceRenderer {
|
||||
private String mLastSelectedGridName;
|
||||
private String mShapeKey;
|
||||
private String mLayoutXml;
|
||||
private int mWorkspacePageId;
|
||||
private boolean mIsMonoThemeEnabled;
|
||||
|
||||
@Nullable private Boolean mDarkMode;
|
||||
@@ -127,7 +131,7 @@ public class PreviewSurfaceRenderer {
|
||||
@Nullable private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
|
||||
|
||||
public PreviewSurfaceRenderer(Context context, RunnableList lifecycleTracker, Bundle bundle,
|
||||
int callingPid) throws Exception {
|
||||
int callingPid, boolean skipAnimations) throws Exception {
|
||||
mContext = context;
|
||||
mLifeCycleTracker = lifecycleTracker;
|
||||
mCallingPid = callingPid;
|
||||
@@ -151,11 +155,12 @@ public class PreviewSurfaceRenderer {
|
||||
mHostToken = bundle.getBinder(KEY_HOST_TOKEN);
|
||||
mWidth = bundle.getInt(KEY_VIEW_WIDTH);
|
||||
mHeight = bundle.getInt(KEY_VIEW_HEIGHT);
|
||||
mSkipAnimations = bundle.getBoolean(KEY_SKIP_ANIMATIONS, false);
|
||||
mSkipAnimations = skipAnimations;
|
||||
mDisplayId = bundle.getInt(KEY_DISPLAY_ID);
|
||||
mDisplay = context.getSystemService(DisplayManager.class)
|
||||
.getDisplay(mDisplayId);
|
||||
mLayoutXml = bundle.getString(KEY_LAYOUT_XML);
|
||||
mWorkspacePageId = bundle.getInt(KEY_WORKSPACE_PAGE_ID, FIRST_SCREEN_ID);
|
||||
if (mDisplay == null) {
|
||||
throw new IllegalArgumentException("Display ID does not match any displays.");
|
||||
}
|
||||
@@ -177,11 +182,8 @@ public class PreviewSurfaceRenderer {
|
||||
return mHostToken;
|
||||
}
|
||||
|
||||
public SurfacePackage getSurfacePackage() {
|
||||
if (mSurfacePackage == null) {
|
||||
mSurfacePackage = mSurfaceControlViewHost.getSurfacePackage();
|
||||
}
|
||||
return mSurfacePackage;
|
||||
public SurfaceControlViewHost getHost() {
|
||||
return mSurfaceControlViewHost;
|
||||
}
|
||||
|
||||
private void setCurrentRenderer(LauncherPreviewRenderer renderer) {
|
||||
@@ -241,10 +243,12 @@ public class PreviewSurfaceRenderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the preview in background
|
||||
* Generates the preview in background and returns the generated view
|
||||
*/
|
||||
public void loadAsync() {
|
||||
MODEL_EXECUTOR.execute(this::loadModelData);
|
||||
public CompletableFuture<View> loadAsync() {
|
||||
CompletableFuture<View> result = new CompletableFuture<>();
|
||||
MODEL_EXECUTOR.execute(() -> loadModelData(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -379,7 +383,7 @@ public class PreviewSurfaceRenderer {
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void loadModelData() {
|
||||
private void loadModelData(CompletableFuture<View> onCompleteCallback) {
|
||||
final Context inflationContext = getPreviewContext();
|
||||
if (shouldReloadModelData()) {
|
||||
boolean isCustomLayout = extendibleThemeManager() && !TextUtils.isEmpty(mLayoutXml);
|
||||
@@ -409,21 +413,26 @@ public class PreviewSurfaceRenderer {
|
||||
|
||||
InvariantDeviceProfile idp = appComponent.getIDP();
|
||||
DeviceProfile deviceProfile = idp.getDeviceProfile(previewContext);
|
||||
|
||||
int closestEvenPageId = mWorkspacePageId - (mWorkspacePageId % 2);
|
||||
String query = deviceProfile.isTwoPanels
|
||||
? selectionForWorkspaceScreen(FIRST_SCREEN_ID, SECOND_SCREEN_ID)
|
||||
: selectionForWorkspaceScreen(FIRST_SCREEN_ID);
|
||||
? selectionForWorkspaceScreen(closestEvenPageId, closestEvenPageId + 1)
|
||||
: selectionForWorkspaceScreen(mWorkspacePageId);
|
||||
task.loadWorkspaceForPreview(query);
|
||||
final SparseArray<Size> spanInfo = getLoadedLauncherWidgetInfo();
|
||||
MAIN_EXECUTOR.execute(() -> {
|
||||
renderView(previewContext, appComponent.getDataModel(), spanInfo, idp);
|
||||
renderView(previewContext, appComponent.getDataModel(), spanInfo, idp,
|
||||
onCompleteCallback);
|
||||
mLifeCycleTracker.add(previewContext::onDestroy);
|
||||
});
|
||||
} else {
|
||||
LauncherAppState.getInstance(inflationContext).getModel().loadAsync(dataModel -> {
|
||||
if (dataModel != null) {
|
||||
MAIN_EXECUTOR.execute(() -> renderView(inflationContext, dataModel,
|
||||
null, LauncherAppState.getIDP(inflationContext)));
|
||||
null, LauncherAppState.getIDP(inflationContext), onCompleteCallback));
|
||||
} else {
|
||||
onCompleteCallback.completeExceptionally(
|
||||
new RuntimeException("Model loading failed"));
|
||||
Log.e(TAG, "Model loading failed");
|
||||
}
|
||||
});
|
||||
@@ -433,17 +442,19 @@ public class PreviewSurfaceRenderer {
|
||||
|
||||
@UiThread
|
||||
private void renderView(Context inflationContext, BgDataModel dataModel,
|
||||
@Nullable final SparseArray<Size> launcherWidgetSpanInfo, InvariantDeviceProfile idp) {
|
||||
@Nullable final SparseArray<Size> launcherWidgetSpanInfo, InvariantDeviceProfile idp,
|
||||
CompletableFuture<View> onCompleteCallback) {
|
||||
if (mDestroyed) {
|
||||
onCompleteCallback.completeExceptionally(new RuntimeException("Renderer destroyed"));
|
||||
return;
|
||||
}
|
||||
LauncherPreviewRenderer renderer;
|
||||
if (Flags.newCustomizationPickerUi()) {
|
||||
renderer = new LauncherPreviewRenderer(inflationContext, idp,
|
||||
mPreviewColorOverride, mWallpaperColors, launcherWidgetSpanInfo);
|
||||
renderer = new LauncherPreviewRenderer(inflationContext, idp, mPreviewColorOverride,
|
||||
mWallpaperColors, mWorkspacePageId, launcherWidgetSpanInfo);
|
||||
} else {
|
||||
renderer = new LauncherPreviewRenderer(inflationContext, idp,
|
||||
mWallpaperColors, launcherWidgetSpanInfo);
|
||||
mWallpaperColors, mWorkspacePageId, launcherWidgetSpanInfo);
|
||||
}
|
||||
renderer.hideBottomRow(mHideQsb);
|
||||
renderer.populate(dataModel);
|
||||
@@ -472,6 +483,7 @@ public class PreviewSurfaceRenderer {
|
||||
view.getMeasuredWidth(),
|
||||
view.getMeasuredHeight()
|
||||
);
|
||||
onCompleteCallback.complete(view);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -497,6 +509,7 @@ public class PreviewSurfaceRenderer {
|
||||
mViewRoot.removeAllViews();
|
||||
mViewRoot.addView(view);
|
||||
}
|
||||
onCompleteCallback.complete(view);
|
||||
}
|
||||
|
||||
private static class MySurfaceControlViewHost extends SurfaceControlViewHost {
|
||||
|
||||
@@ -25,12 +25,14 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.ArrayMap;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -41,6 +43,7 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.dagger.ApplicationContext;
|
||||
import com.android.launcher3.dagger.LauncherAppComponent;
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -207,6 +210,11 @@ public class ApiWrapper {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Captures a snapshot of the host content as a bitmap */
|
||||
public Bitmap captureSnapshot(SurfaceControlViewHost host, int width, int height) {
|
||||
return BitmapRenderer.createHardwareBitmap(width, height, host.getView()::draw);
|
||||
}
|
||||
|
||||
private static class NoopDrawable extends ColorDrawable {
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
|
||||
Reference in New Issue
Block a user