From ee9740462ef72f0dc3cdbcc2ed873a26608fef20 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 25 May 2023 19:20:10 -0700 Subject: [PATCH] Simplifying some test utility methods Bug: 283821111 Test: Presubmit Flag: N/A Change-Id: I7b9690bc0cc53d097d26cd4f0ab2dd36ba88e1cb --- .../taskbar/TaskbarStashController.java | 5 +- .../quickstep/ViewInflationDuringSwipeUp.java | 2 +- .../launcher3/model/DeviceGridState.java | 4 + .../model/GridSizeMigrationUtil.java | 7 +- .../android/launcher3/model/LoaderTask.java | 13 +--- .../launcher3/model/ModelDbController.java | 18 ++++- .../celllayout/FavoriteItemsTransaction.java | 76 ++++++++++++------- .../launcher3/celllayout/ReorderWidgets.java | 4 +- .../celllayout/TestWorkspaceBuilder.java | 53 +++++++------ .../launcher3/ui/AbstractLauncherUiTest.java | 23 +----- .../android/launcher3/ui/TestViewHelpers.java | 33 ++++---- .../ui/widget/AddConfigWidgetTest.java | 2 +- .../launcher3/ui/widget/AddWidgetTest.java | 2 +- .../launcher3/ui/widget/BindWidgetTest.java | 11 +-- .../com/android/launcher3/util/TestUtil.java | 51 ++++++++++--- .../tapl/LauncherInstrumentation.java | 27 ------- .../launcher3/tapl/OverviewTaskMenuItem.java | 30 -------- .../com/android/launcher3/tapl/Workspace.java | 3 - 18 files changed, 171 insertions(+), 193 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index eb4c136ab2..85d10b4572 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -819,8 +819,11 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba .setDuration(isStashed ? duration / 2 : duration)); } - private static void play(AnimatorSet as, Animator a, long startDelay, long duration, + private static void play(AnimatorSet as, @Nullable Animator a, long startDelay, long duration, Interpolator interpolator) { + if (a == null) { + return; + } a.setDuration(duration); a.setStartDelay(startDelay); a.setInterpolator(interpolator); diff --git a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java index 7e408a8587..acb2db5925 100644 --- a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java +++ b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java @@ -187,7 +187,7 @@ public class ViewInflationDuringSwipeUp extends AbstractQuickStepTest { LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB); LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG); - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false); + LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(false); // Make sure the widget is big enough to show a list of items info.minSpanX = 2; info.minSpanY = 2; diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java index edc8c1bcd9..f24d1d2fff 100644 --- a/src/com/android/launcher3/model/DeviceGridState.java +++ b/src/com/android/launcher3/model/DeviceGridState.java @@ -33,6 +33,7 @@ import android.text.TextUtils; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.logging.StatsLogManager.LauncherEvent; +import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext; import java.util.Locale; import java.util.Objects; @@ -92,6 +93,9 @@ public class DeviceGridState implements Comparable { * Stores the device state to shared preferences */ public void writeToPrefs(Context context) { + if (context instanceof SandboxContext) { + return; + } LauncherPrefs.get(context).put( WORKSPACE_SIZE.to(mGridSizeString), HOTSEAT_COUNT.to(mNumHotseat), diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java index 9d16610410..c233872cc5 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java +++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java @@ -45,7 +45,6 @@ import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.IntArray; -import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.WidgetManagerHelper; @@ -133,10 +132,8 @@ public class GridSizeMigrationUtil { Log.v(TAG, "Workspace migration completed in " + (System.currentTimeMillis() - migrationStartTime)); - if (!(context instanceof SandboxContext)) { - // Save current configuration, so that the migration does not run again. - destDeviceState.writeToPrefs(context); - } + // Save current configuration, so that the migration does not run again. + destDeviceState.writeToPrefs(context); } } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 91fd65d056..0767426dcb 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -367,18 +367,9 @@ public class LoaderTask implements Runnable { final boolean isSdCardReady = Utilities.isBootCompleted(); final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context); - boolean clearDb = false; - if (!mApp.getModel().getModelDbController().migrateGridIfNeeded()) { - // Migration failed. Clear workspace. - clearDb = true; - } - - if (clearDb) { - Log.d(TAG, "loadWorkspace: resetting launcher database"); - Settings.call(contentResolver, Settings.METHOD_CREATE_EMPTY_DB); - } - + mApp.getModel().getModelDbController().tryMigrateDB(); Log.d(TAG, "loadWorkspace: loading default favorites"); + mApp.getModel().getModelDbController().loadDefaultFavoritesIfNecessary(); Settings.call(contentResolver, Settings.METHOD_LOAD_DEFAULT_FAVORITES); synchronized (mBgDataModel) { diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java index f0e5ef6bbd..d5cc82b3f9 100644 --- a/src/com/android/launcher3/model/ModelDbController.java +++ b/src/com/android/launcher3/model/ModelDbController.java @@ -280,13 +280,29 @@ public class ModelDbController { mOpenHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE); } + + /** + * Migrates the DB if needed. If the migration failed, it clears the DB. + */ + public void tryMigrateDB() { + if (!migrateGridIfNeeded()) { + Log.d(TAG, "Migration failed: resetting launcher database"); + createEmptyDB(); + LauncherPrefs.get(mContext).putSync( + getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()).to(true)); + + // Write the grid state to avoid another migration + new DeviceGridState(LauncherAppState.getIDP(mContext)).writeToPrefs(mContext); + } + } + /** * Migrates the DB if needed, and returns false if the migration failed * and DB needs to be cleared. * @return true if migration was success or ignored, false if migration failed * and the DB should be reset. */ - public boolean migrateGridIfNeeded() { + private boolean migrateGridIfNeeded() { createDbIfNotExists(); InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext); if (!GridSizeMigrationUtil.needsToMigrate(mContext, idp)) { diff --git a/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java b/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java index 8ce932d281..80cc5aa90c 100644 --- a/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java +++ b/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java @@ -15,62 +15,80 @@ */ package com.android.launcher3.celllayout; +import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; 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 android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; +import com.android.launcher3.model.BgDataModel.Callbacks; +import com.android.launcher3.model.ModelDbController; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.util.ContentWriter; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ExecutionException; +import java.util.function.Supplier; public class FavoriteItemsTransaction { - private ArrayList mItemsToSubmit; + private ArrayList> mItemsToSubmit; private Context mContext; - private ContentResolver mResolver; - public AbstractLauncherUiTest mTest; - public FavoriteItemsTransaction(Context context, AbstractLauncherUiTest test) { + public FavoriteItemsTransaction(Context context) { mItemsToSubmit = new ArrayList<>(); mContext = context; - mResolver = mContext.getContentResolver(); - mTest = test; } - public FavoriteItemsTransaction addItem(ItemInfo itemInfo) { + public FavoriteItemsTransaction addItem(Supplier itemInfo) { this.mItemsToSubmit.add(itemInfo); return this; } - public FavoriteItemsTransaction removeLast() { - this.mItemsToSubmit.remove(this.mItemsToSubmit.size() - 1); - return this; - } - /** * Commits all the ItemInfo into the database of Favorites **/ - public void commit() throws ExecutionException, InterruptedException { - List values = new ArrayList<>(); - for (ItemInfo item : this.mItemsToSubmit) { - ContentWriter writer = new ContentWriter(mContext); - item.onAddToDatabase(writer); - writer.put(LauncherSettings.Favorites._ID, item.id); - values.add(writer.getValues(mContext)); - } - // Submit the icons to the database in the model thread to prevent race conditions - MODEL_EXECUTOR.submit(() -> mResolver.bulkInsert(LauncherSettings.Favorites.CONTENT_URI, - values.toArray(new ContentValues[0]))).get(); - // Reload the state of the Launcher - MAIN_EXECUTOR.submit(() -> LauncherAppState.getInstance( - mContext).getModel().forceReload()).get(); + public void commit() { + LauncherModel model = LauncherAppState.getInstance(mContext).getModel(); + // Load the model once so that there is no pending migration: + loadModelSync(model); + + runOnExecutorSync(MODEL_EXECUTOR, () -> { + ModelDbController controller = model.getModelDbController(); + // Migrate any previous data so that the DB state is correct + controller.tryMigrateDB(); + + // Create DB again to load fresh data + controller.createEmptyDB(); + controller.clearEmptyDbFlag(); + + // Add new data + List values = new ArrayList<>(); + int count = mItemsToSubmit.size(); + for (int i = 0; i < count; i++) { + ContentWriter writer = new ContentWriter(mContext); + mItemsToSubmit.get(i).get().onAddToDatabase(writer); + writer.put(LauncherSettings.Favorites._ID, i); + values.add(writer.getValues(mContext)); + } + controller.bulkInsert(TABLE_NAME, values.toArray(new ContentValues[0])); + }); + + // Reload model + runOnExecutorSync(MAIN_EXECUTOR, model::forceReload); + loadModelSync(model); + } + + private void loadModelSync(LauncherModel model) { + Callbacks mockCb = new Callbacks() { }; + runOnExecutorSync(MAIN_EXECUTOR, () -> model.addCallbacksAndLoad(mockCb)); + runOnExecutorSync(MODEL_EXECUTOR, () -> { }); + + runOnExecutorSync(MAIN_EXECUTOR, () -> { }); + runOnExecutorSync(MAIN_EXECUTOR, () -> model.removeCallbacks(mockCb)); } } diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java index c4aa42bde8..c426480d4e 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java @@ -60,7 +60,7 @@ public class ReorderWidgets extends AbstractLauncherUiTest { @Before public void setup() throws Throwable { - mWorkspaceBuilder = new TestWorkspaceBuilder(this, mTargetContext); + mWorkspaceBuilder = new TestWorkspaceBuilder(mTargetContext); TaplTestsLauncher3.initialize(this); clearHomescreen(); } @@ -109,7 +109,7 @@ public class ReorderWidgets extends AbstractLauncherUiTest { testCase.mStart); FavoriteItemsTransaction transaction = - new FavoriteItemsTransaction(mTargetContext, this); + new FavoriteItemsTransaction(mTargetContext); transaction = buildWorkspaceFromBoards(testCase.mStart, transaction); transaction.commit(); // resetLoaderState triggers the launcher to start loading the workspace which allows diff --git a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java index 5945605daf..cde733ed2b 100644 --- a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java +++ b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java @@ -15,6 +15,9 @@ */ package com.android.launcher3.celllayout; +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; + +import static com.android.launcher3.ui.TestViewHelpers.findWidgetProvider; import static com.android.launcher3.util.WidgetUtils.createWidgetInfo; import android.content.ComponentName; @@ -25,33 +28,29 @@ import android.os.Process; import android.os.UserHandle; import android.util.Log; -import androidx.test.core.app.ApplicationProvider; - import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherSettings; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.ui.AbstractLauncherUiTest; -import com.android.launcher3.ui.TestViewHelpers; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; +import java.util.function.Supplier; +import java.util.stream.IntStream; + public class TestWorkspaceBuilder { private static final String TAG = "CellLayoutBoardBuilder"; private static final ComponentName APP_COMPONENT_NAME = new ComponentName( "com.google.android.calculator", "com.android.calculator2.Calculator"); - public AbstractLauncherUiTest mTest; - private UserHandle mMyUser; private Context mContext; private ContentResolver mResolver; - public TestWorkspaceBuilder(AbstractLauncherUiTest test, Context context) { - mTest = test; + public TestWorkspaceBuilder(Context context) { mMyUser = Process.myUserHandle(); mContext = context; mResolver = mContext.getContentResolver(); @@ -68,10 +67,9 @@ public class TestWorkspaceBuilder { for (int y = initY; y < initY + widgetRect.getSpanY(); y++) { try { // this widgets are filling, we don't care if we can't place them - ItemInfo item = createWidgetInCell( + transaction.addItem(createWidgetInCell( new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE, - new Rect(x, y, x, y)), screenId); - transaction.addItem(item); + new Rect(x, y, x, y)), screenId)); } catch (Exception e) { Log.d(TAG, "Unable to place filling widget at " + x + "," + y); } @@ -108,7 +106,7 @@ public class TestWorkspaceBuilder { board.getWidgets().forEach( (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId)); board.getIcons().forEach((iconPoint) -> - transaction.addItem(createIconInCell(iconPoint, screenId)) + transaction.addItem(() -> createIconInCell(iconPoint, screenId)) ); return transaction; } @@ -118,24 +116,25 @@ public class TestWorkspaceBuilder { * be clean otherwise this doesn't overrides the existing icons. */ public FavoriteItemsTransaction fillHotseatIcons(FavoriteItemsTransaction transaction) { - int hotseatCount = InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons; - for (int i = 0; i < hotseatCount; i++) { - transaction.addItem(getHotseatValues(i)); - } + IntStream.range(0, InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons) + .forEach(i -> transaction.addItem(() -> getHotseatValues(i))); return transaction; } - private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect, int screenId) { - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false); - LauncherAppWidgetInfo item = createWidgetInfo(info, - ApplicationProvider.getApplicationContext(), true); - item.id = getID(); - item.cellX = widgetRect.getCellX(); - item.cellY = widgetRect.getCellY(); - item.spanX = widgetRect.getSpanX(); - item.spanY = widgetRect.getSpanY(); - item.screenId = screenId; - return item; + private Supplier createWidgetInCell( + CellLayoutBoard.WidgetRect widgetRect, int screenId) { + // Create the widget lazily since the appWidgetId can get lost during setup + return () -> { + LauncherAppWidgetProviderInfo info = findWidgetProvider(false); + LauncherAppWidgetInfo item = createWidgetInfo(info, getApplicationContext(), true); + item.id = getID(); + item.cellX = widgetRect.getCellX(); + item.cellY = widgetRect.getCellY(); + item.spanX = widgetRect.getSpanX(); + item.spanY = widgetRect.getSpanY(); + item.screenId = screenId; + return item; + }; } private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint, int screenId) { diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 09c4b1f49a..4506fa36a2 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -19,6 +19,7 @@ import static androidx.test.InstrumentationRegistry.getInstrumentation; import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.TestUtil.getOnUiThread; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -39,7 +40,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; -import android.system.OsConstants; import android.util.Log; import androidx.test.InstrumentationRegistry; @@ -64,6 +64,7 @@ import com.android.launcher3.testcomponent.TestCommandReceiver; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.LooperExecutor; import com.android.launcher3.util.SimpleBroadcastReceiver; +import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.Wait; import com.android.launcher3.util.WidgetUtils; import com.android.launcher3.util.rule.FailureWatcher; @@ -82,10 +83,8 @@ import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import java.io.IOException; -import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -98,7 +97,7 @@ public abstract class AbstractLauncherUiTest { public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10); public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5; - public static final long DEFAULT_UI_TIMEOUT = 10000; + public static final long DEFAULT_UI_TIMEOUT = TestUtil.DEFAULT_UI_TIMEOUT; private static final String TAG = "AbstractLauncherUiTest"; private static boolean sDumpWasGenerated = false; @@ -332,22 +331,6 @@ public abstract class AbstractLauncherUiTest { mLauncher.waitForLauncherInitialized(); } - /** - * Runs the callback on the UI thread and returns the result. - */ - protected T getOnUiThread(final Callable callback) { - try { - return mMainThreadExecutor.submit(callback).get(DEFAULT_UI_TIMEOUT, - TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - Log.e(TAG, "Timeout in getOnUiThread, sending SIGABRT", e); - Process.sendSignal(Process.myPid(), OsConstants.SIGABRT); - throw new RuntimeException(e); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - protected T getFromLauncher(Function f) { if (!TestHelpers.isInLauncherProcess()) return null; return getOnUiThread(() -> f.apply(mActivityMonitor.getActivity())); diff --git a/tests/src/com/android/launcher3/ui/TestViewHelpers.java b/tests/src/com/android/launcher3/ui/TestViewHelpers.java index 083f58015c..4b2bade452 100644 --- a/tests/src/com/android/launcher3/ui/TestViewHelpers.java +++ b/tests/src/com/android/launcher3/ui/TestViewHelpers.java @@ -15,11 +15,14 @@ */ package com.android.launcher3.ui; -import static androidx.test.InstrumentationRegistry.getInstrumentation; -import static androidx.test.InstrumentationRegistry.getTargetContext; +import static android.os.Process.myUserHandle; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static com.android.launcher3.util.TestUtil.getOnUiThread; + +import android.app.Instrumentation; import android.content.ComponentName; -import android.os.Process; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -29,7 +32,6 @@ import com.android.launcher3.testcomponent.AppWidgetWithConfig; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.WidgetManagerHelper; -import java.util.concurrent.Callable; import java.util.function.Function; public class TestViewHelpers { @@ -38,23 +40,16 @@ public class TestViewHelpers { /** * Finds a widget provider which can fit on the home screen. * - * @param test test suite. * @param hasConfigureScreen if true, a provider with a config screen is returned. */ - public static LauncherAppWidgetProviderInfo findWidgetProvider(AbstractLauncherUiTest test, - final boolean hasConfigureScreen) { - LauncherAppWidgetProviderInfo info = - test.getOnUiThread(new Callable() { - @Override - public LauncherAppWidgetProviderInfo call() throws Exception { - ComponentName cn = new ComponentName(getInstrumentation().getContext(), - hasConfigureScreen ? AppWidgetWithConfig.class - : AppWidgetNoConfig.class); - Log.d(TAG, "findWidgetProvider componentName=" + cn.flattenToString()); - return new WidgetManagerHelper(getTargetContext()) - .findProvider(cn, Process.myUserHandle()); - } - }); + public static LauncherAppWidgetProviderInfo findWidgetProvider(boolean hasConfigureScreen) { + LauncherAppWidgetProviderInfo info = getOnUiThread(() -> { + Instrumentation i = getInstrumentation(); + ComponentName cn = new ComponentName(i.getContext(), + hasConfigureScreen ? AppWidgetWithConfig.class : AppWidgetNoConfig.class); + Log.d(TAG, "findWidgetProvider componentName=" + cn.flattenToString()); + return new WidgetManagerHelper(i.getTargetContext()).findProvider(cn, myUserHandle()); + }); if (info == null) { throw new IllegalArgumentException("No valid widget provider"); } diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java index 38066487a6..fddbc37697 100644 --- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java @@ -64,7 +64,7 @@ public class AddConfigWidgetTest extends AbstractLauncherUiTest { @Before public void setUp() throws Exception { super.setUp(); - mWidgetInfo = TestViewHelpers.findWidgetProvider(this, true /* hasConfigureScreen */); + mWidgetInfo = TestViewHelpers.findWidgetProvider(true /* hasConfigureScreen */); mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext); } diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java index 028b9b6a59..5cdc886a41 100644 --- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java @@ -61,7 +61,7 @@ public class AddWidgetTest extends AbstractLauncherUiTest { waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading()); final LauncherAppWidgetProviderInfo widgetInfo = - TestViewHelpers.findWidgetProvider(this, false /* hasConfigureScreen */); + TestViewHelpers.findWidgetProvider(false /* hasConfigureScreen */); WidgetResizeFrame resizeFrame = mLauncher .getWorkspace() diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java index 0f861eb1f3..99d22016a8 100644 --- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java @@ -17,6 +17,7 @@ package com.android.launcher3.ui.widget; import static androidx.test.InstrumentationRegistry.getTargetContext; +import static com.android.launcher3.util.TestUtil.getOnUiThread; import static com.android.launcher3.util.WidgetUtils.createWidgetInfo; import static org.junit.Assert.assertEquals; @@ -103,7 +104,7 @@ public class BindWidgetTest extends AbstractLauncherUiTest { @Test public void testBindNormalWidget_withConfig() { - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, true); + LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(true); LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), true); addItemToScreen(item); @@ -112,7 +113,7 @@ public class BindWidgetTest extends AbstractLauncherUiTest { @Test public void testBindNormalWidget_withoutConfig() { - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false); + LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(false); LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), true); addItemToScreen(item); @@ -121,7 +122,7 @@ public class BindWidgetTest extends AbstractLauncherUiTest { @Test public void testUnboundWidget_removed() { - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false); + LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(false); LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), false); item.appWidgetId = -33; @@ -140,7 +141,7 @@ public class BindWidgetTest extends AbstractLauncherUiTest { @Test public void testPendingWidget_autoRestored() { // A non-restored widget with no config screen gets restored automatically. - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false); + LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(false); // Do not bind the widget LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), false); @@ -153,7 +154,7 @@ public class BindWidgetTest extends AbstractLauncherUiTest { @Test public void testPendingWidget_withConfigScreen() { // A non-restored widget with config screen get bound and shows a 'Click to setup' UI. - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, true); + LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(true); // Do not bind the widget LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), false); diff --git a/tests/src/com/android/launcher3/util/TestUtil.java b/tests/src/com/android/launcher3/util/TestUtil.java index 14bc8b9e4c..7332b836f8 100644 --- a/tests/src/com/android/launcher3/util/TestUtil.java +++ b/tests/src/com/android/launcher3/util/TestUtil.java @@ -18,14 +18,13 @@ package com.android.launcher3.util; import static android.util.Base64.NO_PADDING; import static android.util.Base64.NO_WRAP; -import static androidx.test.InstrumentationRegistry.getContext; -import static androidx.test.InstrumentationRegistry.getInstrumentation; -import static androidx.test.InstrumentationRegistry.getTargetContext; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG; +import android.app.Instrumentation; import android.app.blob.BlobHandle; import android.app.blob.BlobStoreManager; import android.content.Context; @@ -35,9 +34,12 @@ import android.os.AsyncTask; import android.os.Handler; import android.os.Looper; import android.os.ParcelFileDescriptor.AutoCloseOutputStream; +import android.os.Process; import android.os.UserHandle; import android.provider.Settings; +import android.system.OsConstants; import android.util.Base64; +import android.util.Log; import androidx.test.uiautomator.UiDevice; @@ -52,27 +54,35 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.MessageDigest; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.function.Predicate; import java.util.function.ToIntFunction; public class TestUtil { + private static final String TAG = "TestUtil"; + public static final String DUMMY_PACKAGE = "com.example.android.aardwolf"; public static final int DEFAULT_USER_ID = 0; + public static final long DEFAULT_UI_TIMEOUT = 10000; public static void installDummyApp() throws IOException { installDummyAppForUser(DEFAULT_USER_ID); } public static void installDummyAppForUser(int userId) throws IOException { + Instrumentation instrumentation = getInstrumentation(); // Copy apk from resources to a local file and install from there. - final Resources resources = getContext().getResources(); + final Resources resources = instrumentation.getContext().getResources(); final InputStream in = resources.openRawResource( resources.getIdentifier("aardwolf_dummy_app", - "raw", getContext().getPackageName())); - final String apkFilename = getInstrumentation().getTargetContext(). - getFilesDir().getPath() + "/dummy_app.apk"; + "raw", instrumentation.getContext().getPackageName())); + final String apkFilename = instrumentation.getTargetContext() + .getFilesDir().getPath() + "/dummy_app.apk"; try (PackageInstallCheck pic = new PackageInstallCheck()) { final FileOutputStream out = new FileOutputStream(apkFilename); @@ -85,7 +95,7 @@ public class TestUtil { in.close(); out.close(); - final String result = UiDevice.getInstance(getInstrumentation()) + final String result = UiDevice.getInstance(instrumentation) .executeShellCommand("pm install --user " + userId + " " + apkFilename); Assert.assertTrue( "Failed to install wellbeing test apk; make sure the device is rooted", @@ -177,13 +187,33 @@ public class TestUtil { } } + /** + * Runs the callback on the UI thread and returns the result. + */ + public static T getOnUiThread(final Callable callback) { + try { + FutureTask task = new FutureTask<>(callback); + if (Looper.myLooper() == Looper.getMainLooper()) { + task.run(); + } else { + new Handler(Looper.getMainLooper()).post(task); + } + return task.get(DEFAULT_UI_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + Log.e(TAG, "Timeout in getOnUiThread, sending SIGABRT", e); + Process.sendSignal(Process.myPid(), OsConstants.SIGABRT); + throw new RuntimeException(e); + } catch (Throwable 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 { @@ -191,7 +221,8 @@ public class TestUtil { final LauncherApps mLauncherApps; PackageInstallCheck() { - mLauncherApps = getTargetContext().getSystemService(LauncherApps.class); + mLauncherApps = getInstrumentation().getTargetContext() + .getSystemService(LauncherApps.class); mLauncherApps.registerCallback(this, new Handler(Looper.getMainLooper())); } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 1111d32124..2286d7ef13 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -138,17 +138,6 @@ public final class LauncherInstrumentation { OUTSIDE_WITH_KEYCODE, } - /** - * Represents a point in the code at which a callback can run. - */ - public enum CALLBACK_RUN_POINT { - CALLBACK_HOLD_BEFORE_DROP, - CALLBACK_HOVER_ENTER, - CALLBACK_HOVER_EXIT, - } - - private Consumer mCallbackAtRunPoint = null; - // Base class for launcher containers. abstract static class VisibleContainer { protected final LauncherInstrumentation mLauncher; @@ -2063,22 +2052,6 @@ public final class LauncherInstrumentation { } } - /** - * Sets the consumer to run callbacks at all run-points. - */ - public void setRunPointCallback(Consumer callback) { - mCallbackAtRunPoint = callback; - } - - /** - * Runs the callback at the specified point if it exists. - */ - void runCallbackIfActive(CALLBACK_RUN_POINT runPoint) { - if (mCallbackAtRunPoint != null) { - mCallbackAtRunPoint.accept(runPoint); - } - } - /** * Waits until a particular condition is true. Based on WaitMixin. */ diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java index b2cc92de09..e3035bf71b 100644 --- a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java +++ b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java @@ -15,13 +15,7 @@ */ package com.android.launcher3.tapl; -import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOVER_ENTER; -import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOVER_EXIT; - -import android.graphics.Point; import android.graphics.Rect; -import android.os.SystemClock; -import android.view.MotionEvent; import androidx.test.uiautomator.UiObject2; @@ -42,28 +36,4 @@ public class OverviewTaskMenuItem { public Rect getVisibleBounds() { return mMenuItem.getVisibleBounds(); } - - /** - * Emulate the cursor entering and exiting a hover over this menu item. - */ - public void hoverCursor() { - try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); - LauncherInstrumentation.Closable c = mLauncher.addContextLayer( - "cursor hover entering menu item")) { - long downTime = SystemClock.uptimeMillis(); - mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER, - new Point(mMenuItem.getVisibleCenter().x, mMenuItem.getVisibleCenter().y), - null); - mLauncher.runCallbackIfActive(CALLBACK_HOVER_ENTER); - - try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( - "cursor hover exiting menu item")) { - downTime = SystemClock.uptimeMillis(); - mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT, - new Point(mMenuItem.getVisibleCenter().x, mMenuItem.getVisibleCenter().y), - null); - mLauncher.runCallbackIfActive(CALLBACK_HOVER_EXIT); - } - } - } } diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 7bb02cb518..860498817a 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -18,7 +18,6 @@ package com.android.launcher3.tapl; import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_SCROLLED; -import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOLD_BEFORE_DROP; import static com.android.launcher3.testing.shared.TestProtocol.ALL_APPS_STATE_ORDINAL; import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL; @@ -553,7 +552,6 @@ public final class Workspace extends Home { launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating, downTime, SystemClock.uptimeMillis(), false, LauncherInstrumentation.GestureScope.INSIDE); - launcher.runCallbackIfActive(CALLBACK_HOLD_BEFORE_DROP); dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents); } } @@ -587,7 +585,6 @@ public final class Workspace extends Home { launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating, downTime, SystemClock.uptimeMillis(), false, LauncherInstrumentation.GestureScope.INSIDE); - launcher.runCallbackIfActive(CALLBACK_HOLD_BEFORE_DROP); dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents); } }