Merge "Revert "Change Overview Actions to round buttons."" into udc-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index f6de926..e521154 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.RectF;
+import android.media.permission.SafeCloseable;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.view.KeyEvent;
@@ -31,6 +32,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.app.viewcapture.SettingsAwareViewCapture;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
@@ -68,6 +70,7 @@
 
     // Initialized in init.
     private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks;
+    private SafeCloseable mViewCaptureCloseable;
 
     private float mTaskbarBackgroundOffset;
 
@@ -128,12 +131,14 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
+        mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+                .startCapture(getRootView(), ".Taskbar");
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-
+        mViewCaptureCloseable.close();
         onDestroy(true);
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index add7279..ff00560 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -21,6 +21,7 @@
 
 import android.content.Context;
 import android.graphics.Insets;
+import android.media.permission.SafeCloseable;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -29,6 +30,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.app.viewcapture.SettingsAwareViewCapture;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
@@ -44,6 +46,7 @@
         BaseDragLayer<TaskbarOverlayContext> implements
         ViewTreeObserver.OnComputeInternalInsetsListener {
 
+    private SafeCloseable mViewCaptureCloseable;
     private final List<OnClickListener> mOnClickListeners = new CopyOnWriteArrayList<>();
     private final TouchController mClickListenerTouchController = new TouchController() {
         @Override
@@ -77,12 +80,15 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+        mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+                .startCapture(getRootView(), ".TaskbarOverlay");
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+        mViewCaptureCloseable.close();
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index 5f7d694..c82cdb7 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -24,7 +24,6 @@
 import android.view.WindowMetrics;
 
 import com.android.internal.policy.SystemBarUtils;
-import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.util.WindowBounds;
 import com.android.launcher3.util.window.CachedDisplayInfo;
 import com.android.launcher3.util.window.WindowManagerProxy;
@@ -61,7 +60,6 @@
         WindowManager windowManager = displayInfoContext.getSystemService(WindowManager.class);
         Set<WindowMetrics> possibleMaximumWindowMetrics =
                 windowManager.getPossibleMaximumWindowMetrics(DEFAULT_DISPLAY);
-        FileLog.d("b/283944974", "possibleMaximumWindowMetrics: " + possibleMaximumWindowMetrics);
         for (WindowMetrics windowMetrics : possibleMaximumWindowMetrics) {
             CachedDisplayInfo info = getDisplayInfo(windowMetrics, Surface.ROTATION_0);
             List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 7350214..bb246c2 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep;
 
+import static com.android.launcher3.testing.shared.TestProtocol.FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP;
 import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
 
@@ -27,6 +28,7 @@
 
 import android.content.Intent;
 import android.platform.test.annotations.PlatinumTest;
+import android.util.Log;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -44,6 +46,7 @@
 import com.android.launcher3.tapl.OverviewTask;
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -144,7 +147,7 @@
         assertNotNull("overview.getCurrentTask() returned null (1)", task);
         assertNotNull("OverviewTask.open returned null", task.open());
         assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
-                By.pkg(getAppPackageName()).text("TestActivity2")),
+                        By.pkg(getAppPackageName()).text("TestActivity2")),
                 DEFAULT_UI_TIMEOUT));
         executeOnLauncher(launcher -> assertTrue(
                 "Launcher activity is the top activity; expecting another activity to be the top "
@@ -313,7 +316,6 @@
     @Test
     @ScreenRecord // b/242163205
     @PlatinumTest(focusArea = "launcher")
-    @TaskbarModeSwitch(mode = PERSISTENT)
     public void testQuickSwitchToPreviousAppForTablet() throws Exception {
         assumeTrue(mLauncher.isTablet());
         startTestActivity(2);
@@ -331,9 +333,18 @@
 
         assertTrue("The first app we should have quick switched to is not running",
                 isTestActivityRunning(2));
-        // Expect task bar visible when the launched app was the test activity.
+
         launchedAppState = getAndAssertLaunchedApp();
-        launchedAppState.assertTaskbarVisible();
+
+        Log.e(FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP,
+                "is Taskbar Transient : " + DisplayController.isTransientTaskbar(mTargetContext));
+        // TODO(b/286084688): Remove this branching check after test corruption is resolved.
+        // Branching this check because of test corruption.
+        if (DisplayController.isTransientTaskbar(mTargetContext)) {
+            launchedAppState.assertTaskbarHidden();
+        } else {
+            launchedAppState.assertTaskbarVisible();
+        }
     }
 
     private boolean isTestActivityRunning(int activityNumber) {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index 4c6874e..7ae3f29 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -16,12 +16,19 @@
 
 package com.android.quickstep;
 
+import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
+
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
+import android.app.Instrumentation;
+
 import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TaplTestsLauncher3;
@@ -36,6 +43,9 @@
 @RunWith(AndroidJUnit4.class)
 public class TaplTestsTrackpad extends AbstractQuickStepTest {
 
+    private static final String READ_DEVICE_CONFIG_PERMISSION =
+            "android.permission.READ_DEVICE_CONFIG";
+
     @Before
     public void setUp() throws Exception {
         super.setUp();
@@ -60,6 +70,29 @@
 
     @Test
     @PortraitLandscape
+    // TODO(b/291944684): Support back in 3-button mode. It requires triggering the logic to enable
+    //  trackpad gesture back in SysUI. Normally it's triggered by the attachment of a trackpad. We
+    //  need to figure out a way to emulate that in the test, or bypass the logic altogether.
+    @NavigationModeSwitch(mode = ZERO_BUTTON)
+    public void pressBack() throws Exception {
+        assumeTrue(mLauncher.isTablet());
+        assumeFalse(FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get());
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+        try {
+            instrumentation.getUiAutomation().adoptShellPermissionIdentity(
+                    READ_DEVICE_CONFIG_PERMISSION);
+            mLauncher.setTrackpadGestureType(TrackpadGestureType.THREE_FINGER);
+
+            startTestActivity(2);
+            mLauncher.pressBack();
+        } finally {
+            instrumentation.getUiAutomation().dropShellPermissionIdentity();
+        }
+    }
+
+    @Test
+    @PortraitLandscape
     @NavigationModeSwitch
     public void switchToOverview() throws Exception {
         assumeTrue(mLauncher.isTablet());
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 9803779..4d75fb8 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -205,13 +205,16 @@
         <!-- File that contains the specs for the workspace.
         Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
         <attr name="workspaceSpecsId" format="reference" />
+        <attr name="workspaceSpecsTwoPanelId" format="reference" />
         <!-- File that contains the specs for all apps.
         Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
         <attr name="allAppsSpecsId" format="reference" />
+        <attr name="allAppsSpecsTwoPanelId" format="reference" />
 
         <!-- File that contains the specs for the workspace.
         Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
         <attr name="folderSpecsId" format="reference" />
+        <attr name="folderSpecsTwoPanelId" format="reference" />
 
         <!-- By default all categories are enabled -->
         <attr name="deviceCategory" format="integer">
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 54965e8..42372f1 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -543,7 +543,8 @@
         // for the available height to be correct
         if (mIsResponsiveGrid) {
             WorkspaceSpecs workspaceSpecs = WorkspaceSpecs.create(
-                    new ResourceHelper(context, inv.workspaceSpecsId));
+                    new ResourceHelper(context,
+                            isTwoPanels ? inv.workspaceSpecsTwoPanelId : inv.workspaceSpecsId));
             int availableResponsiveWidth =
                     availableWidthPx - (isVerticalBarLayout() ? hotseatBarSizePx : 0);
             int numColumns = getPanelCount() * inv.numColumns;
@@ -557,14 +558,16 @@
                     availableResponsiveHeight);
 
             AllAppsSpecs allAppsSpecs = AllAppsSpecs.create(
-                    new ResourceHelper(context, inv.allAppsSpecsId));
+                    new ResourceHelper(context,
+                            isTwoPanels ? inv.allAppsSpecsTwoPanelId : inv.allAppsSpecsId));
             mAllAppsResponsiveWidthSpec = allAppsSpecs.getCalculatedWidthSpec(numColumns,
                     mResponsiveWidthSpec.getAvailableSpace(), mResponsiveWidthSpec);
             mAllAppsResponsiveHeightSpec = allAppsSpecs.getCalculatedHeightSpec(inv.numRows,
                     mResponsiveHeightSpec.getAvailableSpace(), mResponsiveHeightSpec);
 
             FolderSpecs folderSpecs = FolderSpecs.create(
-                    new ResourceHelper(context, inv.folderSpecsId));
+                    new ResourceHelper(context,
+                            isTwoPanels ? inv.folderSpecsTwoPanelId : inv.folderSpecsId));
             mResponsiveFolderWidthSpec = folderSpecs.getCalculatedWidthSpec(inv.numFolderColumns,
                     mResponsiveWidthSpec.getAvailableSpace(), mResponsiveWidthSpec);
             mResponsiveFolderHeightSpec = folderSpecs.getCalculatedHeightSpec(inv.numFolderRows,
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 4eaacdc..dac6120 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -180,9 +180,15 @@
     @XmlRes
     public int workspaceSpecsId = INVALID_RESOURCE_HANDLE;
     @XmlRes
+    public int workspaceSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+    @XmlRes
     public int allAppsSpecsId = INVALID_RESOURCE_HANDLE;
     @XmlRes
+    public int allAppsSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+    @XmlRes
     public int folderSpecsId = INVALID_RESOURCE_HANDLE;
+    @XmlRes
+    public int folderSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
 
     public String dbFile;
     public int defaultLayoutId;
@@ -357,8 +363,11 @@
         isScalable = closestProfile.isScalable;
         devicePaddingId = closestProfile.devicePaddingId;
         workspaceSpecsId = closestProfile.mWorkspaceSpecsId;
+        workspaceSpecsTwoPanelId = closestProfile.mWorkspaceSpecsTwoPanelId;
         allAppsSpecsId = closestProfile.mAllAppsSpecsId;
+        allAppsSpecsTwoPanelId = closestProfile.mAllAppsSpecsTwoPanelId;
         folderSpecsId = closestProfile.mFolderSpecsId;
+        folderSpecsTwoPanelId = closestProfile.mFolderSpecsTwoPanelId;
         this.deviceType = deviceType;
 
         inlineNavButtonsEndSpacing = closestProfile.inlineNavButtonsEndSpacing;
@@ -805,8 +814,11 @@
         private final boolean isScalable;
         private final int devicePaddingId;
         private final int mWorkspaceSpecsId;
+        private final int mWorkspaceSpecsTwoPanelId;
         private final int mAllAppsSpecsId;
+        private final int mAllAppsSpecsTwoPanelId;
         private final int mFolderSpecsId;
+        private final int mFolderSpecsTwoPanelId;
 
         public GridOption(Context context, AttributeSet attrs) {
             TypedArray a = context.obtainStyledAttributes(
@@ -871,14 +883,26 @@
             if (FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE.get()) {
                 mWorkspaceSpecsId = a.getResourceId(
                         R.styleable.GridDisplayOption_workspaceSpecsId, INVALID_RESOURCE_HANDLE);
+                mWorkspaceSpecsTwoPanelId = a.getResourceId(
+                        R.styleable.GridDisplayOption_workspaceSpecsTwoPanelId,
+                        INVALID_RESOURCE_HANDLE);
                 mAllAppsSpecsId = a.getResourceId(
                         R.styleable.GridDisplayOption_allAppsSpecsId, INVALID_RESOURCE_HANDLE);
+                mAllAppsSpecsTwoPanelId = a.getResourceId(
+                        R.styleable.GridDisplayOption_allAppsSpecsTwoPanelId,
+                        INVALID_RESOURCE_HANDLE);
                 mFolderSpecsId = a.getResourceId(
                         R.styleable.GridDisplayOption_folderSpecsId, INVALID_RESOURCE_HANDLE);
+                mFolderSpecsTwoPanelId = a.getResourceId(
+                        R.styleable.GridDisplayOption_folderSpecsTwoPanelId,
+                        INVALID_RESOURCE_HANDLE);
             } else {
                 mWorkspaceSpecsId = INVALID_RESOURCE_HANDLE;
+                mWorkspaceSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
                 mAllAppsSpecsId = INVALID_RESOURCE_HANDLE;
+                mAllAppsSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
                 mFolderSpecsId = INVALID_RESOURCE_HANDLE;
+                mFolderSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
             }
 
             int inlineForRotation = a.getInt(R.styleable.GridDisplayOption_inlineQsb,
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 5f3d27c..fd8f668 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -102,6 +102,9 @@
     private LoaderTask mLoaderTask;
     private boolean mIsLoaderTaskRunning;
 
+    // only allow this once per reboot to reload work apps
+    private boolean mShouldReloadWorkProfile = true;
+
     // Indicates whether the current model data is valid or not.
     // We start off with everything not loaded. After that, we assume that
     // our monitoring of the package manager provides all updates and we never
@@ -308,17 +311,19 @@
      */
     public void onUserEvent(UserHandle user, String action) {
         if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
+                && mShouldReloadWorkProfile) {
+            mShouldReloadWorkProfile = false;
+            forceReload();
+        } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
                 || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
+            mShouldReloadWorkProfile = false;
             enqueueModelUpdateTask(new PackageUpdatedTask(
                     PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user));
-        }
-
-        if (UserCache.ACTION_PROFILE_LOCKED.equals(action)
+        } else if (UserCache.ACTION_PROFILE_LOCKED.equals(action)
                 || UserCache.ACTION_PROFILE_UNLOCKED.equals(action)) {
             enqueueModelUpdateTask(new UserLockStateChangedTask(
                     user, UserCache.ACTION_PROFILE_UNLOCKED.equals(action)));
-        }
-        if (UserCache.ACTION_PROFILE_ADDED.equals(action)
+        } else if (UserCache.ACTION_PROFILE_ADDED.equals(action)
                 || UserCache.ACTION_PROFILE_REMOVED.equals(action)) {
             forceReload();
         }
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 1e2447a..fcc2fc1 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -156,6 +156,7 @@
     public static final String PERMANENT_DIAG_TAG = "TaplTarget";
     public static final String TWO_TASKBAR_LONG_CLICKS = "b/262282528";
     public static final String FLAKY_ACTIVITY_COUNT = "b/260260325";
+    public static final String FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP = "b/286084688";
     public static final String ICON_MISSING = "b/282963545";
     public static final String LAUNCH_SPLIT_PAIR = "b/288939273";
 
diff --git a/tests/src/com/android/launcher3/tapl/TaplUtilityTests.java b/tests/src/com/android/launcher3/tapl/TaplUtilityTests.java
new file mode 100644
index 0000000..15db1d8
--- /dev/null
+++ b/tests/src/com/android/launcher3/tapl/TaplUtilityTests.java
@@ -0,0 +1,38 @@
+/*
+ * 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.tapl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class TaplUtilityTests {
+
+    @Test
+    public void testNewStringWithRegex() {
+        assertTrue(AppIcon.makeMultilinePattern("Play Store")
+                .matcher("Play Store has 7 notifications").matches());
+        assertTrue(AppIcon.makeMultilinePattern("Play Store")
+                .matcher("Play  Store!").matches());
+        assertFalse(AppIcon.makeMultilinePattern("Play Store")
+                .matcher("play  store").matches());
+        assertFalse(AppIcon.makeMultilinePattern("Play Store")
+                .matcher("").matches());
+        assertTrue(AppIcon.makeMultilinePattern("Play Store")
+                .matcher("Play \n Store").matches());
+    }
+}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index f061fab..b1b3baa 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -100,7 +100,7 @@
 
     private static boolean sDumpWasGenerated = false;
     private static boolean sActivityLeakReported = false;
-    private static boolean sSeenKeygard = false;
+    private static boolean sSeenKeyguard = false;
 
     private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
 
@@ -260,9 +260,9 @@
     }
 
     private static void verifyKeyguardInvisible() {
-        final boolean keyguardAlreadyVisible = sSeenKeygard;
+        final boolean keyguardAlreadyVisible = sSeenKeyguard;
 
-        sSeenKeygard = sSeenKeygard
+        sSeenKeyguard = sSeenKeyguard
                 || !TestHelpers.wait(
                 Until.gone(By.res(SYSTEMUI_PACKAGE, "keyguard_status_view")), 60000);
 
@@ -270,7 +270,7 @@
                 "Keyguard is visible, which is likely caused by a crash in SysUI, seeing keyguard"
                         + " for the first time = "
                         + !keyguardAlreadyVisible,
-                sSeenKeygard);
+                sSeenKeyguard);
     }
 
     @After
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 0d63a68..b67478f 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -683,8 +683,8 @@
         HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
         allApps.freeze();
         try {
-            HomeAppIcon icon = allApps.getAppIcon(APP_NAME);
-            assertEquals("Wrong app icon name.", icon.getIconName(), APP_NAME);
+            // getAppIcon() already verifies that the icon is not null and is the correct icon name.
+            allApps.getAppIcon(APP_NAME);
         } finally {
             allApps.unfreeze();
         }
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
index 7ba0b53..8e5e9cc 100644
--- a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -147,9 +147,8 @@
                 for (int i = parent.getChildCount() - 1; i >= 0; i--) {
                     viewQueue.add(parent.getChildAt(i));
                 }
-            } else if (view instanceof BubbleTextView) {
-                BubbleTextView btv = (BubbleTextView) view;
-                if (title.equals(btv.getText())) {
+            } else if (view instanceof BubbleTextView btv) {
+                if (title.equals(btv.getContentDescription().toString())) {
                     icon = btv;
                     break;
                 }
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 399abc7..23d09d4 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -210,6 +210,9 @@
     public AppIcon getAppIcon(String appName) {
         AppIcon appIcon = tryGetAppIcon(appName);
         mLauncher.assertNotNull("Unable to scroll to a clickable icon: " + appName, appIcon);
+        // appIcon.getAppName() checks for content description, so it is possible that it can have
+        // trailing words. So check if the content description contains the appName.
+        mLauncher.assertTrue("Wrong app icon name.", appIcon.getAppName().contains(appName));
         return appIcon;
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 0a0cf07..85098c8 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -37,10 +37,14 @@
     }
 
     static BySelector getAppIconSelector(String appName, LauncherInstrumentation launcher) {
-        return By.clazz(TextView.class).textContains(appName)
+        return By.clazz(TextView.class).desc(makeMultilinePattern(appName))
                 .pkg(launcher.getLauncherPackageName());
     }
 
+    static BySelector getMenuItemSelector(String text, LauncherInstrumentation launcher) {
+        return By.clazz(TextView.class).text(text).pkg(launcher.getLauncherPackageName());
+    }
+
     static BySelector getAnyAppIconSelector() {
         return By.clazz(TextView.class);
     }
@@ -94,4 +98,24 @@
     public String getIconName() {
         return getObject().getText();
     }
+
+    /**
+     * Return the app name of a icon by the content description. This should be used when trying to
+     * get the name of an app where the text of it is multiline.
+     */
+    @NonNull
+    String getAppName() {
+        return getObject().getContentDescription();
+    }
+
+    /**
+     * Create a regular expression pattern that matches strings starting with the app name, where
+     * spaces in the app name are replaced with zero or more occurrences of the "\s" character
+     * (which represents a whitespace character in regular expressions), followed by any characters
+     * after the app name.
+     */
+    static Pattern makeMultilinePattern(String appName) {
+        return Pattern.compile(appName.replaceAll("\\s+", "\\\\s*") + ".*",
+                Pattern.DOTALL);
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
index 667290f..bbcc6a8 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
@@ -50,7 +50,7 @@
      */
     public AppIconMenuItem getMenuItem(String shortcutText) {
         final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
-                AppIcon.getAppIconSelector(shortcutText, mLauncher));
+                AppIcon.getMenuItemSelector(shortcutText, mLauncher));
         return createMenuItem(menuItem);
     }
 
@@ -59,7 +59,7 @@
      */
     public SplitScreenMenuItem getSplitScreenMenuItem() {
         final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
-                AppIcon.getAppIconSelector("Split screen", mLauncher));
+                AppIcon.getMenuItemSelector("Split screen", mLauncher));
         return new SplitScreenMenuItem(mLauncher, menuItem);
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 3395bbf..b929293 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -99,15 +99,17 @@
     private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 15;
     private static final int GESTURE_STEP_MS = 16;
 
-    static final Pattern EVENT_TOUCH_DOWN = getTouchEventPattern("ACTION_DOWN");
-    static final Pattern EVENT_TOUCH_UP = getTouchEventPattern("ACTION_UP");
-    private static final Pattern EVENT_TOUCH_CANCEL = getTouchEventPattern("ACTION_CANCEL");
+    static final Pattern EVENT_TOUCH_DOWN = getTouchEventPatternWithPointerCount("ACTION_DOWN");
+    static final Pattern EVENT_TOUCH_UP = getTouchEventPatternWithPointerCount("ACTION_UP");
+    private static final Pattern EVENT_TOUCH_CANCEL = getTouchEventPatternWithPointerCount(
+            "ACTION_CANCEL");
     static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
     static final Pattern EVENT_START = Pattern.compile("start:");
 
     static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
     static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP");
-    static final Pattern EVENT_TOUCH_CANCEL_TIS = getTouchEventPatternTIS("ACTION_CANCEL");
+    static final Pattern EVENT_TOUCH_CANCEL_TIS = getTouchEventPattern(
+            "TouchInteractionService.onInputEvent", "ACTION_CANCEL");
     static final Pattern EVENT_HOVER_ENTER_TIS = getTouchEventPatternTIS("ACTION_HOVER_ENTER");
     static final Pattern EVENT_HOVER_EXIT_TIS = getTouchEventPatternTIS("ACTION_HOVER_EXIT");
     static final Pattern EVENT_BUTTON_PRESS_TIS = getTouchEventPatternTIS("ACTION_BUTTON_PRESS");
@@ -212,30 +214,35 @@
     private int mPointerCount = 0;
 
     private static Pattern getTouchEventPattern(String prefix, String action) {
-        return getTouchEventPattern(prefix, action, 1);
+        return Pattern.compile(
+                prefix + ": MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
+                        + ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?");
     }
 
-    private static Pattern getTouchEventPattern(String prefix, String action, int pointerCount) {
+    private static Pattern getTouchEventPatternWithPointerCount(String prefix, String action,
+            int pointerCount) {
         return Pattern.compile(
                 prefix + ": MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
                         + ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount="
                         + pointerCount);
     }
 
-    private static Pattern getTouchEventPattern(String action) {
-        return getTouchEventPattern("Touch event", action);
+    private static Pattern getTouchEventPatternWithPointerCount(String action) {
+        return getTouchEventPatternWithPointerCount("Touch event", action, 1);
     }
 
-    private static Pattern getTouchEventPattern(String action, int pointerCount) {
-        return getTouchEventPattern("Touch event", action, pointerCount);
+    private static Pattern getTouchEventPatternWithPointerCount(String action, int pointerCount) {
+        return getTouchEventPatternWithPointerCount("Touch event", action, pointerCount);
     }
 
     private static Pattern getTouchEventPatternTIS(String action) {
-        return getTouchEventPattern("TouchInteractionService.onInputEvent", action);
+        return getTouchEventPatternWithPointerCount("TouchInteractionService.onInputEvent", action,
+                1);
     }
 
     private static Pattern getTouchEventPatternTIS(String action, int pointerCount) {
-        return getTouchEventPattern("TouchInteractionService.onInputEvent", action, pointerCount);
+        return getTouchEventPatternWithPointerCount("TouchInteractionService.onInputEvent", action,
+                pointerCount);
     }
 
     private static Pattern getKeyEventPattern(String action, String keyCode) {
@@ -1814,11 +1821,14 @@
                         && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
                         && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
                         && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
-                    expectEvent(TestProtocol.SEQUENCE_MAIN,
-                            getTouchEventPattern("ACTION_POINTER_DOWN", mPointerCount));
+                    expectEvent(TestProtocol.SEQUENCE_MAIN, getTouchEventPatternWithPointerCount(
+                            "ACTION_POINTER_DOWN", mPointerCount));
                 }
-                expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
-                        "ACTION_POINTER_DOWN", mPointerCount));
+                if (hasTIS && (isTrackpadGestureEnabled()
+                        || getNavigationModel() != NavigationModel.THREE_BUTTON)) {
+                    expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
+                            "ACTION_POINTER_DOWN", mPointerCount));
+                }
                 pointerCount = mPointerCount;
                 break;
             case MotionEvent.ACTION_POINTER_UP:
@@ -1826,14 +1836,17 @@
                         && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
                         && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
                         && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
-                    expectEvent(TestProtocol.SEQUENCE_MAIN,
-                            getTouchEventPattern("ACTION_POINTER_UP", mPointerCount));
+                    expectEvent(TestProtocol.SEQUENCE_MAIN, getTouchEventPatternWithPointerCount(
+                            "ACTION_POINTER_UP", mPointerCount));
                 }
                 // When the gesture is handled outside, it's cancelled within launcher.
-                if (gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
-                        && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
-                    expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
-                            "ACTION_POINTER_UP", mPointerCount));
+                if (hasTIS && (isTrackpadGestureEnabled()
+                        || getNavigationModel() != NavigationModel.THREE_BUTTON)) {
+                    if (gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
+                            && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
+                        expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
+                                "ACTION_POINTER_UP", mPointerCount));
+                    }
                 }
                 mPointerCount--;
                 break;