2020-03-20 16:04:05 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2020 The Android Open Source Project
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package com.android.launcher3.graphics;
|
|
|
|
|
|
|
|
|
|
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
2020-06-24 12:48:11 -07:00
|
|
|
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-04-23 11:40:58 -07:00
|
|
|
import android.app.WallpaperColors;
|
2021-05-19 19:42:14 -07:00
|
|
|
import android.appwidget.AppWidgetProviderInfo;
|
2020-03-20 16:04:05 -07:00
|
|
|
import android.content.Context;
|
|
|
|
|
import android.hardware.display.DisplayManager;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.os.IBinder;
|
2021-05-19 19:42:14 -07:00
|
|
|
import android.util.Log;
|
2021-04-23 11:40:58 -07:00
|
|
|
import android.view.ContextThemeWrapper;
|
2020-03-20 16:04:05 -07:00
|
|
|
import android.view.Display;
|
|
|
|
|
import android.view.SurfaceControlViewHost;
|
2021-05-19 19:42:14 -07:00
|
|
|
import android.view.SurfaceControlViewHost.SurfacePackage;
|
2020-03-20 16:04:05 -07:00
|
|
|
import android.view.View;
|
2021-05-20 01:50:03 +08:00
|
|
|
import android.view.WindowManager.LayoutParams;
|
2020-05-12 14:43:44 -07:00
|
|
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
import androidx.annotation.UiThread;
|
|
|
|
|
import androidx.annotation.WorkerThread;
|
|
|
|
|
|
2021-06-23 12:18:08 +02:00
|
|
|
import com.android.launcher3.DeviceProfile;
|
2020-03-20 16:04:05 -07:00
|
|
|
import com.android.launcher3.InvariantDeviceProfile;
|
2021-05-19 19:42:14 -07:00
|
|
|
import com.android.launcher3.LauncherAppState;
|
|
|
|
|
import com.android.launcher3.LauncherSettings;
|
2021-05-20 01:50:03 +08:00
|
|
|
import com.android.launcher3.Utilities;
|
2021-06-23 12:18:08 +02:00
|
|
|
import com.android.launcher3.Workspace;
|
2021-05-19 19:42:14 -07:00
|
|
|
import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext;
|
|
|
|
|
import com.android.launcher3.model.BgDataModel;
|
2020-06-24 12:48:11 -07:00
|
|
|
import com.android.launcher3.model.GridSizeMigrationTaskV2;
|
2021-05-19 19:42:14 -07:00
|
|
|
import com.android.launcher3.model.LoaderTask;
|
|
|
|
|
import com.android.launcher3.model.ModelDelegate;
|
|
|
|
|
import com.android.launcher3.util.ComponentKey;
|
|
|
|
|
import com.android.launcher3.util.RunnableList;
|
2021-04-23 11:40:58 -07:00
|
|
|
import com.android.launcher3.util.Themes;
|
|
|
|
|
import com.android.launcher3.widget.LocalColorExtractor;
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Map;
|
2020-03-20 16:04:05 -07:00
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
|
|
/** Render preview using surface view. */
|
2021-04-23 11:40:58 -07:00
|
|
|
@SuppressWarnings("NewApi")
|
2021-05-19 19:42:14 -07:00
|
|
|
public class PreviewSurfaceRenderer {
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "PreviewSurfaceRenderer";
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2020-05-12 14:43:44 -07:00
|
|
|
private static final int FADE_IN_ANIMATION_DURATION = 200;
|
|
|
|
|
|
2020-03-20 16:04:05 -07:00
|
|
|
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";
|
2021-04-23 11:40:58 -07:00
|
|
|
private static final String KEY_COLORS = "wallpaper_colors";
|
2020-03-20 16:04:05 -07:00
|
|
|
|
|
|
|
|
private final Context mContext;
|
|
|
|
|
private final InvariantDeviceProfile mIdp;
|
|
|
|
|
private final IBinder mHostToken;
|
|
|
|
|
private final int mWidth;
|
|
|
|
|
private final int mHeight;
|
|
|
|
|
private final Display mDisplay;
|
2021-04-23 11:40:58 -07:00
|
|
|
private final WallpaperColors mWallpaperColors;
|
2021-05-19 19:42:14 -07:00
|
|
|
private final RunnableList mOnDestroyCallbacks = new RunnableList();
|
|
|
|
|
|
|
|
|
|
private final SurfaceControlViewHost mSurfaceControlViewHost;
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
private boolean mDestroyed = false;
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
public PreviewSurfaceRenderer(Context context, Bundle bundle) throws Exception {
|
2020-03-20 16:04:05 -07:00
|
|
|
mContext = context;
|
|
|
|
|
|
|
|
|
|
String gridName = bundle.getString("name");
|
|
|
|
|
bundle.remove("name");
|
|
|
|
|
if (gridName == null) {
|
|
|
|
|
gridName = InvariantDeviceProfile.getCurrentGridName(context);
|
|
|
|
|
}
|
2021-04-23 11:40:58 -07:00
|
|
|
mWallpaperColors = bundle.getParcelable(KEY_COLORS);
|
2020-03-20 16:04:05 -07:00
|
|
|
mIdp = new InvariantDeviceProfile(context, gridName);
|
|
|
|
|
|
|
|
|
|
mHostToken = bundle.getBinder(KEY_HOST_TOKEN);
|
|
|
|
|
mWidth = bundle.getInt(KEY_VIEW_WIDTH);
|
|
|
|
|
mHeight = bundle.getInt(KEY_VIEW_HEIGHT);
|
2021-05-19 19:42:14 -07:00
|
|
|
mDisplay = context.getSystemService(DisplayManager.class)
|
|
|
|
|
.getDisplay(bundle.getInt(KEY_DISPLAY_ID));
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
mSurfaceControlViewHost = MAIN_EXECUTOR
|
|
|
|
|
.submit(() -> new SurfaceControlViewHost(mContext, mDisplay, mHostToken))
|
|
|
|
|
.get(5, TimeUnit.SECONDS);
|
|
|
|
|
mOnDestroyCallbacks.add(mSurfaceControlViewHost::release);
|
2020-03-20 16:04:05 -07:00
|
|
|
}
|
|
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
public IBinder getHostToken() {
|
|
|
|
|
return mHostToken;
|
|
|
|
|
}
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
public SurfacePackage getSurfacePackage() {
|
|
|
|
|
return mSurfaceControlViewHost.getSurfacePackage();
|
|
|
|
|
}
|
2020-03-20 16:04:05 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
/**
|
|
|
|
|
* Destroys the preview and all associated data
|
|
|
|
|
*/
|
|
|
|
|
@UiThread
|
|
|
|
|
public void destroy() {
|
|
|
|
|
mDestroyed = true;
|
|
|
|
|
mOnDestroyCallbacks.executeAllAndDestroy();
|
|
|
|
|
}
|
2020-06-24 12:48:11 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
/**
|
|
|
|
|
* Generates the preview in background
|
|
|
|
|
*/
|
|
|
|
|
public void loadAsync() {
|
|
|
|
|
MODEL_EXECUTOR.execute(this::loadModelData);
|
2020-03-20 16:04:05 -07:00
|
|
|
}
|
|
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
@WorkerThread
|
|
|
|
|
private void loadModelData() {
|
|
|
|
|
final boolean migrated = doGridMigrationIfNecessary();
|
|
|
|
|
|
|
|
|
|
final Context inflationContext;
|
|
|
|
|
if (mWallpaperColors != null) {
|
|
|
|
|
// Create a themed context, without affecting the main application context
|
|
|
|
|
Context context = mContext.createDisplayContext(mDisplay);
|
2021-05-20 01:50:03 +08:00
|
|
|
if (Utilities.ATLEAST_R) {
|
|
|
|
|
context = context.createWindowContext(
|
|
|
|
|
LayoutParams.TYPE_APPLICATION_OVERLAY, null);
|
|
|
|
|
}
|
2021-05-19 19:42:14 -07:00
|
|
|
LocalColorExtractor.newInstance(mContext)
|
|
|
|
|
.applyColorsOverride(context, mWallpaperColors);
|
|
|
|
|
inflationContext = new ContextThemeWrapper(context,
|
|
|
|
|
Themes.getActivityThemeRes(context, mWallpaperColors.getColorHints()));
|
|
|
|
|
} else {
|
2021-08-27 14:21:42 -04:00
|
|
|
inflationContext = new ContextThemeWrapper(mContext,
|
|
|
|
|
Themes.getActivityThemeRes(mContext));
|
2021-05-19 19:42:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (migrated) {
|
|
|
|
|
PreviewContext previewContext = new PreviewContext(inflationContext, mIdp);
|
|
|
|
|
new LoaderTask(
|
|
|
|
|
LauncherAppState.getInstance(previewContext),
|
|
|
|
|
null,
|
|
|
|
|
new BgDataModel(),
|
|
|
|
|
new ModelDelegate(), null) {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
2021-07-22 01:37:41 +02:00
|
|
|
DeviceProfile deviceProfile = mIdp.getDeviceProfile(previewContext);
|
2021-08-13 21:48:35 +01:00
|
|
|
String query =
|
|
|
|
|
LauncherSettings.Favorites.SCREEN + " = " + Workspace.FIRST_SCREEN_ID
|
2021-06-23 12:18:08 +02:00
|
|
|
+ " or " + LauncherSettings.Favorites.CONTAINER + " = "
|
|
|
|
|
+ LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
2021-08-13 21:48:35 +01:00
|
|
|
if (deviceProfile.isTwoPanels) {
|
|
|
|
|
query += " or " + LauncherSettings.Favorites.SCREEN + " = "
|
2021-08-17 23:12:17 +02:00
|
|
|
+ Workspace.SECOND_SCREEN_ID;
|
2021-08-13 21:48:35 +01:00
|
|
|
}
|
2021-05-19 19:42:14 -07:00
|
|
|
loadWorkspace(new ArrayList<>(), LauncherSettings.Favorites.PREVIEW_CONTENT_URI,
|
2021-06-23 12:18:08 +02:00
|
|
|
query);
|
|
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
MAIN_EXECUTOR.execute(() -> {
|
|
|
|
|
renderView(previewContext, mBgDataModel, mWidgetProvidersMap);
|
|
|
|
|
mOnDestroyCallbacks.add(previewContext::onDestroy);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}.run();
|
|
|
|
|
} else {
|
2021-08-06 11:52:10 -07:00
|
|
|
LauncherAppState.getInstance(inflationContext).getModel().loadAsync(dataModel -> {
|
|
|
|
|
if (dataModel != null) {
|
|
|
|
|
MAIN_EXECUTOR.execute(() -> renderView(inflationContext, dataModel, null));
|
|
|
|
|
} else {
|
|
|
|
|
Log.e(TAG, "Model loading failed");
|
2021-05-19 19:42:14 -07:00
|
|
|
}
|
2021-08-06 11:52:10 -07:00
|
|
|
});
|
2020-03-20 16:04:05 -07:00
|
|
|
}
|
|
|
|
|
}
|
2020-06-24 12:48:11 -07:00
|
|
|
|
2021-05-19 19:42:14 -07:00
|
|
|
@WorkerThread
|
2020-06-24 12:48:11 -07:00
|
|
|
private boolean doGridMigrationIfNecessary() {
|
2021-07-28 14:35:47 -07:00
|
|
|
if (!GridSizeMigrationTaskV2.needsToMigrate(mContext, mIdp)) {
|
2020-06-24 12:48:11 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
2021-07-28 14:35:47 -07:00
|
|
|
return GridSizeMigrationTaskV2.migrateGridIfNeeded(mContext, mIdp);
|
2020-06-24 12:48:11 -07:00
|
|
|
}
|
2021-05-19 19:42:14 -07:00
|
|
|
|
|
|
|
|
@UiThread
|
|
|
|
|
private void renderView(Context inflationContext, BgDataModel dataModel,
|
|
|
|
|
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) {
|
|
|
|
|
if (mDestroyed) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-06-21 16:07:09 -04:00
|
|
|
View view = new LauncherPreviewRenderer(inflationContext, mIdp, mWallpaperColors)
|
2021-05-19 19:42:14 -07:00
|
|
|
.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());
|
|
|
|
|
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();
|
|
|
|
|
mSurfaceControlViewHost.setView(view, view.getMeasuredWidth(), view.getMeasuredHeight());
|
|
|
|
|
}
|
2020-03-20 16:04:05 -07:00
|
|
|
}
|