Merge "Render user's actual workspace in ThemePicker preview (Part 1)" into ub-launcher3-master
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index ae30380..1ae30b7 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -126,6 +126,10 @@
public static final TogglableFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = new TogglableFlag(
"ENABLE_DEEP_SHORTCUT_ICON_CACHE", true, "R/W deep shortcut in IconCache");
+ public static final TogglableFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = new TogglableFlag(
+ "ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", false,
+ "Show launcher preview in grid picker");
+
public static void initialize(Context context) {
// Avoid the disk read for user builds
if (Utilities.IS_DEBUG_DEVICE) {
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 2badb6e..0c5535f 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -19,6 +19,10 @@
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.model.ModelUtils.filterCurrentWorkspaceItems;
+import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;
+
import android.annotation.TargetApi;
import android.app.Fragment;
import android.content.Context;
@@ -48,6 +52,10 @@
import com.android.launcher3.Hotseat;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppState;
+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;
@@ -58,11 +66,20 @@
import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.BitmapRenderer;
+import com.android.launcher3.model.AllAppsList;
+import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.LoaderResults;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
+import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Utility class for generating the preview of Launcher for a given InvariantDeviceProfile.
@@ -241,22 +258,59 @@
}
private void renderScreenShot(Canvas canvas) {
- // Add hotseat icons
- for (int i = 0; i < mIdp.numHotseatIcons; i++) {
- WorkspaceItemInfo info = new WorkspaceItemInfo(mWorkspaceItemInfo);
- info.container = Favorites.CONTAINER_HOTSEAT;
- info.screenId = i;
- inflateAndAddIcon(info);
- }
+ if (ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER.get()) {
+ final LauncherModel launcherModel = LauncherAppState.getInstance(
+ mContext).getModel();
+ final WorkspaceItemsInfoFetcher fetcher = new WorkspaceItemsInfoFetcher();
+ launcherModel.enqueueModelUpdateTask(fetcher);
+ ArrayList<ItemInfo> workspaceItems;
+ try {
+ workspaceItems = fetcher.mTask.get(5, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ Log.d(TAG, "Error fetching workspace items info", e);
+ return;
+ }
- // Add workspace icons
- for (int i = 0; i < mIdp.numColumns; i++) {
- WorkspaceItemInfo info = new WorkspaceItemInfo(mWorkspaceItemInfo);
- info.container = Favorites.CONTAINER_DESKTOP;
- info.screenId = 0;
- info.cellX = i;
- info.cellY = mIdp.numRows - 1;
- inflateAndAddIcon(info);
+ // Separate the items that are on the current screen, and all the other remaining
+ // items
+ ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
+ ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>();
+
+ filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceItems,
+ currentWorkspaceItems, otherWorkspaceItems);
+ sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems);
+
+ for (ItemInfo itemInfo : currentWorkspaceItems) {
+ switch (itemInfo.itemType) {
+ case Favorites.ITEM_TYPE_APPLICATION:
+ case Favorites.ITEM_TYPE_SHORTCUT:
+ case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ inflateAndAddIcon((WorkspaceItemInfo) itemInfo);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+ // TODO: for folder implementation here.
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ // Add hotseat icons
+ for (int i = 0; i < mIdp.numHotseatIcons; i++) {
+ WorkspaceItemInfo info = new WorkspaceItemInfo(mWorkspaceItemInfo);
+ info.container = Favorites.CONTAINER_HOTSEAT;
+ info.screenId = i;
+ inflateAndAddIcon(info);
+ }
+ // Add workspace icons
+ for (int i = 0; i < mIdp.numColumns; i++) {
+ WorkspaceItemInfo info = new WorkspaceItemInfo(mWorkspaceItemInfo);
+ info.container = Favorites.CONTAINER_DESKTOP;
+ info.screenId = 0;
+ info.cellX = i;
+ info.cellY = mIdp.numRows - 1;
+ inflateAndAddIcon(info);
+ }
}
// Add first page QSB
@@ -286,6 +340,42 @@
}
}
+ private static class WorkspaceItemsInfoFetcher implements Callable<ArrayList<ItemInfo>>,
+ LauncherModel.ModelUpdateTask {
+
+ private final FutureTask<ArrayList<ItemInfo>> mTask = new FutureTask<>(this);
+
+ private LauncherAppState mApp;
+ private LauncherModel mModel;
+ private BgDataModel mBgDataModel;
+ private AllAppsList mAllAppsList;
+
+ @Override
+ public void init(LauncherAppState app, LauncherModel model, BgDataModel dataModel,
+ AllAppsList allAppsList, Executor uiExecutor) {
+ mApp = app;
+ mModel = model;
+ mBgDataModel = dataModel;
+ mAllAppsList = allAppsList;
+ }
+
+ @Override
+ public void run() {
+ mTask.run();
+ }
+
+ @Override
+ public ArrayList<ItemInfo> call() throws Exception {
+ if (!mModel.isModelLoaded()) {
+ Log.d(TAG, "Workspace not loaded, loading now");
+ mModel.startLoaderForResults(
+ new LoaderResults(mApp, mBgDataModel, mAllAppsList, 0, null));
+ return new ArrayList<>();
+ }
+ return mBgDataModel.workspaceItems;
+ }
+ }
+
private static void measureView(View view, int width, int height) {
view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
view.layout(0, 0, width, height);
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index a00a6bd..76c2951 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -16,6 +16,8 @@
package com.android.launcher3.model;
+import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
+import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.os.Looper;
@@ -27,20 +29,15 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel.CallbackTask;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.PagedView;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.ViewOnDrawExecutor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
import java.util.concurrent.Executor;
/**
@@ -123,8 +120,9 @@
otherWorkspaceItems);
filterCurrentWorkspaceItems(currentScreenId, appWidgets, currentAppWidgets,
otherAppWidgets);
- sortWorkspaceItemsSpatially(currentWorkspaceItems);
- sortWorkspaceItemsSpatially(otherWorkspaceItems);
+ final InvariantDeviceProfile idp = mApp.getInvariantDeviceProfile();
+ sortWorkspaceItemsSpatially(idp, currentWorkspaceItems);
+ sortWorkspaceItemsSpatially(idp, otherWorkspaceItems);
// Tell the workspace that we're about to start binding items
executeCallbacksTask(c -> {
@@ -169,89 +167,6 @@
}
}
-
- /** Filters the set of items who are directly or indirectly (via another container) on the
- * specified screen. */
- public static <T extends ItemInfo> void filterCurrentWorkspaceItems(int currentScreenId,
- ArrayList<T> allWorkspaceItems,
- ArrayList<T> currentScreenItems,
- ArrayList<T> otherScreenItems) {
- // Purge any null ItemInfos
- Iterator<T> iter = allWorkspaceItems.iterator();
- while (iter.hasNext()) {
- ItemInfo i = iter.next();
- if (i == null) {
- iter.remove();
- }
- }
-
- // Order the set of items by their containers first, this allows use to walk through the
- // list sequentially, build up a list of containers that are in the specified screen,
- // as well as all items in those containers.
- IntSet itemsOnScreen = new IntSet();
- Collections.sort(allWorkspaceItems,
- (lhs, rhs) -> Integer.compare(lhs.container, rhs.container));
-
- for (T info : allWorkspaceItems) {
- if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (info.screenId == currentScreenId) {
- currentScreenItems.add(info);
- itemsOnScreen.add(info.id);
- } else {
- otherScreenItems.add(info);
- }
- } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- currentScreenItems.add(info);
- itemsOnScreen.add(info.id);
- } else {
- if (itemsOnScreen.contains(info.container)) {
- currentScreenItems.add(info);
- itemsOnScreen.add(info.id);
- } else {
- otherScreenItems.add(info);
- }
- }
- }
- }
-
- /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to
- * right) */
- protected void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
- final InvariantDeviceProfile profile = mApp.getInvariantDeviceProfile();
- final int screenCols = profile.numColumns;
- final int screenCellCount = profile.numColumns * profile.numRows;
- Collections.sort(workspaceItems, new Comparator<ItemInfo>() {
- @Override
- public int compare(ItemInfo lhs, ItemInfo rhs) {
- if (lhs.container == rhs.container) {
- // Within containers, order by their spatial position in that container
- switch (lhs.container) {
- case LauncherSettings.Favorites.CONTAINER_DESKTOP: {
- int lr = (lhs.screenId * screenCellCount +
- lhs.cellY * screenCols + lhs.cellX);
- int rr = (rhs.screenId * screenCellCount +
- rhs.cellY * screenCols + rhs.cellX);
- return Integer.compare(lr, rr);
- }
- case LauncherSettings.Favorites.CONTAINER_HOTSEAT: {
- // We currently use the screen id as the rank
- return Integer.compare(lhs.screenId, rhs.screenId);
- }
- default:
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
- throw new RuntimeException("Unexpected container type when " +
- "sorting workspace items.");
- }
- return 0;
- }
- } else {
- // Between containers, order by hotseat, desktop
- return Integer.compare(lhs.container, rhs.container);
- }
- }
- });
- }
-
protected void bindWorkspaceItems(final ArrayList<ItemInfo> workspaceItems,
final Executor executor) {
// Bind the workspace items
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 2754cfc..cc994df 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -19,7 +19,7 @@
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
-import static com.android.launcher3.model.LoaderResults.filterCurrentWorkspaceItems;
+import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.isSystemApp;
diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java
new file mode 100644
index 0000000..628dd95
--- /dev/null
+++ b/src/com/android/launcher3/model/ModelUtils.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 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.model;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.IntSet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * Utils class for {@link com.android.launcher3.LauncherModel}.
+ */
+public class ModelUtils {
+
+ /**
+ * Filters the set of items who are directly or indirectly (via another container) on the
+ * specified screen.
+ */
+ public static <T extends ItemInfo> void filterCurrentWorkspaceItems(int currentScreenId,
+ ArrayList<T> allWorkspaceItems,
+ ArrayList<T> currentScreenItems,
+ ArrayList<T> otherScreenItems) {
+ // Purge any null ItemInfos
+ Iterator<T> iter = allWorkspaceItems.iterator();
+ while (iter.hasNext()) {
+ ItemInfo i = iter.next();
+ if (i == null) {
+ iter.remove();
+ }
+ }
+ // Order the set of items by their containers first, this allows use to walk through the
+ // list sequentially, build up a list of containers that are in the specified screen,
+ // as well as all items in those containers.
+ IntSet itemsOnScreen = new IntSet();
+ Collections.sort(allWorkspaceItems,
+ (lhs, rhs) -> Integer.compare(lhs.container, rhs.container));
+ for (T info : allWorkspaceItems) {
+ if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ if (info.screenId == currentScreenId) {
+ currentScreenItems.add(info);
+ itemsOnScreen.add(info.id);
+ } else {
+ otherScreenItems.add(info);
+ }
+ } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ currentScreenItems.add(info);
+ itemsOnScreen.add(info.id);
+ } else {
+ if (itemsOnScreen.contains(info.container)) {
+ currentScreenItems.add(info);
+ itemsOnScreen.add(info.id);
+ } else {
+ otherScreenItems.add(info);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right)
+ */
+ public static void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile,
+ ArrayList<ItemInfo> workspaceItems) {
+ final int screenCols = profile.numColumns;
+ final int screenCellCount = profile.numColumns * profile.numRows;
+ Collections.sort(workspaceItems, (lhs, rhs) -> {
+ if (lhs.container == rhs.container) {
+ // Within containers, order by their spatial position in that container
+ switch (lhs.container) {
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP: {
+ int lr = (lhs.screenId * screenCellCount + lhs.cellY * screenCols
+ + lhs.cellX);
+ int rr = (rhs.screenId * screenCellCount + +rhs.cellY * screenCols
+ + rhs.cellX);
+ return Integer.compare(lr, rr);
+ }
+ case LauncherSettings.Favorites.CONTAINER_HOTSEAT: {
+ // We currently use the screen id as the rank
+ return Integer.compare(lhs.screenId, rhs.screenId);
+ }
+ default:
+ if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ throw new RuntimeException(
+ "Unexpected container type when sorting workspace items.");
+ }
+ return 0;
+ }
+ } else {
+ // Between containers, order by hotseat, desktop
+ return Integer.compare(lhs.container, rhs.container);
+ }
+ });
+ }
+}