diff options
29 files changed, 200 insertions, 76 deletions
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeStatesTouchController.java b/go/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeStatesTouchController.java index 1ccd7d79a..66aec4050 100644 --- a/go/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeStatesTouchController.java +++ b/go/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeStatesTouchController.java @@ -64,7 +64,7 @@ public final class LandscapeStatesTouchController extends PortraitStatesTouchCon } @Override - protected int getLogContainerTypeForNormalState() { + protected int getLogContainerTypeForNormalState(MotionEvent ev) { return LauncherLogProto.ContainerType.WORKSPACE; } } diff --git a/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java b/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java index 1e449108d..7fd4a9de0 100644 --- a/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java +++ b/go/src/com/android/launcher3/shortcuts/DeepShortcutManager.java @@ -25,6 +25,7 @@ import android.os.Bundle; import android.os.UserHandle; import com.android.launcher3.ItemInfo; +import com.android.launcher3.notification.NotificationKeyData; import java.util.Collections; import java.util.List; @@ -52,6 +53,14 @@ public class DeepShortcutManager { return false; } + public static boolean supportsDeepShortcuts(ItemInfo info) { + return false; + } + + public static String getShortcutIdIfApplicable(ItemInfo info) { + return null; + } + public boolean wasLastCallSuccess() { return false; } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java index 73f328bc1..90911684e 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java @@ -75,7 +75,7 @@ public class OverviewToAllAppsTouchController extends PortraitStatesTouchControl } @Override - protected int getLogContainerTypeForNormalState() { + protected int getLogContainerTypeForNormalState(MotionEvent ev) { return LauncherLogProto.ContainerType.WORKSPACE; } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java index 18b8af4fa..eb571f607 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java @@ -154,7 +154,7 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll } @Override - protected int getLogContainerTypeForNormalState() { + protected int getLogContainerTypeForNormalState(MotionEvent ev) { return LauncherLogProto.ContainerType.NAVBAR; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java index 5e77e0ade..5ebefa337 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java @@ -81,6 +81,7 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple }); factory.onRemoteAnimationReceived(null); factory.createActivityController(RECENTS_LAUNCH_DURATION); + factory.setRecentsAttachedToAppWindow(true, false); mActivity = activity; mRecentsView = mActivity.getOverviewPanel(); return false; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java index 6533c63ef..a94f25d2b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java @@ -99,6 +99,7 @@ public class OverviewCommandHelper { @Override protected void onTransitionComplete() { + // TODO(b/138729100) This doesn't execute first time launcher is run if (mTriggeredFromAltTab) { RecentsView rv = (RecentsView) mHelper.getVisibleRecentsView(); if (rv == null) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java index 83601e617..14083dd95 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationListenerSet.java @@ -23,6 +23,7 @@ import android.util.ArraySet; import com.android.launcher3.Utilities; import com.android.launcher3.util.Preconditions; import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener; +import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RecentsAnimationListener; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; @@ -39,7 +40,7 @@ import androidx.annotation.UiThread; public class RecentsAnimationListenerSet implements RecentsAnimationListener { // The actual app surface is replaced by a screenshot upon recents animation cancelation when - // deferredWithScreenshot is true. Launcher takes the responsibility to clean up this screenshot + // the thumbnailData exists. Launcher takes the responsibility to clean up this screenshot // after app transition is finished. This delay is introduced to cover the app transition // period of time. private final int TRANSITION_DELAY = 100; @@ -90,14 +91,14 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { } @Override - public final void onAnimationCanceled(boolean deferredWithScreenshot) { + public final void onAnimationCanceled(ThumbnailData thumbnailData) { Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> { for (SwipeAnimationListener listener : getListeners()) { listener.onRecentsAnimationCanceled(); } }); // TODO: handle the transition better instead of simply using a transition delay. - if (deferredWithScreenshot) { + if (thumbnailData != null) { MAIN_THREAD_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(), TRANSITION_DELAY); } @@ -109,6 +110,6 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener { public void cancelListener() { mCancelled = true; - onAnimationCanceled(false); + onAnimationCanceled(null); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java index 0605953dc..bb72315d3 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java @@ -46,7 +46,7 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro } @Override - protected int getLogContainerTypeForNormalState() { + protected int getLogContainerTypeForNormalState(MotionEvent ev) { return LauncherLogProto.ContainerType.NAVBAR; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java index a55f36b78..b81edfa4c 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java @@ -147,8 +147,8 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr } @Override - protected int getLogContainerTypeForNormalState() { - return ContainerType.HOTSEAT; + protected int getLogContainerTypeForNormalState(MotionEvent ev) { + return isTouchOverHotseat(mLauncher, ev) ? ContainerType.HOTSEAT : ContainerType.WORKSPACE; } private AnimatorSetBuilder getNormalToOverviewAnimation() { diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 5b38261a4..8a2fef277 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -873,9 +873,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, if (mLauncherCallbacks != null) { mLauncherCallbacks.onStop(); } - - getUserEventDispatcher().logActionCommand(Action.Command.STOP, - mStateManager.getState().containerType, -1); + logStopAndResume(Action.Command.STOP); mAppWidgetHost.setListenIfResumed(false); @@ -901,8 +899,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, private void handleDeferredResume() { if (hasBeenResumed() && !mStateManager.getState().disableInteraction) { - getUserEventDispatcher().logActionCommand(Action.Command.RESUME, - mStateManager.getState().containerType, -1); + logStopAndResume(Action.Command.RESUME); getUserEventDispatcher().startSession(); UiFactory.onLauncherStateOrResumeChanged(this); @@ -929,6 +926,17 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } } + private void logStopAndResume(int command) { + int containerType = mStateManager.getState().containerType; + if (containerType == ContainerType.WORKSPACE && mWorkspace != null) { + getUserEventDispatcher().logActionCommand(command, + containerType, -1, mWorkspace.isOverlayShown() ? -1 : 0); + } else { + getUserEventDispatcher().logActionCommand(command, containerType, -1); + } + + } + protected void onStateSet(LauncherState state) { getAppWidgetHost().setResumed(state == LauncherState.NORMAL); if (mDeferredResumePending) { diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 269a59111..3be91d410 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -85,6 +85,7 @@ import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.pageindicators.WorkspacePageIndicator; import com.android.launcher3.popup.PopupContainerWithArrow; import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.WorkspaceTouchListener; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; @@ -420,6 +421,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator> } // Always enter the spring loaded mode + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TO_WORKSPACE, "Switching to SPRING_LOADED"); + } mLauncher.getStateManager().goToState(SPRING_LOADED); } @@ -1741,6 +1745,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator> public void prepareAccessibilityDrop() { } public void onDrop(final DragObject d, DragOptions options) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TO_WORKSPACE, "Workspace.onDrop"); + } mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter); CellLayout dropTargetLayout = mDropToLayout; @@ -2418,6 +2425,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator> * to add an item to one of the workspace screens. */ private void onDropExternal(final int[] touchXY, final CellLayout cellLayout, DragObject d) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TO_WORKSPACE, "Workspace.onDropExternal"); + } if (d.dragInfo instanceof PendingAddShortcutInfo) { WorkspaceItemInfo si = ((PendingAddShortcutInfo) d.dragInfo) .activityInfo.createWorkspaceItemInfo(); @@ -3251,6 +3261,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator> } } + public boolean isOverlayShown() { + return mOverlayShown; + } + void moveToDefaultScreen() { int page = DEFAULT_PAGE; if (!workspaceInModalState() && getNextPage() != page) { diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index d32dd2eb9..b72fd988a 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -579,6 +579,9 @@ public class DragController implements DragDriver.EventListener, TouchController } private void drop(DropTarget dropTarget, Runnable flingAnimation) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TO_WORKSPACE, "DragController.drop"); + } final int[] coordinates = mCoordinatesTemp; mDragObject.x = coordinates[0]; mDragObject.y = coordinates[1]; diff --git a/src/com/android/launcher3/dragndrop/DragDriver.java b/src/com/android/launcher3/dragndrop/DragDriver.java index 84fc94dd2..bd2a03b6c 100644 --- a/src/com/android/launcher3/dragndrop/DragDriver.java +++ b/src/com/android/launcher3/dragndrop/DragDriver.java @@ -17,10 +17,12 @@ package com.android.launcher3.dragndrop; import android.content.Context; +import android.util.Log; import android.view.DragEvent; import android.view.MotionEvent; import com.android.launcher3.DropTarget.DragObject; +import com.android.launcher3.testing.TestProtocol; /** * Base class for driving a drag/drop operation. @@ -52,6 +54,9 @@ public abstract class DragDriver { mEventListener.onDriverDragMove(ev.getX(), ev.getY()); break; case MotionEvent.ACTION_UP: + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.NO_DRAG_TO_WORKSPACE, "DragDriver.ACTION_UP"); + } mEventListener.onDriverDragMove(ev.getX(), ev.getY()); mEventListener.onDriverDragEnd(ev.getX(), ev.getY()); break; diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java index d81020ef3..c72b07a7f 100644 --- a/src/com/android/launcher3/logging/UserEventDispatcher.java +++ b/src/com/android/launcher3/logging/UserEventDispatcher.java @@ -187,6 +187,14 @@ public class UserEventDispatcher implements ResourceBasedOverride { dstContainerType >=0 ? newContainerTarget(dstContainerType) : null); } + public void logActionCommand(int command, int srcContainerType, int dstContainerType, + int pageIndex) { + Target srcTarget = newContainerTarget(srcContainerType); + srcTarget.pageIndex = pageIndex; + logActionCommand(command, srcTarget, + dstContainerType >=0 ? newContainerTarget(dstContainerType) : null); + } + public void logActionCommand(int command, Target srcTarget, Target dstTarget) { LauncherEvent event = newLauncherEvent(newCommandAction(command), srcTarget); if (command == Action.Command.STOP) { diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java index 2d301ac00..6e4883e41 100644 --- a/src/com/android/launcher3/popup/PopupDataProvider.java +++ b/src/com/android/launcher3/popup/PopupDataProvider.java @@ -38,8 +38,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Predicate; +import java.util.stream.Collectors; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** * Provides data for the popup menu that appears after long-clicking on apps. @@ -129,7 +131,8 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan for (PackageUserKey packageUserKey : mPackageUserToDotInfos.keySet()) { DotInfo prevDot = updatedDots.get(packageUserKey); DotInfo newDot = mPackageUserToDotInfos.get(packageUserKey); - if (prevDot == null) { + if (prevDot == null + || prevDot.getNotificationCount() != newDot.getNotificationCount()) { updatedDots.put(packageUserKey, newDot); } else { // No need to update the dot if it already existed (no visual change). @@ -155,7 +158,7 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan } public int getShortcutCountForItem(ItemInfo info) { - if (!DeepShortcutManager.supportsShortcuts(info)) { + if (!DeepShortcutManager.supportsDeepShortcuts(info)) { return 0; } ComponentName component = info.getTargetComponent(); @@ -167,17 +170,26 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan return count == null ? 0 : count; } - public DotInfo getDotInfoForItem(ItemInfo info) { + public @Nullable DotInfo getDotInfoForItem(@NonNull ItemInfo info) { if (!DeepShortcutManager.supportsShortcuts(info)) { return null; } - - return mPackageUserToDotInfos.get(PackageUserKey.fromItemInfo(info)); + DotInfo dotInfo = mPackageUserToDotInfos.get(PackageUserKey.fromItemInfo(info)); + if (dotInfo == null) { + return null; + } + List<NotificationKeyData> notifications = getNotificationsForItem( + info, dotInfo.getNotificationKeys()); + if (notifications.isEmpty()) { + return null; + } + return dotInfo; } public @NonNull List<NotificationKeyData> getNotificationKeysForItem(ItemInfo info) { DotInfo dotInfo = getDotInfoForItem(info); - return dotInfo == null ? Collections.EMPTY_LIST : dotInfo.getNotificationKeys(); + return dotInfo == null ? Collections.EMPTY_LIST + : getNotificationsForItem(info, dotInfo.getNotificationKeys()); } /** This makes a potentially expensive binder call and should be run on a background thread. */ @@ -226,6 +238,20 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan return null; } + /** + * Returns a list of notifications that are relevant to given ItemInfo. + */ + public static @NonNull List<NotificationKeyData> getNotificationsForItem( + @NonNull ItemInfo info, @NonNull List<NotificationKeyData> notifications) { + String shortcutId = DeepShortcutManager.getShortcutIdIfApplicable(info); + if (shortcutId == null) { + return notifications; + } + return notifications.stream().filter((NotificationKeyData notification) -> + shortcutId.equals(notification.shortcutId) + ).collect(Collectors.toList()); + } + public interface PopupDataChangeListener { PopupDataChangeListener INSTANCE = new PopupDataChangeListener() { }; diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java index 41ab4df7b..5a5fbabac 100644 --- a/src/com/android/launcher3/popup/RemoteActionShortcut.java +++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java @@ -29,11 +29,12 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.ItemInfo; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.userevent.nano.LauncherLogProto; public class RemoteActionShortcut extends SystemShortcut<BaseDraggingActivity> { private static final String TAG = "RemoteActionShortcut"; - private static final boolean DEBUG = false; + private static final boolean DEBUG = Utilities.IS_DEBUG_DEVICE; private final RemoteAction mAction; diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 9846a0427..cb8f811cb 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -79,4 +79,5 @@ public final class TestProtocol { public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing"; public static final String NO_BACKGROUND_TO_OVERVIEW_TAG = "b/138251824"; + public static final String NO_DRAG_TO_WORKSPACE = "b/138729456"; } diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 054534417..c5ba5bab6 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -69,6 +69,7 @@ public abstract class AbstractStateChangeTouchController protected final SwipeDetector.Direction mSwipeDirection; private boolean mNoIntercept; + private boolean mIsLogContainerSet; protected int mStartContainerType; protected LauncherState mStartState; @@ -180,7 +181,7 @@ public abstract class AbstractStateChangeTouchController /** * Returns the container that the touch started from when leaving NORMAL state. */ - protected abstract int getLogContainerTypeForNormalState(); + protected abstract int getLogContainerTypeForNormalState(MotionEvent ev); private boolean reinitCurrentAnimation(boolean reachedToState, boolean isDragTowardPositive) { LauncherState newFromState = mFromState == null ? mLauncher.getStateManager().getState() @@ -231,13 +232,7 @@ public abstract class AbstractStateChangeTouchController @Override public void onDragStart(boolean start) { mStartState = mLauncher.getStateManager().getState(); - if (mStartState == ALL_APPS) { - mStartContainerType = LauncherLogProto.ContainerType.ALLAPPS; - } else if (mStartState == NORMAL) { - mStartContainerType = getLogContainerTypeForNormalState(); - } else if (mStartState == OVERVIEW){ - mStartContainerType = LauncherLogProto.ContainerType.TASKSWITCHER; - } + mIsLogContainerSet = false; if (mCurrentAnimation == null) { mFromState = mStartState; mToState = null; @@ -285,6 +280,21 @@ public abstract class AbstractStateChangeTouchController return true; } + @Override + public boolean onDrag(float displacement, MotionEvent ev) { + if (!mIsLogContainerSet) { + if (mStartState == ALL_APPS) { + mStartContainerType = LauncherLogProto.ContainerType.ALLAPPS; + } else if (mStartState == NORMAL) { + mStartContainerType = getLogContainerTypeForNormalState(ev); + } else if (mStartState == OVERVIEW) { + mStartContainerType = LauncherLogProto.ContainerType.TASKSWITCHER; + } + mIsLogContainerSet = true; + } + return onDrag(displacement); + } + protected void updateProgress(float fraction) { mCurrentAnimation.setPlayFraction(fraction); if (mAtomicComponentsController != null) { diff --git a/src_shortcuts_overrides/com/android/launcher3/shortcuts/DeepShortcutManager.java b/src_shortcuts_overrides/com/android/launcher3/shortcuts/DeepShortcutManager.java index 6b6f70d7b..aec2badf2 100644 --- a/src_shortcuts_overrides/com/android/launcher3/shortcuts/DeepShortcutManager.java +++ b/src_shortcuts_overrides/com/android/launcher3/shortcuts/DeepShortcutManager.java @@ -64,10 +64,26 @@ public class DeepShortcutManager { } public static boolean supportsShortcuts(ItemInfo info) { - boolean isItemPromise = info instanceof WorkspaceItemInfo - && ((WorkspaceItemInfo) info).hasPromiseIconUi(); - return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION - && !info.isDisabled() && !isItemPromise; + return isActive(info) && (isApp(info) || isPinnedShortcut(info)); + } + + public static boolean supportsDeepShortcuts(ItemInfo info) { + return isActive(info) && isApp(info); + } + + public static String getShortcutIdIfApplicable(ItemInfo info) { + return isActive(info) && isPinnedShortcut(info) ? + ShortcutKey.fromItemInfo(info).getId() : null; + } + + private static boolean isApp(ItemInfo info) { + return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; + } + + private static boolean isPinnedShortcut(ItemInfo info) { + return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT + && info.container != ItemInfo.NO_ID + && info instanceof WorkspaceItemInfo; } public boolean wasLastCallSuccess() { @@ -183,6 +199,12 @@ public class DeepShortcutManager { return shortcutIds; } + private static boolean isActive(ItemInfo info) { + boolean isLoading = info instanceof WorkspaceItemInfo + && ((WorkspaceItemInfo) info).hasPromiseIconUi(); + return !isLoading && !info.isDisabled(); + } + /** * Query the system server for all the shortcuts matching the given parameters. * If packageName == null, we query for all shortcuts with the passed flags, regardless of app. diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java index e9dc800e3..bd6ea502e 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java @@ -57,7 +57,7 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { } @Override - protected int getLogContainerTypeForNormalState() { + protected int getLogContainerTypeForNormalState(MotionEvent ev) { return mLauncher.getDragLayer().isEventOverView(mLauncher.getHotseat(), mTouchDownEvent) ? ContainerType.HOTSEAT : ContainerType.WORKSPACE; } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 8dc8cea40..fc19baace 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -38,6 +38,7 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.Until; @@ -330,30 +331,27 @@ public abstract class AbstractLauncherUiTest { } protected void startAppFast(String packageName) { - final Instrumentation instrumentation = getInstrumentation(); - final Intent intent = instrumentation.getContext().getPackageManager(). - getLaunchIntentForPackage(packageName); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - instrumentation.getTargetContext().startActivity(intent); - assertTrue(packageName + " didn't start", - mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), DEFAULT_UI_TIMEOUT)); + startIntent( + getInstrumentation().getContext().getPackageManager().getLaunchIntentForPackage( + packageName), + By.pkg(packageName).depth(0)); } protected void startTestActivity(int activityNumber) { final String packageName = getAppPackageName(); - final Instrumentation instrumentation = getInstrumentation(); - final Intent intent = instrumentation.getContext().getPackageManager(). + final Intent intent = getInstrumentation().getContext().getPackageManager(). getLaunchIntentForPackage(packageName); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setComponent(new ComponentName(packageName, "com.android.launcher3.tests.Activity" + activityNumber)); - instrumentation.getTargetContext().startActivity(intent); - assertTrue(packageName + " didn't start", - mDevice.wait( - Until.hasObject(By.pkg(packageName).text("TestActivity" + activityNumber)), - DEFAULT_UI_TIMEOUT)); + startIntent(intent, By.pkg(packageName).text("TestActivity" + activityNumber)); + } + + private void startIntent(Intent intent, BySelector selector) { + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + getInstrumentation().getTargetContext().startActivity(intent); + assertTrue("App didn't start: " + selector, + mDevice.wait(Until.hasObject(selector), DEFAULT_UI_TIMEOUT)); } public static String resolveSystemApp(String category) { diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 4dab44fad..0c87ab908 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -173,6 +173,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { @Test public void testWorkspace() throws Exception { + mLauncher.enableDebugTracing(); final Workspace workspace = mLauncher.getWorkspace(); // Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there. @@ -190,7 +191,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { launcher -> assertTrue("ensureScrollable didn't make workspace scrollable", isWorkspaceScrollable(launcher))); assertNotNull("ensureScrollable didn't add Chrome app", - workspace.tryGetWorkspaceAppIcon("Chrome")); + workspace.getWorkspaceAppIcon("Chrome")); // Test flinging workspace. workspace.flingBackward(); @@ -206,8 +207,9 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); // Test starting a workspace app. - final AppIcon app = workspace.tryGetWorkspaceAppIcon("Chrome"); + final AppIcon app = workspace.getWorkspaceAppIcon("Chrome"); assertNotNull("No Chrome app in workspace", app); + mLauncher.disableDebugTracing(); } public static void runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { @@ -298,6 +300,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { @Test @PortraitLandscape public void testDragAppIcon() throws Throwable { + mLauncher.enableDebugTracing(); // 1. Open all apps and wait for load complete. // 2. Drag icon to homescreen. // 3. Verify that the icon works on homescreen. @@ -314,11 +317,13 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { "Launcher activity is the top activity; expecting another activity to be the top " + "one", isInBackground(launcher))); + mLauncher.disableDebugTracing(); } @Test @PortraitLandscape public void testDragShortcut() throws Throwable { + mLauncher.enableDebugTracing(); // 1. Open all apps and wait for load complete. // 2. Find the app and long press it to show shortcuts. // 3. Press icon center until shortcuts appear @@ -338,6 +343,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { } finally { allApps.unfreeze(); } + mLauncher.disableDebugTracing(); } public static String getAppPackageName() { diff --git a/tests/src/com/android/launcher3/util/Wait.java b/tests/src/com/android/launcher3/util/Wait.java index 593cce832..899686bd6 100644 --- a/tests/src/com/android/launcher3/util/Wait.java +++ b/tests/src/com/android/launcher3/util/Wait.java @@ -1,6 +1,7 @@ package com.android.launcher3.util; import android.os.SystemClock; +import android.util.Log; import org.junit.Assert; @@ -16,7 +17,9 @@ public class Wait { } public static void atMost(String message, Condition condition, long timeout, long sleepMillis) { - long endTime = SystemClock.uptimeMillis() + timeout; + final long startTime = SystemClock.uptimeMillis(); + long endTime = startTime + timeout; + Log.d("Wait", "atMost: " + startTime + " - " + endTime); while (SystemClock.uptimeMillis() < endTime) { try { if (condition.isTrue()) { @@ -36,6 +39,7 @@ public class Wait { } catch (Throwable t) { throw new RuntimeException(t); } + Log.d("Wait", "atMost: timed out: " + SystemClock.uptimeMillis()); Assert.fail(message); } } diff --git a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java index 204240324..62fe26d13 100644 --- a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java +++ b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java @@ -19,6 +19,7 @@ import android.app.Activity; import android.app.Application; import android.app.Application.ActivityLifecycleCallbacks; import android.os.Bundle; + import androidx.test.InstrumentationRegistry; import com.android.launcher3.Launcher; @@ -84,19 +85,27 @@ public class LauncherActivityRule implements TestRule { } @Override - public void onActivityStarted(Activity activity) { } + public void onActivityStarted(Activity activity) { + if (activity instanceof Launcher) { + mActivity.getRotationHelper().forceAllowRotationForTesting(true); + } + } @Override - public void onActivityResumed(Activity activity) { } + public void onActivityResumed(Activity activity) { + } @Override - public void onActivityPaused(Activity activity) { } + public void onActivityPaused(Activity activity) { + } @Override - public void onActivityStopped(Activity activity) { } + public void onActivityStopped(Activity activity) { + } @Override - public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { } + public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { + } @Override public void onActivityDestroyed(Activity activity) { diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 9ff354a7e..f070280ea 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -120,7 +120,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer { mLauncher.assertTrue("Unable to scroll to a clickable icon: " + appName, hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)); - final UiObject2 appIcon = mLauncher.getObjectInContainer(appListRecycler, + final UiObject2 appIcon = mLauncher.waitForObjectInContainer(appListRecycler, appIconSelector); return new AppIcon(mLauncher, appIcon); } diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java index bbd2c29e3..25e6e8c8f 100644 --- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java @@ -74,7 +74,7 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { flingForward(); } - mLauncher.getObjectInContainer(verifyActiveContainer(), clearAllSelector).click(); + mLauncher.waitForObjectInContainer(verifyActiveContainer(), clearAllSelector).click(); try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( "dismissed all tasks")) { return new Workspace(mLauncher); diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index fe7401ca6..6348c41af 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -178,6 +178,7 @@ public final class LauncherInstrumentation { PackageManager pm = getContext().getPackageManager(); ProviderInfo pi = pm.resolveContentProvider( testProviderAuthority, MATCH_ALL | MATCH_DISABLED_COMPONENTS); + assertNotNull("Cannot find content provider for " + testProviderAuthority, pi); ComponentName cn = new ComponentName(pi.packageName, pi.name); if (pm.getComponentEnabledSetting(cn) != COMPONENT_ENABLED_STATE_ENABLED) { @@ -678,13 +679,6 @@ public final class LauncherInstrumentation { } @NonNull - UiObject2 getObjectInContainer(UiObject2 container, BySelector selector) { - final UiObject2 object = container.findObject(selector); - assertNotNull("Can't find an object with selector: " + selector, object); - return object; - } - - @NonNull List<UiObject2> getObjectsInContainer(UiObject2 container, String resName) { return container.findObjects(getLauncherObjectSelector(resName)); } diff --git a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java index 399c59d36..a089a527e 100644 --- a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java +++ b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java @@ -109,7 +109,7 @@ public class TestHelpers { DropBoxManager.Entry entry; StringBuilder errorDetails = new StringBuilder(); while (null != (entry = dropbox.getNextEntry(label, timestamp))) { - if (errorDetails.length() != 0) errorDetails.append("------------------------------"); + errorDetails.append("------------------------------\n"); timestamp = entry.getTimeMillis(); errorDetails.append(new Date(timestamp)); errorDetails.append(": "); diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 07f8b6443..639902fa0 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -108,10 +108,13 @@ public final class Workspace extends Home { */ @NonNull public AppIcon getWorkspaceAppIcon(String appName) { - return new AppIcon(mLauncher, - mLauncher.getObjectInContainer( - verifyActiveContainer(), - AppIcon.getAppIconSelector(appName, mLauncher))); + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get a workspace icon")) { + return new AppIcon(mLauncher, + mLauncher.waitForObjectInContainer( + verifyActiveContainer(), + AppIcon.getAppIconSelector(appName, mLauncher))); + } } /** @@ -142,13 +145,13 @@ public final class Workspace extends Home { @NonNull public AppIcon getHotseatAppIcon(String appName) { - return new AppIcon(mLauncher, mLauncher.getObjectInContainer( + return new AppIcon(mLauncher, mLauncher.waitForObjectInContainer( mHotseat, AppIcon.getAppIconSelector(appName, mLauncher))); } @NonNull public Folder getHotseatFolder(String appName) { - return new Folder(mLauncher, mLauncher.getObjectInContainer( + return new Folder(mLauncher, mLauncher.waitForObjectInContainer( mHotseat, Folder.getSelector(appName, mLauncher))); } |