Merge "Moving some tests off TAPL" into main
diff --git a/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
similarity index 73%
rename from quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
rename to quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
index e981570..5b46dc8 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
+++ b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
@@ -15,7 +15,9 @@
*/
package com.android.quickstep;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.util.TestUtil.resolveSystemAppInfo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -25,10 +27,13 @@
import android.app.usage.UsageStatsManager;
import android.content.Intent;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.BaseLauncherActivityTest;
import com.android.quickstep.views.DigitalWellBeingToast;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskContainer;
@@ -41,30 +46,31 @@
@LargeTest
@RunWith(AndroidJUnit4.class)
-public class TaplDigitalWellBeingToastTest extends AbstractQuickStepTest {
- private static final String CALCULATOR_PACKAGE =
- resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+public class DigitalWellBeingToastTest extends BaseLauncherActivityTest<QuickstepLauncher> {
+
+ public final String calculatorPackage =
+ resolveSystemAppInfo(Intent.CATEGORY_APP_CALCULATOR).packageName;
@Test
- public void testToast() throws Exception {
- startAppFast(CALCULATOR_PACKAGE);
+ public void testToast() {
+ startAppFast(calculatorPackage);
final UsageStatsManager usageStatsManager =
- mTargetContext.getSystemService(UsageStatsManager.class);
+ targetContext().getSystemService(UsageStatsManager.class);
final int observerId = 0;
try {
- final String[] packages = new String[]{CALCULATOR_PACKAGE};
+ final String[] packages = new String[]{calculatorPackage};
// Set time limit for app.
runWithShellPermission(() ->
usageStatsManager.registerAppUsageLimitObserver(observerId, packages,
Duration.ofSeconds(600), Duration.ofSeconds(300),
- PendingIntent.getActivity(mTargetContext, -1, new Intent()
- .setPackage(mTargetContext.getPackageName()),
+ PendingIntent.getActivity(targetContext(), -1, new Intent()
+ .setPackage(targetContext().getPackageName()),
PendingIntent.FLAG_MUTABLE)));
- mLauncher.goHome();
+ loadLauncherSync();
final DigitalWellBeingToast toast = getToast();
waitForLauncherCondition("Toast is not visible", launcher -> toast.getHasLimit());
@@ -74,7 +80,7 @@
runWithShellPermission(
() -> usageStatsManager.unregisterAppUsageLimitObserver(observerId));
- mLauncher.goHome();
+ goToState(LauncherState.NORMAL);
assertFalse("Toast is visible", getToast().getHasLimit());
} finally {
runWithShellPermission(
@@ -83,12 +89,12 @@
}
private DigitalWellBeingToast getToast() {
- mLauncher.getWorkspace().switchToOverview();
+ goToState(LauncherState.OVERVIEW);
final TaskView task = getOnceNotNull("No latest task", launcher -> getLatestTask(launcher));
return getFromLauncher(launcher -> {
TaskContainer taskContainer = task.getTaskContainers().get(0);
- assertTrue("Latest task is not Calculator", CALCULATOR_PACKAGE.equals(
+ assertTrue("Latest task is not Calculator", calculatorPackage.equals(
taskContainer.getTask().getTopComponent().getPackageName()));
return taskContainer.getDigitalWellBeingToast();
});
@@ -105,6 +111,5 @@
} finally {
getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
}
-
}
}
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java b/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java
index ce682f1..eb25acf 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java
@@ -29,7 +29,10 @@
import android.app.blob.BlobHandle;
import android.app.blob.BlobStoreManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.AsyncTask;
@@ -231,6 +234,15 @@
.adoptShellPermissionIdentity(Manifest.permission.WRITE_SECURE_SETTINGS);
}
+ /**
+ * Returns the activity info corresponding to the system app for the provided category
+ */
+ public static ActivityInfo resolveSystemAppInfo(String category) {
+ return getInstrumentation().getTargetContext().getPackageManager().resolveActivity(
+ new Intent(Intent.ACTION_MAIN).addCategory(category),
+ PackageManager.MATCH_SYSTEM_ONLY).activityInfo;
+ }
+
/** Interface to indicate a runnable which can throw any exception. */
public interface UncheckedRunnable {
/** Method to run the task */
diff --git a/tests/src/com/android/launcher3/LauncherIntentTest.java b/tests/src/com/android/launcher3/LauncherIntentTest.java
index 3e16713..a3d9614 100644
--- a/tests/src/com/android/launcher3/LauncherIntentTest.java
+++ b/tests/src/com/android/launcher3/LauncherIntentTest.java
@@ -27,17 +27,23 @@
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.SearchRecyclerView;
-import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.BaseLauncherActivityTest;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@LargeTest
@RunWith(AndroidJUnit4.class)
-public class LauncherIntentTest extends AbstractLauncherUiTest<Launcher> {
+public class LauncherIntentTest extends BaseLauncherActivityTest<Launcher> {
public final Intent allAppsIntent = new Intent(Intent.ACTION_ALL_APPS);
+ @Before
+ public void setUp() {
+ loadLauncherSync();
+ }
+
@Test
public void testAllAppsIntent() {
// Try executing ALL_APPS intent
@@ -45,7 +51,6 @@
// A-Z view with Main adapter should be loaded
assertOnMainAdapterAToZView();
-
// Try Moving to search view now
moveToSearchView();
// Try executing ALL_APPS intent
@@ -63,12 +68,14 @@
// Search view should be in focus
waitForLauncherCondition("Search view is not in focus.",
launcher -> launcher.getAppsView().getSearchView().hasFocus());
- mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_C, 0);
+
+ injectKeyEvent(KeyEvent.KEYCODE_C, true);
// Upon key press, search recycler view should be loaded
waitForLauncherCondition("Search view not active.",
launcher -> launcher.getAppsView().getActiveRecyclerView()
instanceof SearchRecyclerView);
- mLauncher.unpressKeyCode(KeyEvent.KEYCODE_C, 0);
+
+ injectKeyEvent(KeyEvent.KEYCODE_C, false);
}
// Checks if main adapter view is selected, search bar is out of focus and scroller is at start.
diff --git a/tests/src/com/android/launcher3/allapps/KeyboardFocusTest.java b/tests/src/com/android/launcher3/allapps/KeyboardFocusTest.java
new file mode 100644
index 0000000..44df5b8
--- /dev/null
+++ b/tests/src/com/android/launcher3/allapps/KeyboardFocusTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import android.view.KeyEvent;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.util.BaseLauncherActivityTest;
+import com.android.launcher3.views.ActivityContext;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KeyboardFocusTest extends BaseLauncherActivityTest<Launcher> {
+
+ @Test
+ public void testAllAppsFocusApp() {
+ loadLauncherSync();
+ goToState(LauncherState.ALL_APPS);
+ freezeAllApps();
+
+ injectKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, true);
+ injectKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, false);
+ waitForLauncherCondition("No focused child", launcher ->
+ launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()
+ != null);
+ }
+
+ @Test
+ public void testAllAppsExitSearchAndFocusApp() {
+ loadLauncherSync();
+ goToState(LauncherState.ALL_APPS);
+ freezeAllApps();
+
+ executeOnLauncher(launcher -> launcher.getAppsView().getSearchView().requestFocus());
+ waitForLauncherCondition("Search view does not have focus.",
+ launcher -> launcher.getAppsView().getSearchView().hasFocus());
+
+ injectKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, true);
+ injectKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, false);
+ waitForLauncherCondition("No focused child", launcher ->
+ launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()
+ != null);
+ }
+
+ @Test
+ public void testAllAppsExitSearchAndFocusSearchResults() {
+ loadLauncherSync();
+ goToState(LauncherState.ALL_APPS);
+ freezeAllApps();
+
+ executeOnLauncher(launcher -> launcher.getAppsView().getSearchView().requestFocus());
+ waitForLauncherCondition("Search view does not have focus.",
+ launcher -> launcher.getAppsView().getSearchView().hasFocus());
+
+ injectKeyEvent(KeyEvent.KEYCODE_C, true);
+ waitForLauncherCondition("Search view not active.",
+ launcher -> launcher.getAppsView().getActiveRecyclerView()
+ instanceof SearchRecyclerView);
+ injectKeyEvent(KeyEvent.KEYCODE_C, false);
+
+ executeOnLauncher(launcher -> launcher.getAppsView().getSearchUiManager().getEditText()
+ .hideKeyboard(/* clearFocus= */ false));
+ waitForLauncherCondition("Keyboard still visible.",
+ ActivityContext::isSoftwareKeyboardHidden);
+
+ injectKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, true);
+ injectKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, false);
+ waitForLauncherCondition("No focused child", launcher ->
+ launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()
+ != null);
+ }
+}
diff --git a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
deleted file mode 100644
index 4e627a9..0000000
--- a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.allapps;
-
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.view.KeyEvent;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
-import com.android.launcher3.tapl.HomeAllApps;
-import com.android.launcher3.ui.AbstractLauncherUiTest;
-import com.android.launcher3.util.rule.TestStabilityRule;
-import com.android.launcher3.views.ActivityContext;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class TaplKeyboardFocusTest extends AbstractLauncherUiTest<Launcher> {
-
- @Test
- public void testAllAppsFocusApp() {
- final HomeAllApps allApps = mLauncher.goHome().switchToAllApps();
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- allApps.freeze();
- try {
- mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_DPAD_DOWN, 0);
- executeOnLauncher(launcher -> assertNotNull("No focused child.",
- launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()));
- } finally {
- allApps.unfreeze();
- }
- }
-
- @Test
- public void testAllAppsExitSearchAndFocusApp() {
- final HomeAllApps allApps = mLauncher.goHome().switchToAllApps();
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- allApps.freeze();
- try {
- executeOnLauncher(launcher -> launcher.getAppsView().getSearchView().requestFocus());
- waitForLauncherCondition("Search view does not have focus.",
- launcher -> launcher.getAppsView().getSearchView().hasFocus());
-
- mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_DPAD_DOWN, 0);
- executeOnLauncher(launcher -> assertNotNull("No focused child.",
- launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()));
- } finally {
- allApps.unfreeze();
- }
- }
-
- @Test
- public void testAllAppsExitSearchAndFocusSearchResults() {
- final HomeAllApps allApps = mLauncher.goHome().switchToAllApps();
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- allApps.freeze();
- try {
- executeOnLauncher(launcher -> launcher.getAppsView().getSearchView().requestFocus());
- waitForLauncherCondition("Search view does not have focus.",
- launcher -> launcher.getAppsView().getSearchView().hasFocus());
-
- mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_C, 0);
- waitForLauncherCondition("Search view not active.",
- launcher -> launcher.getAppsView().getActiveRecyclerView()
- instanceof SearchRecyclerView);
- mLauncher.unpressKeyCode(KeyEvent.KEYCODE_C, 0);
-
- executeOnLauncher(launcher -> launcher.getAppsView().getSearchUiManager().getEditText()
- .hideKeyboard(/* clearFocus= */ false));
- waitForLauncherCondition("Keyboard still visible.",
- ActivityContext::isSoftwareKeyboardHidden);
-
- mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_DPAD_DOWN, 0);
- mLauncher.unpressKeyCode(KeyEvent.KEYCODE_DPAD_DOWN, 0);
- waitForLauncherCondition("No focused child", launcher ->
- launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()
- != null);
- } finally {
- allApps.unfreeze();
- }
- }
-}
diff --git a/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
similarity index 73%
rename from tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java
rename to tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
index 1500538..34b292c 100644
--- a/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java
+++ b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
@@ -1,18 +1,19 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
+
package com.android.launcher3.compat;
import static com.android.launcher3.Flags.FLAG_ENABLE_SUPPORT_FOR_ARCHIVING;
@@ -27,32 +28,31 @@
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.text.TextUtils;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.tapl.AllApps;
-import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.BaseLauncherActivityTest;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.TestUtil;
-import com.android.launcher3.util.rule.ViewCaptureRule;
import org.junit.After;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
+import java.util.Arrays;
import java.util.UUID;
-
/**
* Test to verify promise icon flow.
*/
@LargeTest
@RunWith(AndroidJUnit4.class)
-public class TaplPromiseIconUiTest extends AbstractLauncherUiTest<Launcher> {
+public class PromiseIconUiTest extends BaseLauncherActivityTest<Launcher> {
@Rule
public final CheckFlagsRule mCheckFlagsRule =
@@ -64,19 +64,17 @@
private int mSessionId = -1;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
- mDevice.pressHome();
- waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null);
- waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
+ loadLauncherSync();
+ goToState(LauncherState.NORMAL);
mSessionId = -1;
}
@After
public void tearDown() throws IOException {
if (mSessionId > -1) {
- mTargetContext.getPackageManager().getPackageInstaller().abandonSession(mSessionId);
+ targetContext().getPackageManager().getPackageInstaller().abandonSession(mSessionId);
}
TestUtil.uninstallDummyApp();
}
@@ -90,7 +88,7 @@
params.setAppLabel(label);
params.setAppIcon(icon);
params.setInstallReason(PackageManager.INSTALL_REASON_USER);
- return mTargetContext.getPackageManager().getPackageInstaller().createSession(params);
+ return targetContext().getPackageManager().getPackageInstaller().createSession(params);
}
@Test
@@ -108,7 +106,7 @@
launcher.getWorkspace().getFirstMatch(findPromiseApp) != null);
// Remove session
- mTargetContext.getPackageManager().getPackageInstaller().abandonSession(mSessionId);
+ targetContext().getPackageManager().getPackageInstaller().abandonSession(mSessionId);
mSessionId = -1;
// Verify promise icon is removed
@@ -117,7 +115,6 @@
}
@Test
- @ViewCaptureRule.MayProduceNoFrames
public void testPromiseIcon_notAddedFromIneligibleSession() throws Throwable {
final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
final ItemOperator findPromiseApp = (info, view) ->
@@ -138,7 +135,8 @@
@RequiresFlagsEnabled(FLAG_ENABLE_SUPPORT_FOR_ARCHIVING)
public void testPromiseIcon_addedArchivedApp() throws Throwable {
installDummyAppAndWaitForUIUpdate();
- assertThat(mDevice.executeShellCommand(String.format("pm archive %s", DUMMY_PACKAGE)))
+ assertThat(executeShellCommand(
+ String.format("pm archive %s", DUMMY_PACKAGE)))
.isEqualTo("Success\n");
// Create and add test session
@@ -148,28 +146,19 @@
// Verify promise icon is added to all apps view. The icon may not be added to the
// workspace even if there might be no icon present for archived app. But icon will
// always be in all apps view. In case an icon is not added, an exception would be thrown.
- final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ goToState(LauncherState.ALL_APPS);
// Wait for the promise icon to be added.
waitForLauncherCondition(
DUMMY_PACKAGE + " app was not found on all apps after being archived",
- launcher -> {
- try {
- allApps.getAppIcon(DUMMY_LABEL);
- } catch (Throwable t) {
- return false;
- }
- return true;
- });
-
- // Remove session
- mTargetContext.getPackageManager().getPackageInstaller().abandonSession(mSessionId);
- mSessionId = -1;
+ launcher -> Arrays.stream(launcher.getAppsView().getAppsStore().getApps())
+ .filter(info -> DUMMY_LABEL.equals(info.title.toString()))
+ .findAny()
+ .isPresent());
}
private void installDummyAppAndWaitForUIUpdate() throws IOException {
TestUtil.installDummyApp();
- mLauncher.waitForModelQueueCleared();
- mLauncher.waitForLauncherInitialized();
+ loadLauncherSync();
}
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 1fbdceb..a273648 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.TestUtil.resolveSystemAppInfo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -31,7 +32,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Point;
@@ -627,13 +627,6 @@
launcherInstrumentation);
}
- public static ActivityInfo resolveSystemAppInfo(String category) {
- return getInstrumentation().getContext().getPackageManager().resolveActivity(
- new Intent(Intent.ACTION_MAIN).addCategory(category),
- PackageManager.MATCH_SYSTEM_ONLY).
- activityInfo;
- }
-
public static String resolveSystemApp(String category) {
return resolveSystemAppInfo(category).packageName;
diff --git a/tests/src/com/android/launcher3/util/BaseLauncherActivityTest.kt b/tests/src/com/android/launcher3/util/BaseLauncherActivityTest.kt
new file mode 100644
index 0000000..bacce40
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/BaseLauncherActivityTest.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util
+
+import android.content.Context
+import android.content.Intent
+import android.os.SystemClock
+import android.view.InputDevice
+import android.view.KeyCharacterMap
+import android.view.KeyEvent
+import android.view.MotionEvent
+import androidx.lifecycle.Lifecycle.State.RESUMED
+import androidx.test.core.app.ActivityScenario
+import androidx.test.core.app.ActivityScenario.ActivityAction
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.Launcher
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.LauncherState
+import com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST
+import com.android.launcher3.tapl.TestHelpers
+import com.android.launcher3.util.ModelTestExtensions.loadModelSync
+import com.android.launcher3.util.Wait.atMost
+import java.util.function.Function
+import java.util.function.Supplier
+import org.junit.After
+
+/**
+ * Base class for tests which use Launcher activity with some utility methods.
+ *
+ * This should instead be a rule, but is kept as a base class for easier migration from TAPL
+ */
+open class BaseLauncherActivityTest<LAUNCHER_TYPE : Launcher> {
+
+ private var currentScenario: ActivityScenario<LAUNCHER_TYPE>? = null
+
+ val scenario: ActivityScenario<LAUNCHER_TYPE>
+ get() =
+ currentScenario
+ ?: ActivityScenario.launch<LAUNCHER_TYPE>(
+ TestHelpers.getHomeIntentInPackage(targetContext()),
+ null,
+ )
+ .also { currentScenario = it }
+
+ @After
+ fun closeCurrentActivity() {
+ currentScenario?.close()
+ currentScenario = null
+ }
+
+ protected fun loadLauncherSync() {
+ LauncherAppState.getInstance(targetContext()).model.loadModelSync()
+ scenario.moveToState(RESUMED)
+ }
+
+ protected fun targetContext(): Context = getInstrumentation().targetContext
+
+ protected fun goToState(state: LauncherState) = executeOnLauncher {
+ it.stateManager.goToState(state, 0)
+ }
+
+ protected fun executeOnLauncher(f: ActivityAction<LAUNCHER_TYPE>) = scenario.onActivity(f)
+
+ protected fun <T> getFromLauncher(f: Function<in LAUNCHER_TYPE, out T?>): T? {
+ var result: T? = null
+ executeOnLauncher { result = f.apply(it) }
+ return result
+ }
+
+ protected fun isInState(state: Supplier<LauncherState>): Boolean =
+ getFromLauncher { it.stateManager.state == state.get() }!!
+
+ protected fun waitForState(message: String, state: Supplier<LauncherState>) =
+ waitForLauncherCondition(message) { it.stateManager.currentStableState === state.get() }
+
+ protected fun waitForLauncherCondition(
+ message: String,
+ condition: Function<LAUNCHER_TYPE, Boolean>,
+ ) = atMost(message, { getFromLauncher(condition)!! })
+
+ protected fun <T> getOnceNotNull(message: String, f: Function<LAUNCHER_TYPE, T?>): T? {
+ var output: T? = null
+ atMost(
+ message,
+ {
+ val fromLauncher = getFromLauncher<T>(f)
+ output = fromLauncher
+ fromLauncher != null
+ },
+ )
+ return output
+ }
+
+ protected fun getAllAppsScroll(launcher: LAUNCHER_TYPE) =
+ launcher.appsView.activeRecyclerView.computeVerticalScrollOffset()
+
+ @JvmOverloads
+ protected fun injectKeyEvent(keyCode: Int, actionDown: Boolean, metaState: Int = 0) {
+ val eventTime = SystemClock.uptimeMillis()
+ val event =
+ KeyEvent.obtain(
+ eventTime,
+ eventTime,
+ if (actionDown) KeyEvent.ACTION_DOWN else MotionEvent.ACTION_UP,
+ keyCode,
+ /* repeat= */ 0,
+ metaState,
+ KeyCharacterMap.VIRTUAL_KEYBOARD,
+ /* scancode= */ 0,
+ /* flags= */ 0,
+ InputDevice.SOURCE_KEYBOARD,
+ /* characters =*/ null,
+ )
+ executeOnLauncher { it.dispatchKeyEvent(event) }
+ event.recycle()
+ }
+
+ fun startAppFast(packageName: String) {
+ val intent = targetContext().packageManager.getLaunchIntentForPackage(packageName)!!
+ intent.addCategory(Intent.CATEGORY_LAUNCHER)
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ targetContext().startActivity(intent)
+ UiDevice.getInstance(getInstrumentation()).waitForIdle()
+ }
+
+ fun freezeAllApps() = executeOnLauncher {
+ it.appsView.appsStore.enableDeferUpdates(DEFER_UPDATES_TEST)
+ }
+
+ fun executeShellCommand(cmd: String) =
+ UiDevice.getInstance(getInstrumentation()).executeShellCommand(cmd)
+}