Using a runtime generated layout for tests instead of defining xml
This allows support for easily setting up default layouts
Bug: 277345535
Test: Presubmit
Flag: N/A
Change-Id: I1c089d60ac3f8add8d7e1060d343e04d30afe094
diff --git a/tests/Android.bp b/tests/Android.bp
index 81853d1..da8d844 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -45,6 +45,7 @@
"src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
"src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
"src/com/android/launcher3/ui/TaplTestsLauncher3.java",
+ "src/com/android/launcher3/util/LauncherLayoutBuilder.java",
"src/com/android/launcher3/util/TestUtil.java",
"src/com/android/launcher3/util/Wait.java",
"src/com/android/launcher3/util/WidgetUtils.java",
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index a37c3cd..dc835e2 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -106,11 +106,6 @@
public static final String REQUEST_GET_HAD_NONTEST_EVENTS = "get-had-nontest-events";
public static final String REQUEST_STOP_EVENT_LOGGING = "stop-event-logging";
public static final String REQUEST_CLEAR_DATA = "clear-data";
- public static final String REQUEST_USE_TEST_WORKSPACE_LAYOUT = "use-test-workspace-layout";
- public static final String REQUEST_USE_TEST2_WORKSPACE_LAYOUT = "use-test2-workspace-layout";
- public static final String REQUEST_USE_TAPL_WORKSPACE_LAYOUT = "use-tapl-workspace-layout";
- public static final String REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT =
- "use-default-workspace-layout";
public static final String REQUEST_HOTSEAT_ICON_NAMES = "get-hotseat-icon-names";
public static final String REQUEST_IS_TABLET = "is-tablet";
public static final String REQUEST_IS_TWO_PANELS = "is-two-panel";
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 217bec3..81f1525 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -54,12 +54,14 @@
import com.android.launcher3.tapl.HomeAppIconMenuItem;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.TISBindRule;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
+import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
@@ -83,6 +85,8 @@
@Rule
public TISBindRule mTISBindRule = new TISBindRule();
+ private AutoCloseable mLauncherLayout;
+
@Before
public void setUp() throws Exception {
super.setUp();
@@ -101,6 +105,13 @@
AbstractLauncherUiTest.checkDetectedLeaks(test.mLauncher);
}
+ @After
+ public void tearDown() throws Exception {
+ if (mLauncherLayout != null) {
+ mLauncherLayout.close();
+ }
+ }
+
// Please don't add negative test cases for methods that fail only after a long wait.
public static void expectFail(String message, Runnable action) {
boolean failed = false;
@@ -230,8 +241,10 @@
@Test
@ScreenRecord // b/202433017
public void testWorkspace() throws Exception {
- // Make sure there is an instance of chrome on the hotseat
- mLauncher.useTaplWorkspaceLayoutOnReload();
+ // Set workspace that includes the chrome Activity app icon on the hotseat.
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atHotseat(0).putApp("com.android.chrome", "com.google.android.apps.chrome.Main");
+ mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, builder);
clearLauncherData();
final Workspace workspace = mLauncher.getWorkspace();
diff --git a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
index 3abafdf..c4b6d43 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
@@ -30,6 +30,8 @@
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.LauncherLayoutBuilder;
+import com.android.launcher3.util.TestUtil;
import org.junit.After;
import org.junit.Before;
@@ -49,12 +51,24 @@
@RunWith(AndroidJUnit4.class)
public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest {
+ private AutoCloseable mLauncherLayout;
+
@Before
public void setUp() throws Exception {
super.setUp();
- mLauncher.useTest2WorkspaceLayoutOnReload();
- TaplTestsLauncher3.initialize(this);
+ // Set layout that includes Maps/Play on workspace, and Messaging/Chrome on hotseat.
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atHotseat(0).putApp(
+ "com.google.android.apps.messaging",
+ "com.google.android.apps.messaging.ui.ConversationListActivity")
+ .atHotseat(1).putApp("com.android.chrome", "com.google.android.apps.chrome.Main")
+ .atWorkspace(0, -1, 0).putApp(
+ "com.google.android.apps.maps", "com.google.android.maps.MapsActivity")
+ .atWorkspace(3, -1, 0).putApp(
+ "com.android.vending", "com.android.vending.AssetBrowserActivity");
+ mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, builder);
+ TaplTestsLauncher3.initialize(this);
assumeTrue(mLauncher.isTwoPanels());
// Pre verifying the screens
@@ -67,9 +81,11 @@
}
@After
- public void tearDown() {
+ public void tearDown() throws Exception {
executeOnLauncher(launcher -> launcher.enableHotseatEdu(true));
- mLauncher.useDefaultWorkspaceLayoutOnReload();
+ if (mLauncherLayout != null) {
+ mLauncherLayout.close();
+ }
}
@Test
diff --git a/tests/src/com/android/launcher3/util/TestUtil.java b/tests/src/com/android/launcher3/util/TestUtil.java
index 433fd31..4981795 100644
--- a/tests/src/com/android/launcher3/util/TestUtil.java
+++ b/tests/src/com/android/launcher3/util/TestUtil.java
@@ -15,15 +15,29 @@
*/
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 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.blob.BlobHandle;
+import android.app.blob.BlobStoreManager;
+import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.res.Resources;
+import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
+import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Base64;
import androidx.test.uiautomator.UiDevice;
@@ -36,6 +50,8 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.MessageDigest;
import java.util.concurrent.CountDownLatch;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
@@ -109,6 +125,35 @@
"pm uninstall " + DUMMY_PACKAGE);
}
+ /**
+ * Sets the default layout for Launcher and returns an object which can be used to clear
+ * the data
+ */
+ public static AutoCloseable setLauncherDefaultLayout(
+ Context context, LauncherLayoutBuilder layoutBuilder) throws Exception {
+ byte[] data = layoutBuilder.build().getBytes();
+ byte[] digest = MessageDigest.getInstance("SHA-256").digest(data);
+
+ BlobHandle handle = BlobHandle.createWithSha256(
+ digest, LAYOUT_DIGEST_LABEL, 0, LAYOUT_DIGEST_TAG);
+ BlobStoreManager blobManager = context.getSystemService(BlobStoreManager.class);
+ final long sessionId = blobManager.createSession(handle);
+ CountDownLatch wait = new CountDownLatch(1);
+ try (BlobStoreManager.Session session = blobManager.openSession(sessionId)) {
+ try (OutputStream out = new AutoCloseOutputStream(session.openWrite(0, -1))) {
+ out.write(data);
+ }
+ session.allowPublicAccess();
+ session.commit(AsyncTask.THREAD_POOL_EXECUTOR, i -> wait.countDown());
+ }
+
+ String key = Base64.encodeToString(digest, NO_WRAP | NO_PADDING);
+ Settings.Secure.putString(context.getContentResolver(), LAYOUT_DIGEST_KEY, key);
+ wait.await();
+ return () ->
+ Settings.Secure.putString(context.getContentResolver(), LAYOUT_DIGEST_KEY, null);
+ }
+
private static class PackageInstallCheck extends LauncherApps.Callback
implements AutoCloseable {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 9905603..ba8f070 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1851,36 +1851,6 @@
getTestInfo(TestProtocol.REQUEST_CLEAR_DATA);
}
- /**
- * Reloads the workspace with a test layout that includes the Test Activity app icon on the
- * hotseat.
- */
- public void useTestWorkspaceLayoutOnReload() {
- getTestInfo(TestProtocol.REQUEST_USE_TEST_WORKSPACE_LAYOUT);
- }
-
- /**
- * Reloads the workspace with a test layout that includes Maps/Play on workspace, and
- * Dialer/Messaging/Chrome/Camera on hotseat.
- */
- public void useTest2WorkspaceLayoutOnReload() {
- getTestInfo(TestProtocol.REQUEST_USE_TEST2_WORKSPACE_LAYOUT);
- }
-
-
- /**
- * Reloads the workspace with a test layout that includes the chrome Activity app icon on the
- * hotseat.
- */
- public void useTaplWorkspaceLayoutOnReload() {
- getTestInfo(TestProtocol.REQUEST_USE_TAPL_WORKSPACE_LAYOUT);
- }
-
- /** Reloads the workspace with the default layout defined by the user's grid size selection. */
- public void useDefaultWorkspaceLayoutOnReload() {
- getTestInfo(TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT);
- }
-
/** Shows the taskbar if it is hidden, otherwise does nothing. */
public void showTaskbarIfHidden() {
getTestInfo(TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED);