Removing support for lagacy shortcuts
> Addition/removal of shortcus is already removed. This just
cleans up the unused code path
Bug: 275875209
Test: Updated tests
Flag: N/A
Change-Id: I8ab7f57b693f996920e50e8beecafcffab5167e9
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index a8b7698..b059cbd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -337,7 +337,6 @@
if (getTag() instanceof WorkspaceItemInfo) {
WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
isBadged = !Process.myUserHandle().equals(info.user)
- || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
|| info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index ef63b3b..8ff0969 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -25,7 +25,6 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.NO_OFFSET;
@@ -283,7 +282,6 @@
if (mAllAppsPredictions != null
&& (info.itemType == ITEM_TYPE_APPLICATION
- || info.itemType == ITEM_TYPE_SHORTCUT
|| info.itemType == ITEM_TYPE_DEEP_SHORTCUT)) {
int count = mAllAppsPredictions.items.size();
for (int i = 0; i < count; i++) {
@@ -1162,7 +1160,6 @@
}
switch (info.itemType) {
case Favorites.ITEM_TYPE_APPLICATION:
- case Favorites.ITEM_TYPE_SHORTCUT:
case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case Favorites.ITEM_TYPE_APPWIDGET:
// Fall through and continue if it's an app, shortcut, or widget
diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
index 83341cb..b12d98b 100644
--- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
+++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
import static com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo;
import static com.google.common.truth.Truth.assertThat;
@@ -40,11 +41,9 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.ComponentWithLabel;
-import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
+import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.LauncherModelHelper;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -53,8 +52,6 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.List;
@@ -76,17 +73,9 @@
private LauncherModelHelper mModelHelper;
private UserHandle mUserHandle;
- @Mock
- private IconCache mIconCache;
-
@Before
public void setup() throws Exception {
mModelHelper = new LauncherModelHelper();
- MockitoAnnotations.initMocks(this);
- doAnswer(invocation -> {
- ComponentWithLabel componentWithLabel = invocation.getArgument(0);
- return componentWithLabel.getComponent().getShortClassName();
- }).when(mIconCache).getTitleNoCache(any());
mUserHandle = myUserHandle();
mApp1Provider1 = createAppWidgetProviderInfo(
@@ -114,16 +103,12 @@
.collect(Collectors.toList());
}).when(manager).getInstalledProvidersForPackage(any(), eq(myUserHandle()));
- // 2 widgets, app4/provider1 & app5/provider1, have already been added to the workspace.
- mModelHelper.initializeData("widgets_predication_update_task_data");
-
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atWorkspace(0, 1, 2).putWidget("app4", "provider1", 1, 1)
+ .atWorkspace(0, 1, 3).putWidget("app5", "provider1", 1, 1);
+ mModelHelper.setupDefaultLayoutProvider(builder);
MAIN_EXECUTOR.submit(() -> mModelHelper.getModel().addCallbacks(mCallback)).get();
- MODEL_EXECUTOR.post(() -> mModelHelper.getBgDataModel().widgetsModel.update(
- LauncherAppState.getInstance(mModelHelper.sandboxContext),
- /* packageUser= */ null));
-
- MODEL_EXECUTOR.submit(() -> { }).get();
- MAIN_EXECUTOR.submit(() -> { }).get();
+ mModelHelper.loadModelSync();
}
@After
@@ -132,65 +117,72 @@
}
@Test
- public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder()
- throws Exception {
- // WHEN newPredicationTask is executed with app predication of 5 apps.
- AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1",
- mUserHandle);
- AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "provider1",
- mUserHandle);
- AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className",
- mUserHandle);
- AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
- mUserHandle);
- AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
- mUserHandle);
- mModelHelper.executeTaskForTest(
- newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1)))
- .forEach(Runnable::run);
+ public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ // WHEN newPredicationTask is executed with app predication of 5 apps.
+ AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1",
+ mUserHandle);
+ AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "provider1",
+ mUserHandle);
+ AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className",
+ mUserHandle);
+ AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
+ mUserHandle);
+ AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
+ mUserHandle);
+ mCallback.mRecommendedWidgets = null;
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1)));
+ runOnExecutorSync(MAIN_EXECUTOR, () -> { });
- // THEN only 2 widgets are returned because
- // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
- // excluded from the result.
- // 2. app3 doesn't have a widget.
- // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
- List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
- .stream()
- .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
- .collect(Collectors.toList());
- assertThat(recommendedWidgets).hasSize(2);
- assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
- assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ // THEN only 2 widgets are returned because
+ // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
+ // excluded from the result.
+ // 2. app3 doesn't have a widget.
+ // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
+ List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
+ .stream()
+ .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
+ .collect(Collectors.toList());
+ assertThat(recommendedWidgets).hasSize(2);
+ assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
+ assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ });
}
@Test
- public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty()
- throws Exception {
+ public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty() {
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
- // Not installed widget
- AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider3",
- mUserHandle);
- // Not installed app
- AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1",
- mUserHandle);
- // Workspace added widgets
- AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
- mUserHandle);
- AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
- mUserHandle);
- mModelHelper.executeTaskForTest(
- newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1)))
- .forEach(Runnable::run);
+ // Not installed widget
+ AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider3",
+ mUserHandle);
+ // Not installed app
+ AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1",
+ mUserHandle);
+ // Workspace added widgets
+ AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
+ mUserHandle);
+ AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
+ mUserHandle);
- // THEN only 2 widgets are returned because the launcher only filters out non-exist widgets.
- List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
- .stream()
- .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
- .collect(Collectors.toList());
- assertThat(recommendedWidgets).hasSize(2);
- // Another widget from the same package
- assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
- assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ mCallback.mRecommendedWidgets = null;
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1)));
+ runOnExecutorSync(MAIN_EXECUTOR, () -> { });
+
+ // THEN only 2 widgets are returned because the launcher only filters out
+ // non-exist widgets.
+ List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
+ .stream()
+ .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
+ .collect(Collectors.toList());
+ assertThat(recommendedWidgets).hasSize(2);
+ // Another widget from the same package
+ assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
+ assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ });
}
private void assertWidgetInfo(
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 0b75c45..5af8e1e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1928,7 +1928,7 @@
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
addAppWidgetFromDrop((PendingAddWidgetInfo) info);
break;
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
processShortcutFromDrop((PendingAddShortcutInfo) info);
break;
default:
@@ -2435,7 +2435,6 @@
final View view;
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: {
WorkspaceItemInfo info = (WorkspaceItemInfo) item;
view = createShortcut(info);
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4d15ac7..cc1c0f5 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -104,6 +104,8 @@
});
mContext.getSystemService(LauncherApps.class).registerCallback(mModel);
+ mOnTerminateCallback.add(() ->
+ mContext.getSystemService(LauncherApps.class).unregisterCallback(mModel));
SimpleBroadcastReceiver modelChangeReceiver =
new SimpleBroadcastReceiver(mModel::onBroadcastIntent);
@@ -123,8 +125,9 @@
mOnTerminateCallback.add(userChangeListener::close);
LockedUserState.get(context).runOnUserUnlocked(() -> {
- CustomWidgetManager.INSTANCE.get(mContext)
- .setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
+ CustomWidgetManager cwm = CustomWidgetManager.INSTANCE.get(mContext);
+ cwm.setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
+ mOnTerminateCallback.add(() -> cwm.setWidgetRefreshCallback(null));
IconObserver observer = new IconObserver();
SafeCloseable iconChangeTracker = mIconProvider.registerIconChangeListener(
@@ -159,6 +162,7 @@
mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext),
iconCacheFileName != null);
mOnTerminateCallback.add(mIconCache::close);
+ mOnTerminateCallback.add(mModel::destroy);
}
private void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
@@ -180,9 +184,6 @@
*/
@Override
public void close() {
- mModel.destroy();
- mContext.getSystemService(LauncherApps.class).unregisterCallback(mModel);
- CustomWidgetManager.INSTANCE.get(mContext).setWidgetRefreshCallback(null);
mOnTerminateCallback.executeAllAndDestroy();
}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 7fda326..2397429 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -89,7 +89,9 @@
/**
* The gesture is an application created shortcut
+ * @deprecated This is no longer supported. Use {@link #ITEM_TYPE_DEEP_SHORTCUT} instead
*/
+ @Deprecated
public static final int ITEM_TYPE_SHORTCUT = 1;
/**
@@ -213,7 +215,6 @@
public static final String itemTypeToString(int type) {
switch(type) {
case ITEM_TYPE_APPLICATION: return "APP";
- case ITEM_TYPE_SHORTCUT: return "SHORTCUT";
case ITEM_TYPE_FOLDER: return "FOLDER";
case ITEM_TYPE_APPWIDGET: return "WIDGET";
case ITEM_TYPE_CUSTOM_APPWIDGET: return "CUSTOMWIDGET";
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 73bb828..dbf0894 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1840,7 +1840,6 @@
!= LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION);
boolean willBecomeShortcut =
(info.itemType == ITEM_TYPE_APPLICATION ||
- info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT);
return (aboveShortcut && willBecomeShortcut);
@@ -2759,7 +2758,7 @@
final PendingAddItemInfo pendingInfo = (PendingAddItemInfo) info;
boolean findNearestVacantCell = true;
- if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+ if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
mTargetCell = findNearestArea(touchXY[0], touchXY[1], spanX, spanY,
cellLayout, mTargetCell);
float distance = cellLayout.getDistanceFromWorkspaceCellVisualCenter(
@@ -2832,8 +2831,7 @@
View view;
switch (info.itemType) {
- case ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION:
if (info instanceof WorkspaceItemFactory) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 4ae54e6..f38cce1 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -881,7 +881,6 @@
final ItemInfo item = d.dragInfo;
final int itemType = item.itemType;
return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT));
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 2c1100f..be643b3 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -260,7 +260,6 @@
private boolean willAcceptItem(ItemInfo item) {
final int itemType = item.itemType;
return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) &&
item != mInfo && !mFolder.isOpen());
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 47677ea..7241b17 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -34,13 +34,9 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.ContextWrapper;
-import android.content.Intent;
import android.content.res.TypedArray;
-import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -78,8 +74,6 @@
import com.android.launcher3.celllayout.CellPosMapper;
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.LauncherIcons;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
@@ -183,7 +177,6 @@
private final DeviceProfile mDp;
private final DeviceProfile mDpOrig;
private final Rect mInsets;
- private final WorkspaceItemInfo mWorkspaceItemInfo;
private final LayoutInflater mHomeElementInflater;
private final InsettableFrameLayout mRootView;
private final Hotseat mHotseat;
@@ -221,19 +214,6 @@
mDp.isTaskbarPresent ? 0 : currentWindowInsets.getSystemWindowInsetBottom());
mDp.updateInsets(mInsets);
- BaseIconFactory iconFactory =
- new BaseIconFactory(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize) { };
- BitmapInfo iconInfo = iconFactory.createBadgedIconBitmap(
- new AdaptiveIconDrawable(
- new ColorDrawable(Color.WHITE),
- new ColorDrawable(Color.WHITE)));
-
- mWorkspaceItemInfo = new WorkspaceItemInfo();
- mWorkspaceItemInfo.bitmap = iconInfo;
- mWorkspaceItemInfo.intent = new Intent();
- mWorkspaceItemInfo.contentDescription = mWorkspaceItemInfo.title =
- context.getString(R.string.label_application);
-
mHomeElementInflater = LayoutInflater.from(
new ContextThemeWrapper(this, R.style.HomeScreenElementTheme));
mHomeElementInflater.setFactory2(this);
@@ -483,7 +463,6 @@
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;
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 27d1f78..5e86bd6 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -91,8 +91,7 @@
List<ItemInfo> filteredItems = new ArrayList<>();
for (Pair<ItemInfo, Object> entry : mItemList) {
ItemInfo item = entry.first;
- if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+ if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
// Short-circuit this logic if the icon exists somewhere on the workspace
if (shortcutExists(dataModel, item.getIntent(), item.user)) {
continue;
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 0861e9d..5b0da5b 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -210,7 +210,6 @@
// Fall through.
}
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
workspaceItems.remove(item);
break;
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
@@ -245,7 +244,6 @@
break;
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
workspaceItems.add(item);
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index 9a6cde6..9d16610 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -455,7 +455,6 @@
try {
// calculate weight
switch (entry.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
entry.mIntent = c.getString(indexIntent);
@@ -531,7 +530,6 @@
try {
// calculate weight
switch (entry.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
entry.mIntent = c.getString(indexIntent);
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index fa0511c..9a3abd4 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -286,7 +286,6 @@
final WorkspaceItemInfo si = new WorkspaceItemInfo();
si.user = user;
- si.itemType = ITEM_TYPE_APPLICATION;
LauncherActivityInfo lai;
boolean usePackageIcon = laiList.isEmpty();
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 2054d93..33332f0 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -193,9 +193,7 @@
public IconRequestInfo<WorkspaceItemInfo> createIconRequestInfo(
WorkspaceItemInfo wai, boolean useLowResIcon) {
- byte[] iconBlob = itemType == Favorites.ITEM_TYPE_SHORTCUT
- || itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
- || restoreFlag != 0
+ byte[] iconBlob = itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT || restoreFlag != 0
? getIconBlob() : null;
return new IconRequestInfo<>(wai, mActivityInfo, iconBlob, useLowResIcon);
@@ -347,7 +345,6 @@
}
final WorkspaceItemInfo info = new WorkspaceItemInfo();
- info.itemType = Favorites.ITEM_TYPE_APPLICATION;
info.user = user;
info.intent = newIntent;
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 1a8cf24..d2a8174 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -503,7 +503,6 @@
boolean allowMissingTarget = false;
switch (c.itemType) {
- case Favorites.ITEM_TYPE_SHORTCUT:
case Favorites.ITEM_TYPE_APPLICATION:
case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
Intent intent = c.parseIntent();
@@ -517,9 +516,8 @@
ComponentName cn = intent.getComponent();
String targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();
- if (TextUtils.isEmpty(targetPkg)
- && c.itemType != Favorites.ITEM_TYPE_SHORTCUT) {
- c.markDeleted("Only legacy shortcuts can have null package");
+ if (TextUtils.isEmpty(targetPkg)) {
+ c.markDeleted("Shortcuts can't have null package");
return;
}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index ddb8b05..f2afaeb 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -498,7 +498,6 @@
modelItem.container == Favorites.CONTAINER_HOTSEAT)) {
switch (modelItem.itemType) {
case Favorites.ITEM_TYPE_APPLICATION:
- case Favorites.ITEM_TYPE_SHORTCUT:
case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case Favorites.ITEM_TYPE_FOLDER:
if (!mBgDataModel.workspaceItems.contains(modelItem)) {
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index bfb80b3..1c68292 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -30,7 +30,6 @@
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_TASK;
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.CONTAINER_NOT_SET;
import static com.android.launcher3.shortcuts.ShortcutKey.EXTRA_SHORTCUT_ID;
@@ -87,7 +86,6 @@
/**
* One of {@link Favorites#ITEM_TYPE_APPLICATION},
- * {@link Favorites#ITEM_TYPE_SHORTCUT},
* {@link Favorites#ITEM_TYPE_DEEP_SHORTCUT}
* {@link Favorites#ITEM_TYPE_FOLDER},
* {@link Favorites#ITEM_TYPE_APP_PAIR},
@@ -361,13 +359,6 @@
})
.orElse(LauncherAtom.Shortcut.newBuilder()));
break;
- case ITEM_TYPE_SHORTCUT:
- itemBuilder
- .setShortcut(nullableComponent
- .map(component -> LauncherAtom.Shortcut.newBuilder()
- .setShortcutName(component.flattenToShortString()))
- .orElse(LauncherAtom.Shortcut.newBuilder()));
- break;
case ITEM_TYPE_APPWIDGET:
itemBuilder
.setWidget(nullableComponent
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 01606d4..3ce194d 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -96,7 +96,7 @@
public WorkspaceItemInfo() {
- itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
public WorkspaceItemInfo(WorkspaceItemInfo info) {
@@ -205,8 +205,8 @@
@Override
public ComponentName getTargetComponent() {
ComponentName cn = super.getTargetComponent();
- if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT || hasStatusFlag(
- FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON))) {
+ if (cn == null && hasStatusFlag(
+ FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON)) {
// Legacy shortcuts and promise icons with web UI may not have a componentName but just
// a packageName. In that case create a empty componentName instead of adding additional
// check everywhere.
diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
index b24ee34..06da8c5 100644
--- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
@@ -72,7 +72,7 @@
}
public int getItemType() {
- return LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ return LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
}
@Override
diff --git a/src/com/android/launcher3/util/IntArray.java b/src/com/android/launcher3/util/IntArray.java
index 1c78795..2498242 100644
--- a/src/com/android/launcher3/util/IntArray.java
+++ b/src/com/android/launcher3/util/IntArray.java
@@ -250,6 +250,11 @@
return b.toString();
}
+ @Override
+ public String toString() {
+ return "IntArray [" + toConcatString() + "]";
+ }
+
public static IntArray fromConcatString(String concatString) {
StringTokenizer tokenizer = new StringTokenizer(concatString, ",");
int[] array = new int[tokenizer.countTokens()];
diff --git a/src/com/android/launcher3/util/MainThreadInitializedObject.java b/src/com/android/launcher3/util/MainThreadInitializedObject.java
index 0899a22..1cb9994 100644
--- a/src/com/android/launcher3/util/MainThreadInitializedObject.java
+++ b/src/com/android/launcher3/util/MainThreadInitializedObject.java
@@ -48,8 +48,8 @@
}
public T get(Context context) {
- if (context instanceof SandboxContext) {
- return ((SandboxContext) context).getObject(this, mProvider);
+ if (context instanceof SandboxContext sc) {
+ return sc.getObject(this);
}
if (mValue == null) {
@@ -131,24 +131,22 @@
* Find a cached object from mObjectMap if we have already created one. If not, generate
* an object using the provider.
*/
- protected <T> T getObject(MainThreadInitializedObject<T> object,
- ObjectProvider<T> provider) {
+ protected <T> T getObject(MainThreadInitializedObject<T> object) {
synchronized (mDestroyLock) {
if (mDestroyed) {
Log.e(TAG, "Static object access with a destroyed context");
}
-
T t = (T) mObjectMap.get(object);
if (t != null) {
return t;
}
if (Looper.myLooper() == Looper.getMainLooper()) {
- t = createObject(provider);
+ t = createObject(object);
// Check if we've explicitly allowed the object or if it's a SafeCloseable,
// it will get destroyed in onDestroy()
if (!mAllowedObjects.contains(object) && !(t instanceof SafeCloseable)) {
- throw new IllegalStateException(
- "Leaking unknown objects " + object + " " + provider + " " + t);
+ throw new IllegalStateException("Leaking unknown objects "
+ + object + " " + object.mProvider + " " + t);
}
mObjectMap.put(object, t);
mOrderedObjects.add(t);
@@ -157,15 +155,15 @@
}
try {
- return MAIN_EXECUTOR.submit(() -> getObject(object, provider)).get();
+ return MAIN_EXECUTOR.submit(() -> getObject(object)).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@UiThread
- protected <T> T createObject(ObjectProvider<T> provider) {
- return provider.get(this);
+ protected <T> T createObject(MainThreadInitializedObject<T> object) {
+ return object.mProvider.get(this);
}
}
}
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index 515a2d8..3c8dfbb 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -332,6 +332,12 @@
return null;
}
+ boolean isShortcut = (item instanceof WorkspaceItemInfo)
+ && item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+ && !((WorkspaceItemInfo) item).isPromise();
+ if (isShortcut && GO_DISABLE_WIDGETS) {
+ return null;
+ }
ActivityOptionsWrapper options = v != null ? getActivityLaunchOptions(v, item)
: makeDefaultActivityOptions(item != null && item.animationType == DEFAULT_NO_ICON
? SPLASH_SCREEN_STYLE_SOLID_COLOR : -1 /* SPLASH_SCREEN_STYLE_UNDEFINED */);
@@ -343,13 +349,11 @@
intent.setSourceBounds(Utilities.getViewBounds(v));
}
try {
- boolean isShortcut = (item instanceof WorkspaceItemInfo)
- && (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
- || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
- && !((WorkspaceItemInfo) item).isPromise();
if (isShortcut) {
- // Shortcuts need some special checks due to legacy reasons.
- startShortcutIntentSafely(intent, optsBundle, item);
+ String id = ((WorkspaceItemInfo) item).getDeepShortcutId();
+ String packageName = intent.getPackage();
+ ((Context) this).getSystemService(LauncherApps.class).startShortcut(
+ packageName, id, intent.getSourceBounds(), optsBundle, user);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
context.startActivity(intent, optsBundle);
@@ -424,55 +428,6 @@
return new ActivityOptionsWrapper(options, new RunnableList());
}
- /**
- * Safely launches an intent for a shortcut.
- *
- * @param intent Intent to start.
- * @param optsBundle Optional launch arguments.
- * @param info Shortcut information.
- */
- default void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
- try {
- StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
- try {
- // Temporarily disable deathPenalty on all default checks. For eg, shortcuts
- // containing file Uri's would cause a crash as penaltyDeathOnFileUriExposure
- // is enabled by default on NYC.
- StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
- .penaltyLog().build());
-
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- String id = ((WorkspaceItemInfo) info).getDeepShortcutId();
- String packageName = intent.getPackage();
- startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user);
- } else {
- // Could be launching some bookkeeping activity
- ((Context) this).startActivity(intent, optsBundle);
- }
- } finally {
- StrictMode.setVmPolicy(oldPolicy);
- }
- } catch (SecurityException e) {
- throw e;
- }
- }
-
- /**
- * A wrapper around the platform method with Launcher specific checks.
- */
- default void startShortcut(String packageName, String id, Rect sourceBounds,
- Bundle startActivityOptions, UserHandle user) {
- if (GO_DISABLE_WIDGETS) {
- return;
- }
- try {
- ((Context) this).getSystemService(LauncherApps.class).startShortcut(packageName, id,
- sourceBounds, startActivityOptions, user);
- } catch (SecurityException | IllegalStateException e) {
- Log.e(TAG, "Failed to start shortcut", e);
- }
- }
-
default CellPosMapper getCellPosMapper() {
return CellPosMapper.DEFAULT;
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 4641e31..aebf752 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -290,7 +290,6 @@
static WorkspaceItemInfo placeholderInfo(Intent intent) {
WorkspaceItemInfo placeholderInfo = new WorkspaceItemInfo();
placeholderInfo.intent = intent;
- placeholderInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
placeholderInfo.container = LauncherSettings.Favorites.CONTAINER_SETTINGS;
return placeholderInfo;
}
diff --git a/tests/res/raw/cache_data_updated_task_data.txt b/tests/res/raw/cache_data_updated_task_data.txt
deleted file mode 100644
index 603dbe3..0000000
--- a/tests/res/raw/cache_data_updated_task_data.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-# Model data used by CacheDataUpdatedTaskTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Auto install app shortcut
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-
-# Custom shortcuts
-bgItem s itemType=1 title=app1-shrt intent=component=app1/class3 id=7
-bgItem s itemType=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Restored custom shortcut
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=9
-bgItem s itemType=1 status=1 title=app5-shrt intent=component=app5/class1 id=10
-
-allApps componentName=app1/class1 intent=component=app1/class1
-allApps componentName=app1/class2 intent=component=app1/class2
-allApps componentName=app2/class1 intent=component=app2/class1
-allApps componentName=app2/class2 intent=component=app2/class2
\ No newline at end of file
diff --git a/tests/res/raw/package_install_state_change_task_data.txt b/tests/res/raw/package_install_state_change_task_data.txt
deleted file mode 100644
index e82ea9d..0000000
--- a/tests/res/raw/package_install_state_change_task_data.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# Model data used by PackageInstallStateChangeTaskTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-classMap w com.android.launcher3.model.data.LauncherAppWidgetInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Promise icons for app3
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=7
-
-# Promise icon for app4
-bgItem s itemType=1 status=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Widget
-bgItem w providerName=app4/provider1 id=9
-bgItem w providerName=app5/provider1 id=10
\ No newline at end of file
diff --git a/tests/res/raw/widgets_predication_update_task_data.txt b/tests/res/raw/widgets_predication_update_task_data.txt
deleted file mode 100644
index 941d195..0000000
--- a/tests/res/raw/widgets_predication_update_task_data.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# Model data used by WidgetsPredictionUpdateTasksTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-classMap w com.android.launcher3.model.data.LauncherAppWidgetInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Promise icons for app3
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=7
-
-# Promise icon for app4
-bgItem s itemType=1 status=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Widget
-bgItem w providerName=app4/provider1 id=9
-bgItem w providerName=app5/provider1 id=10
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
index 03352fe..98191fe 100644
--- a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
+++ b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
@@ -17,17 +17,18 @@
import android.content.ComponentName
import android.content.Context
-import android.content.Intent
import android.graphics.Rect
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherAppState
-import com.android.launcher3.LauncherSettings
+import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.model.data.WorkspaceItemInfo
-import com.android.launcher3.util.ContentWriter
import com.android.launcher3.util.GridOccupancy
import com.android.launcher3.util.IntArray
import com.android.launcher3.util.IntSparseArrayMap
+import com.android.launcher3.util.LauncherLayoutBuilder
import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY
+import com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE
import java.util.UUID
/** Base class for workspace related tests. */
@@ -38,6 +39,7 @@
val nonEmptyScreenSpaces = listOf(Rect(1, 2, 3, 4))
}
+ protected lateinit var mLayoutBuilder: LauncherLayoutBuilder
protected lateinit var mTargetContext: Context
protected lateinit var mIdp: InvariantDeviceProfile
protected lateinit var mAppState: LauncherAppState
@@ -47,6 +49,7 @@
protected lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
open fun setup() {
+ mLayoutBuilder = LauncherLayoutBuilder()
mModelHelper = LauncherModelHelper()
mTargetContext = mModelHelper.sandboxContext
mIdp = InvariantDeviceProfile.INSTANCE[mTargetContext]
@@ -64,10 +67,11 @@
/** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
fun setupWorkspaces(screenIdsWithItems: List<Int>) {
- var nextItemId = 1
- screenIdsWithItems.forEach { screenId ->
- nextItemId = setupWorkspace(nextItemId, screenId, nonEmptyScreenSpaces)
- }
+ screenIdsWithItems.forEach { screenId -> setupWorkspace(screenId, nonEmptyScreenSpaces) }
+ mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
+ mIdp.numRows = 5
+ mIdp.numColumns = mIdp.numRows
+ mModelHelper.loadModelSync()
}
/**
@@ -78,30 +82,23 @@
screen1: List<Rect>? = null,
screen2: List<Rect>? = null,
screen3: List<Rect>? = null,
- ) = listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
+ ) {
+ listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
+ mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
+ mIdp.numRows = 5
+ mIdp.numColumns = mIdp.numRows
+ mModelHelper.loadModelSync()
+ }
private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
- var nextItemId = 1
workspaceSpaces.forEachIndexed { screenId, spaces ->
if (spaces != null) {
- nextItemId = setupWorkspace(nextItemId, screenId, spaces)
+ setupWorkspace(screenId, spaces)
}
}
}
- private fun setupWorkspace(startId: Int, screenId: Int, spaces: List<Rect>): Int {
- return mModelHelper.executeSimpleTask { dataModel ->
- writeWorkspaceWithSpaces(dataModel, startId, screenId, spaces)
- }
- }
-
- private fun writeWorkspaceWithSpaces(
- bgDataModel: BgDataModel,
- itemStartId: Int,
- screenId: Int,
- spaces: List<Rect>,
- ): Int {
- var itemId = itemStartId
+ private fun setupWorkspace(screenId: Int, spaces: List<Rect>) {
val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
spaces.forEach { spaceRect -> occupancy.markCells(spaceRect, false) }
@@ -109,35 +106,22 @@
mScreenOccupancy.append(screenId, occupancy)
for (x in 0 until mIdp.numColumns) {
for (y in 0 until mIdp.numRows) {
- if (!occupancy.cells[x][y]) {
- continue
+ if (occupancy.cells[x][y]) {
+ mLayoutBuilder.atWorkspace(x, y, screenId).putApp(TEST_PACKAGE, TEST_ACTIVITY)
}
- val info = getExistingItem()
- info.id = itemId++
- info.screenId = screenId
- info.cellX = x
- info.cellY = y
- info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP
- bgDataModel.addItem(mTargetContext, info, false)
- val writer = ContentWriter(mTargetContext)
- info.writeToValues(writer)
- writer.put(LauncherSettings.Favorites._ID, info.id)
- mTargetContext.contentResolver.insert(
- LauncherSettings.Favorites.CONTENT_URI,
- writer.getValues(mTargetContext)
- )
}
}
- return itemId
}
fun getExistingItem() =
- WorkspaceItemInfo().apply { intent = Intent().setComponent(ComponentName("a", "b")) }
+ WorkspaceItemInfo().apply {
+ intent = AppInfo.makeLaunchIntent(ComponentName(TEST_PACKAGE, TEST_ACTIVITY))
+ }
fun getNewItem(): WorkspaceItemInfo {
val itemPackage = UUID.randomUUID().toString()
return WorkspaceItemInfo().apply {
- intent = Intent().setComponent(ComponentName(itemPackage, itemPackage))
+ intent = AppInfo.makeLaunchIntent(ComponentName(itemPackage, itemPackage))
}
}
}
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
index 6636b8a..1155227 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
@@ -23,7 +23,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.util.Executors
import com.android.launcher3.util.IntArray
-import com.android.launcher3.util.IntSet
+import com.android.launcher3.util.TestUtil.runOnExecutorSync
import com.android.launcher3.util.any
import com.android.launcher3.util.eq
import com.android.launcher3.util.same
@@ -32,8 +32,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -46,11 +44,7 @@
@RunWith(AndroidJUnit4::class)
class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
- @Captor private lateinit var mAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
- @Captor private lateinit var mNotAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
- @Mock private lateinit var mDataModelCallbacks: BgDataModel.Callbacks
+ private lateinit var mDataModelCallbacks: MyCallbacks
@Mock private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
@@ -58,7 +52,7 @@
override fun setup() {
super.setup()
MockitoAnnotations.initMocks(this)
- whenever(mDataModelCallbacks.getPagesToBindSynchronously(any())).thenReturn(IntSet())
+ mDataModelCallbacks = MyCallbacks()
Executors.MAIN_EXECUTOR.submit { mModelHelper.model.addCallbacks(mDataModelCallbacks) }
.get()
}
@@ -105,7 +99,7 @@
val addedItems = testAddItems(nonEmptyScreenIds, itemToAdd)
assertThat(addedItems.size).isEqualTo(0)
- verifyZeroInteractions(mWorkspaceItemSpaceFinder, mDataModelCallbacks)
+ verifyZeroInteractions(mWorkspaceItemSpaceFinder)
}
@Test
@@ -191,22 +185,14 @@
): List<AddedItem> {
setupWorkspaces(nonEmptyScreenIds)
val task = newTask(*itemsToAdd)
- var updateCount = 0
- mModelHelper.executeTaskForTest(task).forEach {
- updateCount++
- it.run()
- }
val addedItems = mutableListOf<AddedItem>()
- if (updateCount > 0) {
- verify(mDataModelCallbacks)
- .bindAppsAdded(
- any(),
- mNotAnimatedItemArgumentCaptor.capture(),
- mAnimatedItemArgumentCaptor.capture()
- )
- addedItems.addAll(mAnimatedItemArgumentCaptor.value.map { AddedItem(it, true) })
- addedItems.addAll(mNotAnimatedItemArgumentCaptor.value.map { AddedItem(it, false) })
+
+ runOnExecutorSync(Executors.MODEL_EXECUTOR) {
+ mDataModelCallbacks.addedItems.clear()
+ mModelHelper.model.enqueueModelUpdateTask(task)
+ runOnExecutorSync(Executors.MAIN_EXECUTOR) {}
+ addedItems.addAll(mDataModelCallbacks.addedItems)
}
return addedItems
@@ -224,3 +210,17 @@
}
private data class AddedItem(val itemInfo: ItemInfo, val isAnimated: Boolean)
+
+private class MyCallbacks : BgDataModel.Callbacks {
+
+ val addedItems = mutableListOf<AddedItem>()
+
+ override fun bindAppsAdded(
+ newScreens: IntArray?,
+ addNotAnimated: ArrayList<ItemInfo>,
+ addAnimated: ArrayList<ItemInfo>
+ ) {
+ addedItems.addAll(addAnimated.map { AddedItem(it, true) })
+ addedItems.addAll(addNotAnimated.map { AddedItem(it, false) })
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index f55b244..f771052 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -1,32 +1,31 @@
package com.android.launcher3.model;
+import static android.os.Process.myUserHandle;
+
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Color;
-import android.os.Process;
-import android.os.UserHandle;
-import android.os.UserManager;
-import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.icons.cache.CachingLogic;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.LauncherModelHelper;
+import com.android.launcher3.util.PackageUserKey;
import org.junit.After;
import org.junit.Before;
@@ -35,6 +34,7 @@
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
/**
* Tests for {@link CacheDataUpdatedTask}
@@ -43,49 +43,40 @@
@RunWith(AndroidJUnit4.class)
public class CacheDataUpdatedTaskTest {
- private static final String NEW_LABEL_PREFIX = "new-label-";
+ private static final String PENDING_APP_1 = TEST_PACKAGE + ".pending1";
+ private static final String PENDING_APP_2 = TEST_PACKAGE + ".pending2";
private LauncherModelHelper mModelHelper;
+ private Context mContext;
+
+ private int mSession1;
@Before
public void setup() throws Exception {
mModelHelper = new LauncherModelHelper();
- mModelHelper.initializeData("cache_data_updated_task_data");
+ mContext = mModelHelper.sandboxContext;
+ mSession1 = mModelHelper.createInstallerSession(PENDING_APP_1);
+ mModelHelper.createInstallerSession(PENDING_APP_2);
- // Add placeholder entries in the cache to simulate update
- Context context = mModelHelper.sandboxContext;
- IconCache iconCache = LauncherAppState.getInstance(context).getIconCache();
- CachingLogic<ItemInfo> placeholderLogic = new CachingLogic<ItemInfo>() {
- @Override
- @NonNull
- public ComponentName getComponent(@NonNull ItemInfo info) {
- return info.getTargetComponent();
- }
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atHotseat(1).putFolder("MyFolder")
+ .addApp(TEST_PACKAGE, TEST_ACTIVITY) // 2
+ .addApp(TEST_PACKAGE, TEST_ACTIVITY2) // 3
+ .addApp(TEST_PACKAGE, TEST_ACTIVITY3) // 4
- @NonNull
- @Override
- public UserHandle getUser(@NonNull ItemInfo info) {
- return info.user;
- }
+ // Pending App 1
+ .addApp(PENDING_APP_1, TEST_ACTIVITY) // 5
+ .addApp(PENDING_APP_1, TEST_ACTIVITY2) // 6
+ .addApp(PENDING_APP_1, TEST_ACTIVITY3) // 7
- @NonNull
- @Override
- public CharSequence getLabel(@NonNull ItemInfo info) {
- return NEW_LABEL_PREFIX + info.id;
- }
-
- @NonNull
- @Override
- public BitmapInfo loadIcon(@NonNull Context context, @NonNull ItemInfo info) {
- return BitmapInfo.of(Bitmap.createBitmap(1, 1, Config.ARGB_8888), Color.RED);
- }
- };
-
- UserManager um = context.getSystemService(UserManager.class);
- for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
- iconCache.addIconToDBAndMemCache(info, placeholderLogic, new PackageInfo(),
- um.getSerialNumberForUser(info.user), true);
- }
+ // Pending App 2
+ .addApp(PENDING_APP_2, TEST_ACTIVITY) // 8
+ .addApp(PENDING_APP_2, TEST_ACTIVITY2) // 9
+ .addApp(PENDING_APP_2, TEST_ACTIVITY3) // 10
+ .build();
+ mModelHelper.setupDefaultLayoutProvider(builder);
+ mModelHelper.loadModelSync();
+ assertEquals(10, mModelHelper.getBgDataModel().itemsIdMap.size());
}
@After
@@ -94,27 +85,63 @@
}
private CacheDataUpdatedTask newTask(int op, String... pkg) {
- return new CacheDataUpdatedTask(op, Process.myUserHandle(),
+ return new CacheDataUpdatedTask(op, myUserHandle(),
new HashSet<>(Arrays.asList(pkg)));
}
@Test
- public void testCacheUpdate_update_apps() throws Exception {
- // Clear all icons from apps list so that its easy to check what was updated
- for (AppInfo info : mModelHelper.getAllAppsList().data) {
- info.bitmap = BitmapInfo.LOW_RES_INFO;
- }
+ public void testCacheUpdate_update_apps() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ // Clear all icons from apps list so that its easy to check what was updated
+ allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
- mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, "app1"));
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, TEST_PACKAGE));
- // Verify that only the app icons of app1 (id 1 & 2) are updated. Custom shortcut (id 7)
- // is not updated
- verifyUpdate(1, 2);
+ // Verify that only the app icons of TEST_PACKAGE (id 2, 3, 4) are updated.
+ verifyUpdate(2, 3, 4);
+ });
+ }
- // Verify that only app1 var updated in allAppsList
- assertFalse(mModelHelper.getAllAppsList().data.isEmpty());
- for (AppInfo info : mModelHelper.getAllAppsList().data) {
- if (info.componentName.getPackageName().equals("app1")) {
+ @Test
+ public void testSessionUpdate_ignores_normal_apps() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ // Clear all icons from apps list so that its easy to check what was updated
+ allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
+
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, TEST_PACKAGE));
+
+ // TEST_PACKAGE has no restored shortcuts. Verify that nothing was updated.
+ verifyUpdate();
+ });
+ }
+
+ @Test
+ public void testSessionUpdate_updates_pending_apps() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ LauncherAppState.getInstance(mContext).getIconCache().updateSessionCache(
+ new PackageUserKey(PENDING_APP_1, myUserHandle()),
+ mContext.getPackageManager().getPackageInstaller().getSessionInfo(mSession1));
+
+ // Clear all icons from apps list so that its easy to check what was updated
+ allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
+
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, PENDING_APP_1));
+
+ // Only restored apps from PENDING_APP_1 (id 5, 6, 7) are updated
+ verifyUpdate(5, 6, 7);
+ });
+ }
+
+ private void verifyUpdate(int... idsUpdated) {
+ IntSet updates = IntSet.wrap(idsUpdated);
+ for (WorkspaceItemInfo info : allItems()) {
+ if (updates.contains(info.id)) {
assertFalse(info.bitmap.isNullOrLowRes());
} else {
assertTrue(info.bitmap.isNullOrLowRes());
@@ -122,33 +149,7 @@
}
}
- @Test
- public void testSessionUpdate_ignores_normal_apps() throws Exception {
- mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app1"));
-
- // app1 has no restored shortcuts. Verify that nothing was updated.
- verifyUpdate();
- }
-
- @Test
- public void testSessionUpdate_updates_pending_apps() throws Exception {
- mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app3"));
-
- // app3 has only restored apps (id 5, 6) and shortcuts (id 9). Verify that only apps were
- // were updated
- verifyUpdate(5, 6);
- }
-
- private void verifyUpdate(Integer... idsUpdated) {
- HashSet<Integer> updates = new HashSet<>(Arrays.asList(idsUpdated));
- for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
- if (updates.contains(info.id)) {
- assertEquals(NEW_LABEL_PREFIX + info.id, info.title);
- assertFalse(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
- } else {
- assertNotSame(NEW_LABEL_PREFIX + info.id, info.title);
- assertTrue(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
- }
- }
+ private List<WorkspaceItemInfo> allItems() {
+ return ((FolderInfo) mModelHelper.getBgDataModel().itemsIdMap.get(1)).contents;
}
}
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 3b480ca..4fa5352 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -24,7 +24,6 @@
import android.os.Process
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
@@ -108,8 +107,8 @@
fun testMigration() {
// Src Hotseat icons
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
// Src grid icons
// _ _ _ _ _
@@ -124,7 +123,7 @@
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE)
// Dest hotseat icons
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
// Dest grid icons
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10)
@@ -219,8 +218,8 @@
// Hotseat items in grid A
// 1 2 _ 3 4
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
// Workspace items in grid A
// _ _ _ _ _
@@ -235,7 +234,7 @@
// Hotseat items in grid B
// 2 _ _ _
- addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
// Workspace items in grid B
// _ _ _ _
// _ _ _ 10
@@ -291,7 +290,7 @@
null
)
?: throw IllegalStateException()
- var locMap = parseLocMap(context, c)
+ var locMap = parseLocMap(c)
// Expected items in grid B
// _ _ _ _
// 5 6 7 8
@@ -348,7 +347,7 @@
null
)
?: throw IllegalStateException()
- locMap = parseLocMap(context, c)
+ locMap = parseLocMap(c)
// Expected workspace items in grid A
// _ _ _ _ _
// _ _ _ _ 5
@@ -410,7 +409,7 @@
null
)
?: throw IllegalStateException()
- locMap = parseLocMap(context, c)
+ locMap = parseLocMap(c)
// Expected workspace items in grid B
// _ _ _ _
// 5 6 _ 8
@@ -436,7 +435,7 @@
c.close()
}
- private fun parseLocMap(context: Context, c: Cursor): Map<String, Triple<Int, Int, Int>> {
+ private fun parseLocMap(c: Cursor): Map<String, Triple<Int, Int, Int>> {
// Check workspace items
val intentIndex = c.getColumnIndex(INTENT)
val screenIndex = c.getColumnIndex(SCREEN)
@@ -465,7 +464,16 @@
1,
TMP_TABLE
),
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE),
+ addItem(
+ ITEM_TYPE_DEEP_SHORTCUT,
+ 1,
+ CONTAINER_HOTSEAT,
+ 0,
+ 0,
+ testPackage2,
+ 2,
+ TMP_TABLE
+ ),
addItem(
ITEM_TYPE_APPLICATION,
2,
@@ -476,7 +484,16 @@
3,
TMP_TABLE
),
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ addItem(
+ ITEM_TYPE_DEEP_SHORTCUT,
+ 3,
+ CONTAINER_HOTSEAT,
+ 0,
+ 0,
+ testPackage4,
+ 4,
+ TMP_TABLE
+ )
)
val numSrcDatabaseHotseatIcons = srcHotseatItems.size
idp.numDatabaseHotseatIcons = 6
@@ -532,9 +549,9 @@
@Test
fun migrateFromLargerHotseat() {
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
idp.numDatabaseHotseatIcons = 4
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 78812c0..544ed6b 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -30,7 +30,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.INTENT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.OPTIONS;
import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID;
import static com.android.launcher3.LauncherSettings.Favorites.RANK;
@@ -158,13 +158,13 @@
@Test
public void loadSimpleShortcut() {
- initCursor(ITEM_TYPE_SHORTCUT, "my-shortcut");
+ initCursor(ITEM_TYPE_DEEP_SHORTCUT, "my-shortcut");
assertTrue(mLoaderCursor.moveToNext());
WorkspaceItemInfo info = mLoaderCursor.loadSimpleWorkspaceItem();
assertTrue(mApp.getIconCache().isDefaultIcon(info.bitmap, info.user));
assertEquals("my-shortcut", info.title);
- assertEquals(ITEM_TYPE_SHORTCUT, info.itemType);
+ assertEquals(ITEM_TYPE_DEEP_SHORTCUT, info.itemType);
}
@Test
diff --git a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
index 519191e..4ba61ac 100644
--- a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
@@ -1,5 +1,12 @@
package com.android.launcher3.model;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
+
import static org.junit.Assert.assertEquals;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -9,6 +16,8 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.PackageInstallInfo;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.LauncherModelHelper;
import org.junit.After;
@@ -16,9 +25,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Arrays;
-import java.util.HashSet;
-
/**
* Tests for {@link PackageInstallStateChangedTask}
*/
@@ -26,12 +32,36 @@
@RunWith(AndroidJUnit4.class)
public class PackageInstallStateChangedTaskTest {
+ private static final String PENDING_APP_1 = TEST_PACKAGE + ".pending1";
+ private static final String PENDING_APP_2 = TEST_PACKAGE + ".pending2";
+
private LauncherModelHelper mModelHelper;
+ private IntSet mDownloadingApps;
@Before
public void setup() throws Exception {
mModelHelper = new LauncherModelHelper();
- mModelHelper.initializeData("package_install_state_change_task_data");
+ mModelHelper.createInstallerSession(PENDING_APP_1);
+ mModelHelper.createInstallerSession(PENDING_APP_2);
+
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atWorkspace(0, 0, 1).putApp(TEST_PACKAGE, TEST_ACTIVITY) // 1
+ .atWorkspace(0, 0, 2).putApp(TEST_PACKAGE, TEST_ACTIVITY2) // 2
+ .atWorkspace(0, 0, 3).putApp(TEST_PACKAGE, TEST_ACTIVITY3) // 3
+
+ .atWorkspace(0, 0, 4).putApp(PENDING_APP_1, TEST_ACTIVITY) // 4
+ .atWorkspace(0, 0, 5).putApp(PENDING_APP_1, TEST_ACTIVITY2) // 5
+ .atWorkspace(0, 0, 6).putApp(PENDING_APP_1, TEST_ACTIVITY3) // 6
+ .atWorkspace(0, 0, 7).putWidget(PENDING_APP_1, "pending.widget", 1, 1) // 7
+
+ .atWorkspace(0, 0, 8).putApp(PENDING_APP_2, TEST_ACTIVITY) // 8
+ .atWorkspace(0, 0, 9).putApp(PENDING_APP_2, TEST_ACTIVITY2) // 9
+ .atWorkspace(0, 0, 10).putApp(PENDING_APP_2, TEST_ACTIVITY3); // 10
+
+ mDownloadingApps = IntSet.wrap(4, 5, 6, 7, 8, 9, 10);
+ mModelHelper.setupDefaultLayoutProvider(builder);
+ mModelHelper.loadModelSync();
+ assertEquals(10, mModelHelper.getBgDataModel().itemsIdMap.size());
}
@After
@@ -47,36 +77,45 @@
}
@Test
- public void testSessionUpdate_ignore_installed() throws Exception {
- mModelHelper.executeTaskForTest(newTask("app1", 30));
+ public void testSessionUpdate_ignore_installed() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ mModelHelper.getModel().enqueueModelUpdateTask(newTask(TEST_PACKAGE, 30));
- // No shortcuts were updated
- verifyProgressUpdate(0);
+ // No shortcuts were updated
+ verifyProgressUpdate(0);
+ });
}
@Test
- public void testSessionUpdate_shortcuts_updated() throws Exception {
- mModelHelper.executeTaskForTest(newTask("app3", 30));
+ public void testSessionUpdate_shortcuts_updated() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ mModelHelper.getModel().enqueueModelUpdateTask(newTask(PENDING_APP_1, 30));
- verifyProgressUpdate(30, 5, 6, 7);
+ verifyProgressUpdate(30, 4, 5, 6, 7);
+ });
}
@Test
- public void testSessionUpdate_widgets_updated() throws Exception {
- mModelHelper.executeTaskForTest(newTask("app4", 30));
+ public void testSessionUpdate_widgets_updated() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ mModelHelper.getModel().enqueueModelUpdateTask(newTask(PENDING_APP_2, 30));
- verifyProgressUpdate(30, 8, 9);
+ verifyProgressUpdate(30, 8, 9, 10);
+ });
}
- private void verifyProgressUpdate(int progress, Integer... idsUpdated) {
- HashSet<Integer> updates = new HashSet<>(Arrays.asList(idsUpdated));
+ private void verifyProgressUpdate(int progress, int... idsUpdated) {
+ IntSet updates = IntSet.wrap(idsUpdated);
for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
- if (info instanceof WorkspaceItemInfo) {
- assertEquals(updates.contains(info.id) ? progress: 100,
- ((WorkspaceItemInfo) info).getProgressLevel());
+ int expectedProgress = updates.contains(info.id) ? progress
+ : (mDownloadingApps.contains(info.id) ? 0 : 100);
+ if (info instanceof WorkspaceItemInfo wi) {
+ assertEquals(expectedProgress, wi.getProgressLevel());
} else {
- assertEquals(updates.contains(info.id) ? progress: -1,
- ((LauncherAppWidgetInfo) info).installProgress);
+ assertEquals(expectedProgress, ((LauncherAppWidgetInfo) info).installProgress);
}
}
}
diff --git a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
index 2f57634..8e4e998 100644
--- a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
+++ b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
@@ -87,9 +87,8 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- whenever(context.getObject(eq(WindowManagerProxy.INSTANCE), any()))
- .thenReturn(windowManagerProxy)
- whenever(context.getObject(eq(LauncherPrefs.INSTANCE), any())).thenReturn(launcherPrefs)
+ whenever(context.getObject(eq(WindowManagerProxy.INSTANCE))).thenReturn(windowManagerProxy)
+ whenever(context.getObject(eq(LauncherPrefs.INSTANCE))).thenReturn(launcherPrefs)
// Mock WindowManagerProxy
val displayInfo =
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 976afcd..9dc04a1 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -15,34 +15,31 @@
*/
package com.android.launcher3.util;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.launcher3.LauncherSettings.Favorites.CONTENT_URI;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
-import android.content.res.Resources;
-import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Color;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
-import android.os.Process;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.util.ArrayMap;
@@ -57,13 +54,10 @@
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.ItemInstallQueue;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.testing.TestInformationProvider;
@@ -72,37 +66,25 @@
import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.widget.custom.CustomWidgetManager;
-import org.mockito.ArgumentCaptor;
-
-import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
-import java.io.InputStreamReader;
+import java.io.IOException;
import java.io.OutputStreamWriter;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
-import java.util.function.Function;
/**
* Utility class to help manage Launcher Model and related objects for test.
*/
public class LauncherModelHelper {
- public static final int DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
- public static final int HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
-
- public static final int APP_ICON = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
- public static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
- public static final int NO__ICON = -1;
-
- public static final String TEST_PACKAGE = testContext().getPackageName();
+ public static final String TEST_PACKAGE = getInstrumentation().getContext().getPackageName();
public static final String TEST_ACTIVITY = "com.android.launcher3.tests.Activity2";
+ public static final String TEST_ACTIVITY2 = "com.android.launcher3.tests.Activity3";
+ public static final String TEST_ACTIVITY3 = "com.android.launcher3.tests.Activity4";
// Authority for providing a test default-workspace-layout data.
private static final String TEST_PROVIDER_AUTHORITY =
@@ -110,39 +92,18 @@
private static final int DEFAULT_BITMAP_SIZE = 10;
private static final int DEFAULT_GRID_SIZE = 4;
- private final HashMap<Class, HashMap<String, Field>> mFieldCache = new HashMap<>();
- private final MockContentResolver mMockResolver = new MockContentResolver();
- public final TestLauncherProvider provider;
public final SandboxModelContext sandboxContext;
- public final long defaultProfileId;
+ private final RunnableList mDestroyTask = new RunnableList();
private BgDataModel mDataModel;
- private AllAppsList mAllAppsList;
public LauncherModelHelper() {
- Context context = getApplicationContext();
- // System settings cache content provider. Ensure that they are statically initialized
- Settings.Secure.getString(context.getContentResolver(), "test");
- Settings.System.getString(context.getContentResolver(), "test");
- Settings.Global.getString(context.getContentResolver(), "test");
-
- provider = new TestLauncherProvider();
sandboxContext = new SandboxModelContext();
- defaultProfileId = UserCache.INSTANCE.get(sandboxContext)
- .getSerialNumberForUser(Process.myUserHandle());
- setupProvider(LauncherProvider.AUTHORITY, provider);
}
public void setupProvider(String authority, ContentProvider provider) {
- ProviderInfo providerInfo = new ProviderInfo();
- providerInfo.authority = authority;
- providerInfo.applicationInfo = sandboxContext.getApplicationInfo();
- provider.attachInfo(sandboxContext, providerInfo);
- mMockResolver.addProvider(providerInfo.authority, provider);
- doReturn(providerInfo)
- .when(sandboxContext.mPm)
- .resolveContentProvider(eq(authority), anyInt());
+ sandboxContext.setupProvider(authority, provider);
}
public LauncherModel getModel() {
@@ -151,16 +112,35 @@
public synchronized BgDataModel getBgDataModel() {
if (mDataModel == null) {
- mDataModel = ReflectionHelpers.getField(getModel(), "mBgDataModel");
+ getModel().enqueueModelUpdateTask(new ModelUpdateTask() {
+ @Override
+ public void init(@NonNull LauncherAppState app, @NonNull LauncherModel model,
+ @NonNull BgDataModel dataModel, @NonNull AllAppsList allAppsList,
+ @NonNull Executor uiExecutor) {
+ mDataModel = dataModel;
+ }
+
+ @Override
+ public void run() { }
+ });
}
return mDataModel;
}
- public synchronized AllAppsList getAllAppsList() {
- if (mAllAppsList == null) {
- mAllAppsList = ReflectionHelpers.getField(getModel(), "mBgAllAppsList");
- }
- return mAllAppsList;
+ /**
+ * Creates a installer session for the provided package.
+ */
+ public int createInstallerSession(String pkg) throws IOException {
+ SessionParams sp = new SessionParams(MODE_FULL_INSTALL);
+ sp.setAppPackageName(pkg);
+ Bitmap icon = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+ icon.eraseColor(Color.RED);
+ sp.setAppIcon(icon);
+ sp.setAppLabel(pkg);
+ PackageInstaller pi = sandboxContext.getPackageManager().getPackageInstaller();
+ int sessionId = pi.createSession(sp);
+ mDestroyTask.add(() -> pi.abandonSession(sessionId));
+ return sessionId;
}
public void destroy() {
@@ -175,6 +155,8 @@
waitOrThrow(l1);
sandboxContext.onDestroy();
l2.countDown();
+
+ mDestroyTask.executeAllAndDestroy();
}
private void waitOrThrow(CountDownLatch latch) {
@@ -186,184 +168,6 @@
}
/**
- * Synchronously executes the task and returns all the UI callbacks posted.
- */
- public List<Runnable> executeTaskForTest(ModelUpdateTask task) throws Exception {
- LauncherModel model = getModel();
- if (!model.isModelLoaded()) {
- ReflectionHelpers.setField(model, "mModelLoaded", true);
- }
- Executor mockExecutor = mock(Executor.class);
- model.enqueueModelUpdateTask(new ModelUpdateTask() {
- @Override
- public void init(@NonNull final LauncherAppState app,
- @NonNull final LauncherModel model, @NonNull final BgDataModel dataModel,
- @NonNull final AllAppsList allAppsList, @NonNull final Executor uiExecutor) {
- task.init(app, model, dataModel, allAppsList, mockExecutor);
- }
-
- @Override
- public void run() {
- task.run();
- }
- });
- MODEL_EXECUTOR.submit(() -> null).get();
-
- ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
- verify(mockExecutor, atLeast(0)).execute(captor.capture());
- return captor.getAllValues();
- }
-
- /**
- * Synchronously executes a task on the model
- */
- public <T> T executeSimpleTask(Function<BgDataModel, T> task) throws Exception {
- BgDataModel dataModel = getBgDataModel();
- return MODEL_EXECUTOR.submit(() -> task.apply(dataModel)).get();
- }
-
- /**
- * Initializes mock data for the test.
- */
- public void initializeData(String resourceName) throws Exception {
- BgDataModel bgDataModel = getBgDataModel();
- AllAppsList allAppsList = getAllAppsList();
-
- MODEL_EXECUTOR.submit(() -> {
- // Copy apk from resources to a local file and install from there.
- Resources resources = testContext().getResources();
- int resId = resources.getIdentifier(
- resourceName, "raw", testContext().getPackageName());
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(
- resources.openRawResource(resId)))) {
- String line;
- HashMap<String, Class> classMap = new HashMap<>();
- while ((line = reader.readLine()) != null) {
- line = line.trim();
- if (line.startsWith("#") || line.isEmpty()) {
- continue;
- }
- String[] commands = line.split(" ");
- switch (commands[0]) {
- case "classMap":
- classMap.put(commands[1], Class.forName(commands[2]));
- break;
- case "bgItem":
- bgDataModel.addItem(sandboxContext,
- (ItemInfo) initItem(classMap.get(commands[1]), commands, 2),
- false);
- break;
- case "allApps":
- allAppsList.add((AppInfo) initItem(AppInfo.class, commands, 1), null);
- break;
- }
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }).get();
- }
-
- private Object initItem(Class clazz, String[] fieldDef, int startIndex) throws Exception {
- HashMap<String, Field> cache = mFieldCache.get(clazz);
- if (cache == null) {
- cache = new HashMap<>();
- Class c = clazz;
- while (c != null) {
- for (Field f : c.getDeclaredFields()) {
- f.setAccessible(true);
- cache.put(f.getName(), f);
- }
- c = c.getSuperclass();
- }
- mFieldCache.put(clazz, cache);
- }
-
- Object item = clazz.newInstance();
- for (int i = startIndex; i < fieldDef.length; i++) {
- String[] fieldData = fieldDef[i].split("=", 2);
- Field f = cache.get(fieldData[0]);
- Class type = f.getType();
- if (type == int.class || type == long.class) {
- f.set(item, Integer.parseInt(fieldData[1]));
- } else if (type == CharSequence.class || type == String.class) {
- f.set(item, fieldData[1]);
- } else if (type == Intent.class) {
- if (!fieldData[1].startsWith("#Intent")) {
- fieldData[1] = "#Intent;" + fieldData[1] + ";end";
- }
- f.set(item, Intent.parseUri(fieldData[1], 0));
- } else if (type == ComponentName.class) {
- f.set(item, ComponentName.unflattenFromString(fieldData[1]));
- } else {
- throw new Exception("Added parsing logic for "
- + f.getName() + " of type " + f.getType());
- }
- }
- return item;
- }
-
- public int addItem(int type, int screen, int container, int x, int y) {
- return addItem(type, screen, container, x, y, defaultProfileId, TEST_PACKAGE);
- }
-
- public int addItem(int type, int screen, int container, int x, int y, long profileId) {
- return addItem(type, screen, container, x, y, profileId, TEST_PACKAGE);
- }
-
- public int addItem(int type, int screen, int container, int x, int y, String packageName) {
- return addItem(type, screen, container, x, y, defaultProfileId, packageName);
- }
-
- public int addItem(int type, int screen, int container, int x, int y, String packageName,
- int id, Uri contentUri) {
- addItem(type, screen, container, x, y, defaultProfileId, packageName, id, contentUri);
- return id;
- }
-
- /**
- * Adds a mock item in the DB.
- * @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
- * folder (where the type represents the number of items in the folder).
- */
- public int addItem(int type, int screen, int container, int x, int y, long profileId,
- String packageName) {
- int id = LauncherSettings.Settings.call(sandboxContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
- addItem(type, screen, container, x, y, profileId, packageName, id, CONTENT_URI);
- return id;
- }
-
- public void addItem(int type, int screen, int container, int x, int y, long profileId,
- String packageName, int id, Uri contentUri) {
- ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites._ID, id);
- values.put(LauncherSettings.Favorites.CONTAINER, container);
- values.put(LauncherSettings.Favorites.SCREEN, screen);
- values.put(LauncherSettings.Favorites.CELLX, x);
- values.put(LauncherSettings.Favorites.CELLY, y);
- values.put(LauncherSettings.Favorites.SPANX, 1);
- values.put(LauncherSettings.Favorites.SPANY, 1);
- values.put(LauncherSettings.Favorites.PROFILE_ID, profileId);
-
- if (type == APP_ICON || type == SHORTCUT) {
- values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
- values.put(LauncherSettings.Favorites.INTENT,
- new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
- } else {
- values.put(LauncherSettings.Favorites.ITEM_TYPE,
- LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
- // Add folder items.
- for (int i = 0; i < type; i++) {
- addItem(APP_ICON, 0, id, 0, 0, profileId);
- }
- }
-
- sandboxContext.getContentResolver().insert(contentUri, values);
- }
-
- /**
* Sets up a mock provider to load the provided layout by default, next time the layout loads
*/
public LauncherModelHelper setupDefaultLayoutProvider(LauncherLayoutBuilder builder)
@@ -394,6 +198,9 @@
}
};
setupProvider(TEST_PROVIDER_AUTHORITY, cp);
+ mDestroyTask.add(() -> runOnExecutorSync(MODEL_EXECUTOR, () ->
+ UiDevice.getInstance(getInstrumentation()).executeShellCommand(
+ "settings delete secure launcher3.layout.provider")));
return this;
}
@@ -402,46 +209,16 @@
*/
public void loadModelSync() throws ExecutionException, InterruptedException {
Callbacks mockCb = new Callbacks() { };
- Executors.MAIN_EXECUTOR.submit(() -> getModel().addCallbacksAndLoad(mockCb)).get();
+ MAIN_EXECUTOR.submit(() -> getModel().addCallbacksAndLoad(mockCb)).get();
Executors.MODEL_EXECUTOR.submit(() -> { }).get();
- Executors.MAIN_EXECUTOR.submit(() -> { }).get();
- Executors.MAIN_EXECUTOR.submit(() -> getModel().removeCallbacks(mockCb)).get();
+ MAIN_EXECUTOR.submit(() -> { }).get();
+ MAIN_EXECUTOR.submit(() -> getModel().removeCallbacks(mockCb)).get();
}
- /**
- * An extension of LauncherProvider backed up by in-memory database.
- */
- public static class TestLauncherProvider extends LauncherProvider {
+ public static class SandboxModelContext extends SandboxContext {
- @Override
- public boolean onCreate() {
- return true;
- }
-
- public SQLiteDatabase getDb() {
- return getModelDbController().getDb();
- }
- }
-
- public static boolean deleteContents(File dir) {
- File[] files = dir.listFiles();
- boolean success = true;
- if (files != null) {
- for (File file : files) {
- if (file.isDirectory()) {
- success &= deleteContents(file);
- }
- if (!file.delete()) {
- success = false;
- }
- }
- }
- return success;
- }
-
- public class SandboxModelContext extends SandboxContext {
-
+ private final MockContentResolver mMockResolver = new MockContentResolver();
private final ArrayMap<String, Object> mSpiedServices = new ArrayMap<>();
private final PackageManager mPm;
private final File mDbDir;
@@ -453,8 +230,31 @@
DisplayController.INSTANCE, CustomWidgetManager.INSTANCE,
SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE, LockedUserState.INSTANCE,
ItemInstallQueue.INSTANCE, WindowManagerProxy.INSTANCE);
+
+ // System settings cache content provider. Ensure that they are statically initialized
+ Settings.Secure.getString(
+ ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+ Settings.System.getString(
+ ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+ Settings.Global.getString(
+ ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+
mPm = spy(getBaseContext().getPackageManager());
mDbDir = new File(getCacheDir(), UUID.randomUUID().toString());
+ setupProvider(LauncherProvider.AUTHORITY, new LauncherProvider() {
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+ });
+ }
+
+ @Override
+ protected <T> T createObject(MainThreadInitializedObject<T> object) {
+ if (object == LauncherAppState.INSTANCE) {
+ return (T) new LauncherAppState(this, null /* iconCacheFileName */);
+ }
+ return super.createObject(object);
}
public SandboxModelContext allow(MainThreadInitializedObject object) {
@@ -505,9 +305,30 @@
mSpiedServices.put(name, result);
return result;
}
- }
- private static Context testContext() {
- return getInstrumentation().getContext();
+ public void setupProvider(String authority, ContentProvider provider) {
+ ProviderInfo providerInfo = new ProviderInfo();
+ providerInfo.authority = authority;
+ providerInfo.applicationInfo = getApplicationInfo();
+ provider.attachInfo(this, providerInfo);
+ mMockResolver.addProvider(providerInfo.authority, provider);
+ doReturn(providerInfo).when(mPm).resolveContentProvider(eq(authority), anyInt());
+ }
+
+ private static boolean deleteContents(File dir) {
+ File[] files = dir.listFiles();
+ boolean success = true;
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ success &= deleteContents(file);
+ }
+ if (!file.delete()) {
+ success = false;
+ }
+ }
+ }
+ return success;
+ }
}
}
diff --git a/tests/src/com/android/launcher3/util/TestUtil.java b/tests/src/com/android/launcher3/util/TestUtil.java
index 4981795..e2c1fde 100644
--- a/tests/src/com/android/launcher3/util/TestUtil.java
+++ b/tests/src/com/android/launcher3/util/TestUtil.java
@@ -53,6 +53,7 @@
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
@@ -154,6 +155,30 @@
Settings.Secure.putString(context.getContentResolver(), LAYOUT_DIGEST_KEY, null);
}
+ /**
+ * Utility method to run a task synchronously which converts any exceptions to RuntimeException
+ */
+ public static void runOnExecutorSync(ExecutorService executor, UncheckedRunnable task) {
+ try {
+ executor.submit(() -> {
+ try {
+ task.run();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Interface to indicate a runnable which can throw any exception. */
+ public interface UncheckedRunnable {
+ /** Method to run the task */
+ void run() throws Exception;
+ }
+
+
private static class PackageInstallCheck extends LauncherApps.Callback
implements AutoCloseable {