From 9fee3fd37966f9c30755ba15d4772b651e553e15 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Wed, 1 Dec 2021 18:43:10 +0000 Subject: [PATCH 1/5] Allow column size of search container to be configured - Added numSearchContainerColumns in grid-option to control search container's width, defaults to numColumns if not specified Bug: 210127246 Test: manual Change-Id: I0c2594f0eeab8844dcff9468e603282a09fae0bd --- res/values/attrs.xml | 2 ++ res/xml/device_profiles.xml | 1 + src/com/android/launcher3/DeviceProfile.java | 4 +++- src/com/android/launcher3/InvariantDeviceProfile.java | 9 +++++++-- src/com/android/launcher3/Workspace.java | 4 ++-- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 08570eb7c2..f96d331dfa 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -133,6 +133,8 @@ + + diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml index b4bb43e9a9..90bf165dc2 100644 --- a/res/xml/device_profiles.xml +++ b/res/xml/device_profiles.xml @@ -137,6 +137,7 @@ launcher:name="6_by_5" launcher:numRows="5" launcher:numColumns="6" + launcher:numSearchContainerColumns="3" launcher:numFolderRows="3" launcher:numFolderColumns="3" launcher:numHotseatIcons="6" diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index f772453c82..6261b01de9 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -1057,8 +1057,10 @@ public class DeviceProfile { writer.println(prefix + "\tisScalableGrid:" + isScalableGrid); - writer.println(prefix + "\tinv.numColumns: " + inv.numColumns); writer.println(prefix + "\tinv.numRows: " + inv.numRows); + writer.println(prefix + "\tinv.numColumns: " + inv.numColumns); + writer.println(prefix + "\tinv.numSearchContainerColumns: " + + inv.numSearchContainerColumns); writer.println(prefix + "\tminCellSize: " + inv.minCellSize[mTypeIndex] + "dp"); diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index ff7a90cb2c..6cb4475794 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -106,6 +106,7 @@ public class InvariantDeviceProfile { */ public int numRows; public int numColumns; + public int numSearchContainerColumns; /** * Number of icons per row and column in the folder. @@ -300,6 +301,7 @@ public class InvariantDeviceProfile { GridOption closestProfile = displayOption.grid; numRows = closestProfile.numRows; numColumns = closestProfile.numColumns; + numSearchContainerColumns = closestProfile.numSearchContainerColumns; dbFile = closestProfile.dbFile; defaultLayoutId = closestProfile.defaultLayoutId; demoModeLayoutId = closestProfile.demoModeLayoutId; @@ -393,8 +395,8 @@ public class InvariantDeviceProfile { private Object[] toModelState() { return new Object[]{ - numColumns, numRows, numDatabaseHotseatIcons, iconBitmapSize, fillResIconDpi, - numDatabaseAllAppsColumns, dbFile}; + numColumns, numRows, numSearchContainerColumns, numDatabaseHotseatIcons, + iconBitmapSize, fillResIconDpi, numDatabaseAllAppsColumns, dbFile}; } private void onConfigChanged(Context context) { @@ -671,6 +673,7 @@ public class InvariantDeviceProfile { public final String name; public final int numRows; public final int numColumns; + public final int numSearchContainerColumns; public final boolean isEnabled; private final int numFolderRows; @@ -697,6 +700,8 @@ public class InvariantDeviceProfile { name = a.getString(R.styleable.GridDisplayOption_name); numRows = a.getInt(R.styleable.GridDisplayOption_numRows, 0); numColumns = a.getInt(R.styleable.GridDisplayOption_numColumns, 0); + numSearchContainerColumns = a.getInt( + R.styleable.GridDisplayOption_numSearchContainerColumns, numColumns); dbFile = a.getString(R.styleable.GridDisplayOption_dbFile); defaultLayoutId = a.getResourceId(deviceType == TYPE_MULTI_DISPLAY && a.hasValue( diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 281dfea492..65006ff87f 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -585,8 +585,8 @@ public class Workspace extends PagedView int cellVSpan = FeatureFlags.EXPANDED_SMARTSPACE.get() ? EXPANDED_SMARTSPACE_HEIGHT : DEFAULT_SMARTSPACE_HEIGHT; - CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, firstPage.getCountX(), - cellVSpan); + int cellHSpan = mLauncher.getDeviceProfile().inv.numSearchContainerColumns; + CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, cellHSpan, cellVSpan); lp.canReorder = false; if (!firstPage.addViewToCellLayout(mQsb, 0, R.id.search_container_workspace, lp, true)) { Log.e(TAG, "Failed to add to item at (0, 0) to CellLayout"); From 4a2732da037914db594373b21bce7e149214eeae Mon Sep 17 00:00:00 2001 From: Jon Spivack Date: Thu, 16 Dec 2021 16:23:12 -0800 Subject: [PATCH 2/5] AppSharing: Better handling of Work Profiles This change improves the Work Profile use case in two ways: 1. When sharing is disabled for the profile, the Share App button is grayed out, and an appropriate message is displayed if the user taps it. 2. When sharing is enabled for the profile, it actually works. Bug: 175159046 Bug: 210168826 Test: Manual (toggled DISALLOW_BLUETOOTH_SHARING via Test DPC on local device) Test: m -j RunLauncherGoGoogleRoboTests ROBOTEST_FILTER=com.android.launcher3.AppSharingTest Change-Id: Id7ba8efc587d0b94aa1f9b2004bf45254b39f992 --- .../src/com/android/launcher3/AppSharing.java | 30 +++++++++++++++---- .../model/AppShareabilityManager.java | 2 +- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java index 7c66f6e105..c252fba728 100644 --- a/go/quickstep/src/com/android/launcher3/AppSharing.java +++ b/go/quickstep/src/com/android/launcher3/AppSharing.java @@ -22,6 +22,9 @@ import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Process; +import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -98,14 +101,19 @@ public final class AppSharing { * The Share App system shortcut, used to initiate p2p sharing of a given app */ public final class Share extends SystemShortcut { - private PopupDataProvider mPopupDataProvider; + private final PopupDataProvider mPopupDataProvider; + private final boolean mSharingEnabledForUser; public Share(Launcher target, ItemInfo itemInfo) { super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo); mPopupDataProvider = target.getPopupDataProvider(); - if (ENABLE_SHAREABILITY_CHECK) { - mShareabilityMgr = AppShareabilityManager.INSTANCE.get(target); + mSharingEnabledForUser = bluetoothSharingEnabled(target); + if (!mSharingEnabledForUser) { + setEnabled(false); + } else if (ENABLE_SHAREABILITY_CHECK) { + mShareabilityMgr = + AppShareabilityManager.INSTANCE.get(target.getApplicationContext()); checkShareability(/* requestUpdateIfUnknown */ true); } } @@ -144,7 +152,12 @@ public final class AppSharing { sendIntent.setType(APP_MIME_TYPE); sendIntent.setComponent(ComponentName.unflattenFromString(mSharingComponent)); - mTarget.startActivitySafely(view, sendIntent, mItemInfo); + UserHandle user = mItemInfo.user; + if (user != null && !user.equals(Process.myUserHandle())) { + mTarget.startActivityAsUser(sendIntent, user); + } else { + mTarget.startActivitySafely(view, sendIntent, mItemInfo); + } AbstractFloatingView.closeAllOpenViews(mTarget); } @@ -170,8 +183,15 @@ public final class AppSharing { } } + private boolean bluetoothSharingEnabled(Context context) { + return !context.getSystemService(UserManager.class) + .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH_SHARING, mItemInfo.user); + } + private void showCannotShareToast(Context context) { - CharSequence text = context.getText(R.string.toast_p2p_app_not_shareable); + CharSequence text = (mSharingEnabledForUser) + ? context.getText(R.string.toast_p2p_app_not_shareable) + : context.getText(R.string.blocked_by_policy); int duration = Toast.LENGTH_SHORT; Toast.makeText(context, text, duration).show(); } diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java index cf80c35972..0d0f700b39 100644 --- a/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java +++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java @@ -47,7 +47,7 @@ import java.util.function.Consumer; * Each app's status is retrieved from the Play Store's API. Statuses are cached in order * to limit extraneous calls to that API (which can be time-consuming). */ -public final class AppShareabilityManager { +public class AppShareabilityManager { @Retention(SOURCE) @IntDef({ ShareabilityStatus.UNKNOWN, From c09012766b7a0b04931876df09e62655c3eff87f Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Thu, 6 Jan 2022 13:26:11 -0800 Subject: [PATCH 3/5] Don't show split option if device in "Lock task mode" fixes: 199342537 Change-Id: Id212cce20b792fb8b16e9fa8eca4635773ae5ea7 --- .../src/com/android/quickstep/TaskOverlayFactory.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java index 02468497bb..276e1c2a6f 100644 --- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java @@ -23,6 +23,7 @@ import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBN import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED; import android.annotation.SuppressLint; +import android.app.ActivityManager; import android.content.Context; import android.graphics.Insets; import android.graphics.Matrix; @@ -54,6 +55,7 @@ import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView.TaskIdAttributeContainer; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; +import com.android.systemui.shared.system.ActivityManagerWrapper; import java.util.ArrayList; import java.util.List; @@ -115,8 +117,9 @@ public class TaskOverlayFactory implements ResourceBasedOverride { * Does NOT add split options in the following scenarios: * * The taskView to add split options is already showing split screen tasks * * There aren't at least 2 tasks in overview to show split options for + * * Device is in "Lock task mode" * * The taskView to show split options for is the focused task AND we haven't started - * scrolling in overview (if we haven't scrolled, there's a split overview action so + * scrolling in overview (if we haven't scrolled, there's a split overview action button so * we don't need this menu option) */ private static void addSplitOptions(List outShortcuts, @@ -130,7 +133,11 @@ public class TaskOverlayFactory implements ResourceBasedOverride { boolean isFocusedTask = deviceProfile.overviewShowAsGrid && taskView.isFocusedTask(); boolean isTaskInExpectedScrollPosition = recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView)); - if (taskViewHasMultipleTasks || notEnoughTasksToSplit || + ActivityManager activityManager = + (ActivityManager) taskView.getContext().getSystemService(Context.ACTIVITY_SERVICE); + boolean isLockTaskMode = activityManager.isInLockTaskMode(); + + if (taskViewHasMultipleTasks || notEnoughTasksToSplit || isLockTaskMode || (isFocusedTask && isTaskInExpectedScrollPosition)) { return; } From 3d8cfd22a1a69f3ae051bfff27ff7c6110691523 Mon Sep 17 00:00:00 2001 From: Andras Kloczl Date: Fri, 10 Dec 2021 13:53:59 +0000 Subject: [PATCH 4/5] Two panel workspace TAPL follow up CL - TODO: enable test in portrait Test: TwoPanelWorkspaceTest Former CL: http://ag/16357467 Bug: 197631877 Change-Id: I35c326b7a6c612d2fb66c8b94b810f5131fd58d8 --- .../ui/workspace/TwoPanelWorkspaceTest.java | 209 ++++++++++++------ .../com/android/launcher3/tapl/Workspace.java | 32 ++- 2 files changed, 162 insertions(+), 79 deletions(-) diff --git a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java index b048cd4d43..122a130f7b 100644 --- a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java +++ b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java @@ -19,6 +19,7 @@ package com.android.launcher3.ui.workspace; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; @@ -47,20 +48,12 @@ import java.util.stream.Collectors; @RunWith(AndroidJUnit4.class) public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { - Workspace mWorkspace; - @Before public void setUp() throws Exception { super.setUp(); TaplTestsLauncher3.initialize(this); - mWorkspace = mLauncher.getWorkspace(); - } - @Test - public void testDragIconToRightPanel() { - if (!mLauncher.isTwoPanels()) { - return; - } + assumeTrue(mLauncher.isTwoPanels()); // Pre verifying the screens executeOnLauncher(launcher -> { @@ -68,8 +61,15 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { assertItemsOnPage(launcher, 0, "Play Store", "Maps"); assertPageEmpty(launcher, 1); }); + } - mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Chrome"), 1); + @Test + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape + public void testDragIconToRightPanel() { + Workspace workspace = mLauncher.getWorkspace(); + + workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 1); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1); @@ -79,19 +79,67 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { } @Test - public void testDragIconToPage2() { - if (!mLauncher.isTwoPanels()) { - return; - } + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape + public void testSinglePageDragIconWhenMultiplePageScrollingIsPossible() { + Workspace workspace = mLauncher.getWorkspace(); + + workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 2); + + workspace.flingBackward(); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3); - // Pre verifying the screens executeOnLauncher(launcher -> { - assertPagesExist(launcher, 0, 1); - assertItemsOnPage(launcher, 0, "Play Store", "Maps"); + assertPagesExist(launcher, 0, 1, 2, 3); + assertItemsOnPage(launcher, 0, "Play Store"); assertPageEmpty(launcher, 1); + assertItemsOnPage(launcher, 2, "Chrome"); + assertItemsOnPage(launcher, 3, "Maps"); }); - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3); + + executeOnLauncher(launcher -> { + assertPagesExist(launcher, 0, 1, 2, 3, 4, 5); + assertItemsOnPage(launcher, 0, "Play Store"); + assertPageEmpty(launcher, 1); + assertItemsOnPage(launcher, 2, "Chrome"); + assertPageEmpty(launcher, 3); + assertPageEmpty(launcher, 4); + assertItemsOnPage(launcher, 5, "Maps"); + }); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1); + + executeOnLauncher(launcher -> { + assertPagesExist(launcher, 0, 1, 2, 3); + assertItemsOnPage(launcher, 0, "Play Store"); + assertPageEmpty(launcher, 1); + assertItemsOnPage(launcher, 2, "Chrome"); + assertItemsOnPage(launcher, 3, "Maps"); + }); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1); + + workspace.flingForward(); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Chrome"), -2); + + executeOnLauncher(launcher -> { + assertPagesExist(launcher, 0, 1); + assertItemsOnPage(launcher, 0, "Chrome", "Play Store"); + assertItemsOnPage(launcher, 1, "Maps"); + }); + } + + @Test + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape + public void testDragIconToPage2() { + Workspace workspace = mLauncher.getWorkspace(); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 2, 3); @@ -103,19 +151,12 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { } @Test + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape public void testDragIconToPage3() { - if (!mLauncher.isTwoPanels()) { - return; - } + Workspace workspace = mLauncher.getWorkspace(); - // Pre verifying the screens - executeOnLauncher(launcher -> { - assertPagesExist(launcher, 0, 1); - assertItemsOnPage(launcher, 0, "Play Store", "Maps"); - assertPageEmpty(launcher, 1); - }); - - mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Phone"), 3); + workspace.dragIcon(workspace.getHotseatAppIcon("Phone"), 3); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 2, 3); @@ -126,22 +167,61 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { }); } - @Test - public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() { - if (!mLauncher.isTwoPanels()) { - return; - } + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape + public void testMultiplePageDragIcon() { + Workspace workspace = mLauncher.getWorkspace(); + + workspace.dragIcon(workspace.getHotseatAppIcon("Messages"), 2); + + workspace.flingBackward(); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 5); - // Pre verifying the screens executeOnLauncher(launcher -> { - assertPagesExist(launcher, 0, 1); - assertItemsOnPage(launcher, 0, "Play Store", "Maps"); + assertPagesExist(launcher, 0, 1, 2, 3, 4, 5); + assertItemsOnPage(launcher, 0, "Play Store"); assertPageEmpty(launcher, 1); + assertItemsOnPage(launcher, 2, "Messages"); + assertPageEmpty(launcher, 3); + assertPageEmpty(launcher, 4); + assertItemsOnPage(launcher, 5, "Maps"); }); - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 3); - mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Chrome"), 0); + workspace.flingBackward(); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Messages"), 4); + + executeOnLauncher(launcher -> { + assertPagesExist(launcher, 0, 1, 4, 5, 6, 7); + assertItemsOnPage(launcher, 0, "Play Store"); + assertPageEmpty(launcher, 1); + assertPageEmpty(launcher, 4); + assertItemsOnPage(launcher, 5, "Maps"); + assertItemsOnPage(launcher, 6, "Messages"); + assertPageEmpty(launcher, 7); + }); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Messages"), -3); + + executeOnLauncher(launcher -> { + assertPagesExist(launcher, 0, 1, 4, 5); + assertItemsOnPage(launcher, 0, "Play Store"); + assertItemsOnPage(launcher, 1, "Messages"); + assertPageEmpty(launcher, 4); + assertItemsOnPage(launcher, 5, "Maps"); + }); + } + + @Test + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape + public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() { + Workspace workspace = mLauncher.getWorkspace(); + + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3); + workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 0); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 2, 3); @@ -151,7 +231,7 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { assertItemsOnPage(launcher, 3, "Maps"); }); - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), -1); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 2, 3); @@ -163,8 +243,8 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { // Move Chrome to the right panel as well, to make sure pages are not deleted whichever // page is the empty one - mWorkspace.flingForward(); - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Chrome"), 1); + workspace.flingForward(); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Chrome"), 1); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 2, 3); @@ -175,22 +255,14 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { }); } - @Test + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape public void testEmptyPagesGetRemovedIfBothPagesAreEmpty() { - if (!mLauncher.isTwoPanels()) { - return; - } + Workspace workspace = mLauncher.getWorkspace(); - // Pre verifying the screens - executeOnLauncher(launcher -> { - assertPagesExist(launcher, 0, 1); - assertItemsOnPage(launcher, 0, "Play Store", "Maps"); - assertPageEmpty(launcher, 1); - }); - - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Play Store"), 2); - mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Camera"), 1); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Play Store"), 2); + workspace.dragIcon(workspace.getHotseatAppIcon("Camera"), 1); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 2, 3); @@ -200,9 +272,9 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { assertItemsOnPage(launcher, 3, "Camera"); }); - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Camera"), -1); - mWorkspace.flingForward(); - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Play Store"), -2); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Camera"), -1); + workspace.flingForward(); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Play Store"), -2); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1); @@ -212,20 +284,13 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { } @Test + // TODO(b/197631877) Enable in portrait. + // @PortraitLandscape public void testMiddleEmptyPagesGetRemoved() { - if (!mLauncher.isTwoPanels()) { - return; - } + Workspace workspace = mLauncher.getWorkspace(); - // Pre verifying the screens - executeOnLauncher(launcher -> { - assertPagesExist(launcher, 0, 1); - assertItemsOnPage(launcher, 0, "Play Store", "Maps"); - assertPageEmpty(launcher, 1); - }); - - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2); - mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Messages"), 3); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2); + workspace.dragIcon(workspace.getHotseatAppIcon("Messages"), 3); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 2, 3, 4, 5); @@ -237,8 +302,8 @@ public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest { assertItemsOnPage(launcher, 5, "Messages"); }); - mWorkspace.flingBackward(); - mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2); + workspace.flingBackward(); + workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2); executeOnLauncher(launcher -> { assertPagesExist(launcher, 0, 1, 4, 5); diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 3f0d7fdc00..e457354289 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -16,6 +16,8 @@ package com.android.launcher3.tapl; +import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_SCROLLED; + import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL; @@ -165,15 +167,22 @@ public final class Workspace extends Home { } /** - * Drags an icon to the (currentPage + pageDelta) page if the page already exists. - * If the target page doesn't exist, the icon will be put onto an existing page that is the - * closest to the target page. + * Drags an icon to the (currentPage + pageDelta) page. + * If the target page doesn't exist yet, a new page will be created. + * In case the target page can't be created (e.g. existing pages are 0, 1, current: 0, + * pageDelta: 3, the latest page that can be created is 2) the icon will be dragged onto the + * page that can be created and is closest to the target page. * * @param appIcon - icon to drag. * @param pageDelta - how many pages should the icon be dragged from the current page. - * It can be a negative value. + * It can be a negative value. currentPage + pageDelta should be greater + * than or equal to 0. */ public void dragIcon(AppIcon appIcon, int pageDelta) { + if (mHotseat.getVisibleBounds().height() > mHotseat.getVisibleBounds().width()) { + throw new UnsupportedOperationException( + "dragIcon does NOT support dragging when the hotseat is on the side."); + } try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { final UiObject2 workspace = verifyActiveContainer(); try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( @@ -338,9 +347,11 @@ public final class Workspace extends Home { while (targetDest.x > displayX || targetDest.x < 0) { int edgeX = targetDest.x > 0 ? displayX : 0; Point screenEdge = new Point(edgeX, targetDest.y); - launcher.movePointer(dragStart, screenEdge, DEFAULT_DRAG_STEPS, isDecelerating, - downTime, true, LauncherInstrumentation.GestureScope.INSIDE); - launcher.waitForIdle(); // Wait for the page change to happen + Point finalDragStart = dragStart; + executeAndWaitForPageScroll(launcher, + () -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS, + isDecelerating, downTime, true, + LauncherInstrumentation.GestureScope.INSIDE)); targetDest.x += displayX * (targetDest.x > 0 ? -1 : 1); dragStart = screenEdge; } @@ -353,6 +364,13 @@ public final class Workspace extends Home { } } + private static void executeAndWaitForPageScroll(LauncherInstrumentation launcher, + Runnable command) { + launcher.executeAndWaitForEvent(command, + event -> event.getEventType() == TYPE_VIEW_SCROLLED, + () -> "Page scroll didn't happen", "Scrolling page"); + } + /** * Flings to get to screens on the right. Waits for scrolling and a possible overscroll * recoil to complete. From 688148ac693a17f248c021319eae2b6a24e0dc66 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 7 Jan 2022 18:32:14 +0000 Subject: [PATCH 5/5] Add null check when logging quick switch Test: none Fixes: 209993127 Change-Id: I927f8969cf5ef3759b501fe1ada4d3b061b53d06 --- quickstep/src/com/android/quickstep/views/TaskView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 9887630e7d..6a2c997e05 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -470,7 +470,9 @@ public class TaskView extends FrameLayout implements Reusable { stubInfo.user = componentKey.user; stubInfo.intent = new Intent().setComponent(componentKey.componentName); stubInfo.title = task.title; - stubInfo.screenId = getRecentsView().indexOfChild(this); + if (getRecentsView() != null) { + stubInfo.screenId = getRecentsView().indexOfChild(this); + } return stubInfo; }