Merge "Remove flag ENABLE_LAUNCH_FROM_STAGED_APP" into udc-qpr-dev
diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
index ecb8365..f99155f 100644
--- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
+++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
@@ -188,12 +188,27 @@
return response;
}
+ case TestProtocol.REQUEST_REINITIALIZE_DATA: {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ MODEL_EXECUTOR.execute(() -> {
+ LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
+ model.getModelDbController().createEmptyDB();
+ MAIN_EXECUTOR.execute(model::forceReload);
+ });
+ return response;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
case TestProtocol.REQUEST_CLEAR_DATA: {
final long identity = Binder.clearCallingIdentity();
try {
MODEL_EXECUTOR.execute(() -> {
LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
model.getModelDbController().createEmptyDB();
+ model.getModelDbController().clearEmptyDbFlag();
MAIN_EXECUTOR.execute(model::forceReload);
});
return response;
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 2b578c3..153c1ac 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -18,6 +18,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
@@ -1210,14 +1211,15 @@
return false;
}
- private boolean hasMultipleTargetsWithMode(RemoteAnimationTarget[] targets, int mode) {
+ private boolean shouldPlayFallbackClosingAnimation(RemoteAnimationTarget[] targets) {
int numTargets = 0;
for (RemoteAnimationTarget target : targets) {
- if (target.mode == mode) {
+ if (target.mode == MODE_CLOSING) {
numTargets++;
- }
- if (numTargets > 1) {
- return true;
+ if (numTargets > 1 || target.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_MULTI_WINDOW) {
+ return true;
+ }
}
}
return false;
@@ -1604,7 +1606,7 @@
boolean playFallBackAnimation = (launcherView == null
&& launcherIsForceInvisibleOrOpening)
|| mLauncher.getWorkspace().isOverlayShown()
- || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING);
+ || shouldPlayFallbackClosingAnimation(appTargets);
boolean playWorkspaceReveal = true;
boolean skipAllAppsScale = false;
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 34316db..023486f 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -16,6 +16,8 @@
package com.android.launcher3.appprediction;
+import static com.android.launcher3.BubbleTextView.DISPLAY_PREDICTION_ROW;
+
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
@@ -36,7 +38,6 @@
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.anim.AlphaUpdateListener;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusIndicatorHelper;
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
import com.android.launcher3.model.data.ItemInfo;
@@ -106,22 +107,12 @@
mActivityContext.getAppsView().getAppsStore().unregisterIconContainer(this);
}
}
-
- // Set the predicted row in All Apps' text line to 1.
- if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()
- || FeatureFlags.ENABLE_TWOLINE_DEVICESEARCH.get()) {
- for (int i = 0; i < getChildCount(); i++) {
- BubbleTextView icon = (BubbleTextView) getChildAt(i);
- icon.setMaxLines(1);
- }
- }
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getExpectedHeight(),
MeasureSpec.EXACTLY));
- updateVisibility();
}
@Override
@@ -231,6 +222,7 @@
icon.reset();
if (predictionCount > i) {
icon.setVisibility(View.VISIBLE);
+ icon.setDisplay(DISPLAY_PREDICTION_ROW);
icon.applyFromWorkspaceItem(mPredictedApps.get(i));
} else {
icon.setVisibility(predictionCount == 0 ? GONE : INVISIBLE);
diff --git a/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java b/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java
index 4d7cc85..6d90b035 100644
--- a/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java
+++ b/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java
@@ -24,6 +24,8 @@
import android.os.Bundle;
import android.util.Log;
+import com.android.launcher3.util.StartActivityParams;
+
public class ProxyActivityStarter extends Activity {
private static final String TAG = "ProxyActivityStarter";
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 0b822fb..4ad3d5a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -202,6 +202,11 @@
public void onStateTransitionComplete(LauncherState finalState) {
mLauncherState = finalState;
updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, false);
+ // TODO(b/279514548) Cleans up bad state that can occur when user interacts with
+ // taskbar on top of transparent activity.
+ if (finalState == LauncherState.NORMAL && mLauncher.isResumed()) {
+ updateStateForFlag(FLAG_RESUMED, true);
+ }
applyState();
boolean disallowLongClick = finalState == LauncherState.OVERVIEW_SPLIT_SELECT;
com.android.launcher3.taskbar.Utilities.setOverviewDragState(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 5eec726..512b77a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -177,7 +177,6 @@
systemShortcuts);
}
- icon.clearAccessibilityFocus();
container.addOnAttachStateChangeListener(
new PopupLiveUpdateHandler<BaseTaskbarContext>(context, container) {
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 6b5c962..b2d5940 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -184,6 +184,8 @@
bubbleControllers.runAfterInit(() -> {
mBubbleBarViewController.setHiddenForBubbles(!BUBBLE_BAR_ENABLED);
mBubbleStashedHandleViewController.setHiddenForBubbles(!BUBBLE_BAR_ENABLED);
+ mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
+ key -> setSelectedBubble(mBubbles.get(key)));
});
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 58c67e3..0b33645 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -32,6 +32,7 @@
import com.android.launcher3.views.ActivityContext;
import java.util.List;
+import java.util.function.Consumer;
/**
* The view that holds all the bubble views. Modifying this view should happen through
@@ -101,6 +102,9 @@
@Nullable
private Runnable mReorderRunnable;
+ @Nullable
+ private Consumer<String> mUpdateSelectedBubbleAfterCollapse;
+
public BubbleBarView(Context context) {
this(context, null);
}
@@ -144,6 +148,13 @@
mReorderRunnable.run();
mReorderRunnable = null;
}
+ // If the bar was just collapsed and the overflow was the last bubble that was
+ // selected, set the first bubble as selected.
+ if (!mIsBarExpanded && mUpdateSelectedBubbleAfterCollapse != null
+ && mSelectedBubbleView.getBubble() instanceof BubbleBarOverflow) {
+ BubbleView firstBubble = (BubbleView) getChildAt(0);
+ mUpdateSelectedBubbleAfterCollapse.accept(firstBubble.getBubble().getKey());
+ }
updateWidth();
}
@@ -293,6 +304,11 @@
}
}
+ public void setUpdateSelectedBubbleAfterCollapse(
+ Consumer<String> updateSelectedBubbleAfterCollapse) {
+ mUpdateSelectedBubbleAfterCollapse = updateSelectedBubbleAfterCollapse;
+ }
+
/**
* Sets which bubble view should be shown as selected.
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 52c144e..4e9f88a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -36,6 +36,7 @@
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* Controller for {@link BubbleBarView}. Manages the visibility of the bubble bar as well as
@@ -184,6 +185,12 @@
}
}
+ /** Sets a callback that updates the selected bubble after the bubble bar collapses. */
+ public void setUpdateSelectedBubbleAfterCollapse(
+ Consumer<String> updateSelectedBubbleAfterCollapse) {
+ mBarView.setUpdateSelectedBubbleAfterCollapse(updateSelectedBubbleAfterCollapse);
+ }
+
/**
* Sets whether the bubble bar should be hidden due to SysUI state (e.g. on lockscreen).
*/
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 582b795..1ba11fd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -120,7 +120,6 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.proxy.ProxyActivityStarter;
-import com.android.launcher3.proxy.StartActivityParams;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
@@ -152,6 +151,7 @@
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
+import com.android.launcher3.util.StartActivityParams;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.widget.LauncherWidgetHolder;
import com.android.quickstep.OverviewCommandHelper;
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 13da40a..5784c37 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -18,6 +18,7 @@
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.LauncherState.FLOATING_SEARCH_BAR;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
@@ -267,7 +268,9 @@
@Override
public boolean allowAllAppsFromOverview() {
- return FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get();
+ return FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()
+ // If floating search bar would not show in overview, don't allow all apps gesture.
+ && OVERVIEW.areElementsVisible(getCreatedActivity(), FLOATING_SEARCH_BAR);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 7693e69..1448a52 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -239,7 +239,7 @@
public void onDisplayInfoChanged(Context context, Info info, int flags) {
if ((flags & (CHANGE_ROTATION | CHANGE_NAVIGATION_MODE)) != 0) {
mMode = info.navigationMode;
- mNavBarPosition = new NavBarPosition(mContext, mMode, info);
+ mNavBarPosition = new NavBarPosition(mMode, info);
if (mMode == NO_BUTTON) {
mExclusionListener.register();
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index dd6499b..1de264a 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.util.LogUtils.splitFailureMessage;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -706,7 +707,7 @@
mSplitScreen.startTasks(taskId1, options1, taskId2, options2, splitPosition,
splitRatio, remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startTasks");
+ Log.w(TAG, splitFailureMessage("startTasks", "RemoteException"), e);
}
}
}
@@ -719,7 +720,7 @@
mSplitScreen.startIntentAndTask(pendingIntent, userId1, options1, taskId, options2,
splitPosition, splitRatio, remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntentAndTask");
+ Log.w(TAG, splitFailureMessage("startIntentAndTask", "RemoteException"), e);
}
}
}
@@ -735,7 +736,7 @@
pendingIntent2, userId2, shortcutInfo2, options2, splitPosition, splitRatio,
remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntents");
+ Log.w(TAG, splitFailureMessage("startIntents", "RemoteException"), e);
}
}
}
@@ -748,7 +749,7 @@
mSplitScreen.startShortcutAndTask(shortcutInfo, options1, taskId, options2,
splitPosition, splitRatio, remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startShortcutAndTask");
+ Log.w(TAG, splitFailureMessage("startShortcutAndTask", "RemoteException"), e);
}
}
}
@@ -764,7 +765,8 @@
mSplitScreen.startTasksWithLegacyTransition(taskId1, options1, taskId2, options2,
splitPosition, splitRatio, adapter, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startTasksWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startTasksWithLegacyTransition", "RemoteException"), e);
}
}
}
@@ -778,7 +780,8 @@
mSplitScreen.startIntentAndTaskWithLegacyTransition(pendingIntent, userId1,
options1, taskId, options2, splitPosition, splitRatio, adapter, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntentAndTaskWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startIntentAndTaskWithLegacyTransition", "RemoteException"), e);
}
}
}
@@ -791,7 +794,8 @@
mSplitScreen.startShortcutAndTaskWithLegacyTransition(shortcutInfo, options1,
taskId, options2, splitPosition, splitRatio, adapter, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startShortcutAndTaskWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startShortcutAndTaskWithLegacyTransition", "RemoteException"), e);
}
}
}
@@ -811,7 +815,8 @@
shortcutInfo1, options1, pendingIntent2, userId2, shortcutInfo2, options2,
sidePosition, splitRatio, adapter, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntentsWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startIntentsWithLegacyTransition", "RemoteException"), e);
}
}
}
@@ -823,7 +828,7 @@
mSplitScreen.startShortcut(packageName, shortcutId, position, options,
user, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startShortcut");
+ Log.w(TAG, splitFailureMessage("startShortcut", "RemoteException"), e);
}
}
}
@@ -835,7 +840,7 @@
mSplitScreen.startIntent(intent, userId, fillInIntent, position, options,
instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntent");
+ Log.w(TAG, splitFailureMessage("startIntent", "RemoteException"), e);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
index 66f5c00..8a87f63 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
@@ -42,7 +42,7 @@
mActivity = activity;
NavigationMode sysUINavigationMode = DisplayController.getNavigationMode(mActivity);
if (sysUINavigationMode == NavigationMode.NO_BUTTON) {
- NavBarPosition navBarPosition = new NavBarPosition(mActivity, sysUINavigationMode,
+ NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode,
DisplayController.INSTANCE.get(mActivity).getInfo());
mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mActivity,
true /* disableHorizontalSwipe */, navBarPosition,
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 63e41d5..c4a2216 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -60,12 +60,11 @@
NavBarGestureHandler(Context context) {
mContext = context;
DisplayController.Info displayInfo = DisplayController.INSTANCE.get(mContext).getInfo();
- final int displayRotation = displayInfo.rotation;
Point currentSize = displayInfo.currentSize;
mDisplaySize.set(currentSize.x, currentSize.y);
mSwipeUpTouchTracker =
new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
- new NavBarPosition(mContext, NavigationMode.NO_BUTTON, displayRotation),
+ new NavBarPosition(NavigationMode.NO_BUTTON, displayInfo),
null /*onInterceptTouch*/, this);
mMotionPauseDetector = new MotionPauseDetector(context);
diff --git a/quickstep/src/com/android/quickstep/util/LogUtils.kt b/quickstep/src/com/android/quickstep/util/LogUtils.kt
index 23a41f6..e34c4ec 100644
--- a/quickstep/src/com/android/quickstep/util/LogUtils.kt
+++ b/quickstep/src/com/android/quickstep/util/LogUtils.kt
@@ -20,6 +20,11 @@
import com.android.launcher3.logging.InstanceId
object LogUtils {
+ @JvmStatic
+ fun splitFailureMessage(caller: String, reason: String): String {
+ return "($caller) Splitscreen aborted: $reason"
+ }
+
/**
* @return a [Pair] of two InstanceIds but with different types, one that can be used by
* framework (if needing to pass through an intent or such) and one used in Launcher
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
index a89e7e3..9418512 100644
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
@@ -16,9 +16,7 @@
package com.android.quickstep.util;
import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
-import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
-import android.content.Context;
import android.view.Surface;
import com.android.launcher3.util.DisplayController.Info;
@@ -29,26 +27,22 @@
*/
public class NavBarPosition {
- private final boolean mIsLargeScreen;
+ private final boolean mIsTablet;
private final NavigationMode mMode;
private final int mDisplayRotation;
- public NavBarPosition(Context context, NavigationMode mode, Info info) {
- this(context, mode, info.rotation);
- }
-
- public NavBarPosition(Context context, NavigationMode mode, int displayRotation) {
- mIsLargeScreen = isLargeScreen(context);
+ public NavBarPosition(NavigationMode mode, Info info) {
+ mIsTablet = info.isTablet(info.realBounds);
mMode = mode;
- mDisplayRotation = displayRotation;
+ mDisplayRotation = info.rotation;
}
public boolean isRightEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90 && !mIsLargeScreen;
+ return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90 && !mIsTablet;
}
public boolean isLeftEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270 && !mIsLargeScreen;
+ return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270 && !mIsTablet;
}
public float getRotation() {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 409b1a5..ae744d4 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -53,6 +53,7 @@
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
+import static com.android.quickstep.util.LogUtils.splitFailureMessage;
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED;
import static com.android.quickstep.views.OverviewActionsView.FLAG_IS_NOT_TABLET;
@@ -4722,6 +4723,8 @@
return false;
}
if (mSplitSelectStateController.isBothSplitAppsConfirmed()) {
+ Log.w(TAG, splitFailureMessage(
+ "confirmSplitSelect", "both apps have already been set"));
return true;
}
// Second task is selected either as an already-running Task or an Intent
@@ -4729,6 +4732,9 @@
if (!task.isDockable) {
// Task does not support split screen
mSplitUnsupportedToast.show();
+ Log.w(TAG, splitFailureMessage("confirmSplitSelect",
+ "selected Task (" + task.key.getPackageName()
+ + ") is not dockable / does not support splitscreen"));
return true;
}
mSplitSelectStateController.setSecondTask(task);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
new file mode 100644
index 0000000..e92dc8f
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -0,0 +1,58 @@
+/*
+ * 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.quickstep;
+
+import static org.junit.Assume.assumeTrue;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplTestsTrackpad extends AbstractQuickStepTest {
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ TaplTestsLauncher3.initialize(this);
+ mLauncher.setSwipeFromTrackpad(true);
+ }
+
+ @After
+ public void tearDown() {
+ mLauncher.setSwipeFromTrackpad(false);
+ }
+
+ @Test
+ @PortraitLandscape
+ @NavigationModeSwitch
+ public void goHome() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ startTestActivity(2);
+ mLauncher.goHome();
+ }
+}
diff --git a/res/layout/hotseat.xml b/res/layout/hotseat.xml
index 95ebd94..82b0b8d 100644
--- a/res/layout/hotseat.xml
+++ b/res/layout/hotseat.xml
@@ -21,5 +21,4 @@
android:layout_height="match_parent"
android:theme="@style/HomeScreenElementTheme"
android:importantForAccessibility="no"
- android:preferKeepClear="true"
launcher:containerType="hotseat" />
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 76a1239..73e392d 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -85,6 +85,7 @@
<enum name="taskbar" value="5" />
<enum name="search_result_tall" value="6" />
<enum name="search_result_small" value="7" />
+ <enum name="prediction_row" value="8" />
</attr>
<attr name="centerVertically" format="boolean" />
</declare-styleable>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 05d434e..2356bcc 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -94,11 +94,12 @@
IconLabelDotView, DraggableView, Reorderable {
private static final int DISPLAY_WORKSPACE = 0;
- private static final int DISPLAY_ALL_APPS = 1;
+ public static final int DISPLAY_ALL_APPS = 1;
private static final int DISPLAY_FOLDER = 2;
protected static final int DISPLAY_TASKBAR = 5;
private static final int DISPLAY_SEARCH_RESULT = 6;
private static final int DISPLAY_SEARCH_RESULT_SMALL = 7;
+ public static final int DISPLAY_PREDICTION_ROW = 8;
private static final float MIN_LETTER_SPACING = -0.05f;
private static final int MAX_SEARCH_LOOP_COUNT = 20;
@@ -211,7 +212,7 @@
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
defaultIconSize = grid.iconSizePx;
setCenterVertically(grid.iconCenterVertically);
- } else if (mDisplay == DISPLAY_ALL_APPS) {
+ } else if (mDisplay == DISPLAY_ALL_APPS || mDisplay == DISPLAY_PREDICTION_ROW) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
defaultIconSize = grid.allAppsIconSizePx;
@@ -402,7 +403,7 @@
* Only if actual text can be displayed in two line, the {@code true} value will be effective.
*/
protected boolean shouldUseTwoLine() {
- return (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get() && mDisplay == DISPLAY_ALL_APPS)
+ return (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get() && mDisplay == DISPLAY_ALL_APPS)
|| (FeatureFlags.ENABLE_TWOLINE_DEVICESEARCH.get()
&& mDisplay == DISPLAY_SEARCH_RESULT);
}
@@ -424,10 +425,10 @@
}
}
- /** This is used for testing to forcefully set the display to ALL_APPS */
+ /** This is used for testing to forcefully set the display. */
@VisibleForTesting
- public void setDisplayAllApps() {
- mDisplay = DISPLAY_ALL_APPS;
+ public void setDisplay(int display) {
+ mDisplay = display;
}
/**
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 463a243..814a0f9 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1258,6 +1258,32 @@
mResponsiveHeightSpec.getGutterPx());
folderContentPaddingLeftRight = mResponsiveFolderWidthSpec.getStartPaddingPx();
+
+ // Reduce icon width if it's wider than the expected folder cell width
+ if (folderCellWidthPx < folderChildIconSizePx) {
+ folderChildIconSizePx = mIconSizeSteps.getIconSmallerThan(folderCellWidthPx);
+ }
+
+ // Recalculating padding and cell height
+ folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
+ int folderCellContentHeight = folderChildIconSizePx + folderChildDrawablePaddingPx
+ + textHeight;
+
+ // Reduce the icon in height when it's taller than the expected cell height
+ while (folderChildIconSizePx > mIconSizeSteps.minimumIconSize()
+ && folderCellContentHeight > folderCellHeightPx) {
+ folderChildDrawablePaddingPx -= folderCellContentHeight - folderCellHeightPx;
+ if (folderChildDrawablePaddingPx < 0) {
+ // get a smaller icon size
+ folderChildIconSizePx = mIconSizeSteps.getNextLowerIconSize(
+ folderChildIconSizePx);
+ folderChildDrawablePaddingPx =
+ getNormalizedFolderChildDrawablePaddingPx(textHeight);
+ }
+ // calculate new cellContentHeight
+ folderCellContentHeight = folderChildIconSizePx + folderChildDrawablePaddingPx
+ + textHeight;
+ }
} else if (mIsScalableGrid) {
if (inv.folderStyle == INVALID_RESOURCE_HANDLE) {
folderCellWidthPx = roundPxValueFromFloat(getCellSize().x * scale);
@@ -1275,6 +1301,8 @@
folderFooterHeightPx = roundPxValueFromFloat(folderFooterHeightPx * scale);
folderContentPaddingLeftRight = folderCellLayoutBorderSpacePx.x;
+
+ folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
} else {
int cellPaddingX = (int) (res.getDimensionPixelSize(R.dimen.folder_cell_x_padding)
* scale);
@@ -1291,9 +1319,8 @@
res.getDimensionPixelSize(R.dimen.folder_footer_height_default)
* scale);
+ folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
}
-
- folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
}
public void updateInsets(Rect insets) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7e43002..66c76ca 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1407,8 +1407,7 @@
*/
protected void completeAddShortcut(Intent data, int container, int screenId, int cellX,
int cellY, PendingRequestArgs args) {
- if (args.getRequestCode() != REQUEST_CREATE_SHORTCUT
- || args.getPendingIntent().getComponent() == null) {
+ if (args.getRequestCode() != REQUEST_CREATE_SHORTCUT) {
return;
}
@@ -1916,16 +1915,10 @@
info.spanX = spanX;
info.spanY = spanY;
- switch (info.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
- case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
- addAppWidgetFromDrop((PendingAddWidgetInfo) info);
- break;
- case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
- processShortcutFromDrop((PendingAddShortcutInfo) info);
- break;
- default:
- throw new IllegalStateException("Unknown item type: " + info.itemType);
+ if (info instanceof PendingAddWidgetInfo) {
+ addAppWidgetFromDrop((PendingAddWidgetInfo) info);
+ } else { // info can only be PendingAddShortcutInfo
+ processShortcutFromDrop((PendingAddShortcutInfo) info);
}
}
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index 177f883..427eaa3 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -277,7 +277,7 @@
@JvmField val ICON_STATE = nonRestorableItem(LauncherAppState.KEY_ICON_STATE, "", true)
@JvmField
val ALL_APPS_OVERVIEW_THRESHOLD =
- nonRestorableItem(LauncherAppState.KEY_ALL_APPS_OVERVIEW_THRESHOLD, 200, true)
+ nonRestorableItem(LauncherAppState.KEY_ALL_APPS_OVERVIEW_THRESHOLD, 180, true)
@JvmField val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false, true)
@JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "")
@JvmField val WORK_EDU_STEP = backedUpItem(WorkProfileManager.KEY_WORK_EDU_STEP, 0)
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index d78e453..5e48177 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -102,6 +102,12 @@
StateManager<LauncherState> stateManager = mActivityContext.getStateManager();
+ // Special case to not expand the search bar when exiting All Apps on phones.
+ if (stateManager.getCurrentStableState() == LauncherState.ALL_APPS
+ && mActivityContext.getDeviceProfile().isPhone) {
+ return LauncherState.ALL_APPS.getFloatingSearchBarRestingMarginStart(mActivityContext);
+ }
+
if (stateManager.isInTransition() && stateManager.getTargetState() != null) {
return stateManager.getTargetState()
.getFloatingSearchBarRestingMarginStart(mActivityContext);
@@ -118,6 +124,12 @@
StateManager<LauncherState> stateManager = mActivityContext.getStateManager();
+ // Special case to not expand the search bar when exiting All Apps on phones.
+ if (stateManager.getCurrentStableState() == LauncherState.ALL_APPS
+ && mActivityContext.getDeviceProfile().isPhone) {
+ return LauncherState.ALL_APPS.getFloatingSearchBarRestingMarginEnd(mActivityContext);
+ }
+
if (stateManager.isInTransition() && stateManager.getTargetState() != null) {
return stateManager.getTargetState()
.getFloatingSearchBarRestingMarginEnd(mActivityContext);
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index 7bdec1c..0f3cad6 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -16,6 +16,8 @@
package com.android.launcher3.dragndrop;
+import static android.content.pm.LauncherApps.EXTRA_PIN_ITEM_REQUEST;
+
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.EDIT_MODE;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
@@ -25,6 +27,7 @@
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.PinItemRequest;
import android.content.pm.PackageManager;
@@ -41,6 +44,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.PinRequestHelper;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.util.StartActivityParams;
import java.util.function.Supplier;
@@ -105,7 +109,11 @@
@Override
public boolean startConfigActivity(Activity activity, int requestCode) {
- return false;
+ new StartActivityParams(activity, requestCode).deliverResult(
+ activity,
+ Activity.RESULT_OK,
+ new Intent().putExtra(EXTRA_PIN_ITEM_REQUEST, mRequestSupplier.get()));
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 8274789..1f26bab 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -125,6 +125,14 @@
this(context, null, 0);
}
+ @Override
+ protected View getAccessibilityInitialFocusView() {
+ if (mSystemShortcutContainer != null) {
+ return mSystemShortcutContainer.getChildAt(0);
+ }
+ return super.getAccessibilityInitialFocusView();
+ }
+
public LauncherAccessibilityDelegate getAccessibilityDelegate() {
return mAccessibilityDelegate;
}
@@ -242,7 +250,6 @@
popupDataProvider.getNotificationKeysForItem(item),
systemShortcuts);
}
- launcher.tryClearAccessibilityFocus(icon);
launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item));
container.requestFocus();
return container;
diff --git a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java b/src/com/android/launcher3/util/StartActivityParams.java
similarity index 94%
rename from quickstep/src/com/android/launcher3/proxy/StartActivityParams.java
rename to src/com/android/launcher3/util/StartActivityParams.java
index 4d0bee6..b48562f 100644
--- a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java
+++ b/src/com/android/launcher3/util/StartActivityParams.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3.proxy;
+package com.android.launcher3.util;
import static android.app.PendingIntent.FLAG_MUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
@@ -34,6 +34,9 @@
import android.os.Parcelable;
import android.util.Log;
+/**
+ * Wrapper class for parameters to start an activity.
+ */
public class StartActivityParams implements Parcelable {
private static final String TAG = "StartActivityParams";
@@ -93,6 +96,7 @@
parcel.writeBundle(options);
}
+ /** Perform the operation on the pendingIntent. */
public void deliverResult(Context context, int resultCode, Intent data) {
ActivityOptions options = allowBGLaunch(ActivityOptions.makeBasic());
try {
@@ -105,7 +109,7 @@
}
public static final Parcelable.Creator<StartActivityParams> CREATOR =
- new Parcelable.Creator<StartActivityParams>() {
+ new Parcelable.Creator<>() {
public StartActivityParams createFromParcel(Parcel source) {
return new StartActivityParams(source);
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index a3ef6e1..c9cd4b6 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -891,6 +891,19 @@
return false;
}
+ /** Gets the sheet for widget picker, which is used for testing. */
+ @VisibleForTesting
+ public View getSheet() {
+ return mContent;
+ }
+
+ /** Opens the first header in widget picker and scrolls to the top of the RecyclerView. */
+ @VisibleForTesting
+ public void openFirstHeader() {
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.selectFirstHeaderEntry();
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView.scrollToTop();
+ }
+
/** A holder class for holding adapters & their corresponding recycler view. */
final class AdapterHolder {
static final int PRIMARY = 0;
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index b170061..c8b5a20 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -41,6 +41,17 @@
</receiver>
<receiver
+ android:name="com.android.launcher3.testcomponent.AppWidgetNoConfigLarge"
+ android:exported="true"
+ android:label="No Config Large">
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
+ </intent-filter>
+ <meta-data android:name="android.appwidget.provider"
+ android:resource="@xml/appwidget_no_config_large"/>
+ </receiver>
+
+ <receiver
android:name="com.android.launcher3.testcomponent.AppWdigetHidden"
android:exported="true"
android:label="Hidden widget">
diff --git a/tests/res/xml/appwidget_no_config_large.xml b/tests/res/xml/appwidget_no_config_large.xml
new file mode 100644
index 0000000..b3b69d9
--- /dev/null
+++ b/tests/res/xml/appwidget_no_config_large.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<appwidget-provider
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="1dp"
+ android:minHeight="1dp"
+ android:minResizeWidth="1dp"
+ android:maxResizeWidth="3000dp"
+ android:targetCellHeight="1"
+ android:targetCellWidth="5"
+ android:updatePeriodMillis="86400000"
+ android:initialLayout="@layout/test_layout_appwidget_red"
+ android:previewLayout="@layout/test_layout_appwidget_red"
+ android:resizeMode="horizontal|vertical"
+ android:widgetCategory="home_screen">
+</appwidget-provider>
\ No newline at end of file
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 36e4e76..84c3555 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -110,6 +110,7 @@
public static final String REQUEST_GET_TEST_EVENTS = "get-test-events";
public static final String REQUEST_GET_HAD_NONTEST_EVENTS = "get-had-nontest-events";
public static final String REQUEST_STOP_EVENT_LOGGING = "stop-event-logging";
+ public static final String REQUEST_REINITIALIZE_DATA = "reinitialize-data";
public static final String REQUEST_CLEAR_DATA = "clear-data";
public static final String REQUEST_HOTSEAT_ICON_NAMES = "get-hotseat-icon-names";
public static final String REQUEST_IS_TABLET = "is-tablet";
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
index ee05fe6..91a0634 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
@@ -164,7 +164,7 @@
Context c = new ActivityContextWrapper(getApplicationContext());
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(c).getDeviceProfile(c).copy(c);
mPrevNumColumns = dp.inv.numColumns;
- mPrevNumRows = dp.inv.numColumns;
+ mPrevNumRows = dp.inv.numRows;
}
@After
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 3239472..a82b005 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -291,8 +291,16 @@
}
}
- protected void clearLauncherData() {
- mLauncher.clearLauncherData();
+ protected void reinitializeLauncherData() {
+ reinitializeLauncherData(false);
+ }
+
+ protected void reinitializeLauncherData(boolean clearWorkspace) {
+ if (clearWorkspace) {
+ mLauncher.clearLauncherData();
+ } else {
+ mLauncher.reinitializeLauncherData();
+ }
mLauncher.waitForLauncherInitialized();
}
diff --git a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
index fdba4eb..ba17fdc 100644
--- a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
+++ b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
@@ -18,6 +18,8 @@
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static com.android.launcher3.BubbleTextView.DISPLAY_ALL_APPS;
+import static com.android.launcher3.BubbleTextView.DISPLAY_PREDICTION_ROW;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TWOLINE_ALLAPPS;
import static org.junit.Assert.assertEquals;
@@ -79,7 +81,6 @@
mContext = new ActivityContextWrapper(getApplicationContext());
mBubbleTextView = new BubbleTextView(mContext);
mBubbleTextView.reset();
- mBubbleTextView.setDisplayAllApps();
BubbleTextView testView = new BubbleTextView(mContext);
testView.setTypeface(Typeface.MONOSPACE);
@@ -104,6 +105,7 @@
public void testEmptyString_flagOn() {
try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
mItemInfoWithIcon.title = EMPTY_STRING;
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.applyLabel(mItemInfoWithIcon);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
@@ -118,6 +120,7 @@
public void testEmptyString_flagOff() {
try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
mItemInfoWithIcon.title = EMPTY_STRING;
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.applyLabel(mItemInfoWithIcon);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
@@ -134,6 +137,7 @@
// test string: "Battery Stats"
mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -149,6 +153,7 @@
// test string: "Battery Stats"
mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -164,6 +169,7 @@
// test string: "flutterappflorafy"
mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -179,6 +185,7 @@
// test string: "flutterappflorafy"
mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -194,6 +201,7 @@
// test string: "System UWB Field Test"
mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -209,6 +217,7 @@
// test string: "System UWB Field Test"
mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -224,6 +233,7 @@
// test string: "LEGO®Builder"
mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -239,6 +249,7 @@
// test string: "LEGO®Builder"
mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -291,4 +302,20 @@
breakPoints);
assertEquals(TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT_RESULT, newString);
}
+
+ @Test
+ public void testEnsurePredictionRowIsOneLine() {
+ try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+ // test string: "Battery Stats"
+ mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+ mBubbleTextView.setDisplay(DISPLAY_PREDICTION_ROW);
+ mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+ mBubbleTextView.measure(mLimitedWidth, 0);
+ mBubbleTextView.onPreDraw();
+ assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 2c8acc4..c1f2bb6 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -97,7 +97,12 @@
}
public static void initialize(AbstractLauncherUiTest test) throws Exception {
- test.clearLauncherData();
+ initialize(test, false);
+ }
+
+ public static void initialize(
+ AbstractLauncherUiTest test, boolean clearWorkspace) throws Exception {
+ test.reinitializeLauncherData(clearWorkspace);
test.mDevice.pressHome();
test.waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null);
test.waitForState("Launcher internal state didn't switch to Home",
@@ -248,7 +253,7 @@
LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
.atHotseat(0).putApp("com.android.chrome", "com.google.android.apps.chrome.Main");
mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, builder);
- clearLauncherData();
+ reinitializeLauncherData();
final Workspace workspace = mLauncher.getWorkspace();
@@ -557,7 +562,7 @@
allApps.unfreeze();
}
// Reset the workspace for the next shortcut creation.
- initialize(this);
+ initialize(this, true);
endTime = SystemClock.uptimeMillis();
elapsedTime = endTime - startTime;
Log.d("testDragAppIconToWorkspaceCellTime",
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 2286d7e..ce50e22 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -20,6 +20,7 @@
import static android.content.pm.PackageManager.DONT_KILL_APP;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
import static com.android.launcher3.tapl.Folder.FOLDER_CONTENT_RES_ID;
import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
@@ -197,11 +198,18 @@
private boolean mCheckEventsForSuccessfulGestures = false;
private Runnable mOnLauncherCrashed;
+ private boolean mSwipeFromTrackpad = false;
+ private int mPointerCount = 0;
+
private static Pattern getTouchEventPattern(String prefix, String action) {
- // The pattern includes checks that we don't get a multi-touch events or other surprises.
+ return getTouchEventPattern(prefix, action, 1);
+ }
+
+ private static Pattern getTouchEventPattern(String prefix, String action, int pointerCount) {
return Pattern.compile(
prefix + ": MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
- + ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount=1");
+ + ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount="
+ + pointerCount);
}
private static Pattern getTouchEventPattern(String action) {
@@ -212,6 +220,10 @@
return getTouchEventPattern("TouchInteractionService.onInputEvent", action);
}
+ private static Pattern getTouchEventPatternTIS(String action, int pointerCount) {
+ return getTouchEventPattern("TouchInteractionService.onInputEvent", action, pointerCount);
+ }
+
private static Pattern getKeyEventPattern(String action, String keyCode) {
return Pattern.compile("Key event: KeyEvent.*action=" + action + ".*keyCode=" + keyCode);
}
@@ -703,6 +715,10 @@
mIgnoreTaskbarVisibility = ignoreTaskbarVisibility;
}
+ public void setSwipeFromTrackpad(boolean swipeFromTrackpad) {
+ mSwipeFromTrackpad = swipeFromTrackpad;
+ }
+
/**
* Sets expected rotation.
* TAPL periodically checks that Launcher didn't suddenly change the rotation to unexpected one.
@@ -993,7 +1009,7 @@
// otherwise waitForIdle may return immediately in case when there was a big enough
// pause in accessibility events prior to pressing Home.
final String action;
- if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
+ if (getNavigationModel() == NavigationModel.ZERO_BUTTON || mSwipeFromTrackpad) {
checkForAnomaly(false, true);
final Point displaySize = getRealDisplaySize();
@@ -1009,9 +1025,11 @@
} else {
action = "swiping up to home";
+ int startY = mSwipeFromTrackpad ? displaySize.y * 3 / 4 : displaySize.y - 1;
+ int endY = mSwipeFromTrackpad ? displaySize.y / 4 : displaySize.y / 2;
swipeToState(
- displaySize.x / 2, displaySize.y - 1,
- displaySize.x / 2, displaySize.y / 2,
+ displaySize.x / 2, startY,
+ displaySize.x / 2, endY,
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
gestureStartFromLauncher ? GestureScope.INSIDE_TO_OUTSIDE
: GestureScope.OUTSIDE_WITH_PILFER);
@@ -1052,14 +1070,16 @@
waitForLauncherInitialized();
final boolean launcherVisible =
isTablet() ? isLauncherContainerVisible() : isLauncherVisible();
- if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
+ if (getNavigationModel() == NavigationModel.ZERO_BUTTON || mSwipeFromTrackpad) {
final Point displaySize = getRealDisplaySize();
final GestureScope gestureScope =
launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
: GestureScope.OUTSIDE_WITH_KEYCODE;
// TODO(b/225505986): change startY and endY back to displaySize.y / 2 once the
// issue is solved.
- linearGesture(0, displaySize.y / 4, displaySize.x / 2, displaySize.y / 4,
+ int startX = mSwipeFromTrackpad ? displaySize.x / 4 : 0;
+ int endX = mSwipeFromTrackpad ? displaySize.x * 3 / 4 : displaySize.x / 2;
+ linearGesture(startX, displaySize.y / 4, endX, displaySize.y / 4,
10, false, gestureScope);
} else {
waitForNavigationUiObject("back").click();
@@ -1589,18 +1609,33 @@
// Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
// fixed interval each time.
public void linearGesture(int startX, int startY, int endX, int endY, int steps,
- boolean slowDown,
- GestureScope gestureScope) {
+ boolean slowDown, GestureScope gestureScope) {
log("linearGesture: " + startX + ", " + startY + " -> " + endX + ", " + endY);
final long downTime = SystemClock.uptimeMillis();
final Point start = new Point(startX, startY);
final Point end = new Point(endX, endY);
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
+ if (mSwipeFromTrackpad) {
+ sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 1),
+ start, gestureScope);
+ sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 2),
+ start, gestureScope);
+ }
final long endTime = movePointer(
start, end, steps, false, downTime, downTime, slowDown, gestureScope);
+ if (mSwipeFromTrackpad) {
+ sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_UP, 2),
+ start, gestureScope);
+ sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_UP, 1),
+ start, gestureScope);
+ }
sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end, gestureScope);
}
+ private static int getPointerAction(int action, int index) {
+ return action + (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ }
+
long movePointer(Point start, Point end, int steps, boolean isDecelerating, long downTime,
long startTime, boolean slowDown, GestureScope gestureScope) {
long endTime = movePointer(downTime, startTime, steps * GESTURE_STEP_MS,
@@ -1624,22 +1659,44 @@
return getContext().getResources();
}
+ private static MotionEvent getTrackpadThreeFingerMotionEvent(long downTime, long eventTime,
+ int action, float x, float y, int pointerCount) {
+ MotionEvent.PointerProperties[] pointerProperties =
+ new MotionEvent.PointerProperties[pointerCount];
+ MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount];
+ for (int i = 0; i < pointerCount; i++) {
+ pointerProperties[i] = getPointerProperties(i);
+ pointerCoords[i] = getPointerCoords(x, y);
+ pointerCoords[i].setAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT, 3);
+ }
+ return MotionEvent.obtain(downTime, eventTime, action, pointerCount, pointerProperties,
+ pointerCoords, 0, 0, 1.0f, 1.0f, 0, 0,
+ InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_CLASS_POINTER, 0, 0,
+ MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE);
+ }
+
private static MotionEvent getMotionEvent(long downTime, long eventTime, int action,
float x, float y) {
- MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
- properties.id = 0;
- properties.toolType = Configurator.getInstance().getToolType();
+ return MotionEvent.obtain(downTime, eventTime, action, 1,
+ new MotionEvent.PointerProperties[] {getPointerProperties(0)},
+ new MotionEvent.PointerCoords[] {getPointerCoords(x, y)},
+ 0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
+ }
+ private static MotionEvent.PointerProperties getPointerProperties(int pointerId) {
+ MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
+ properties.id = pointerId;
+ properties.toolType = Configurator.getInstance().getToolType();
+ return properties;
+ }
+
+ private static MotionEvent.PointerCoords getPointerCoords(float x, float y) {
MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
coords.pressure = 1;
coords.size = 1;
coords.x = x;
coords.y = y;
-
- return MotionEvent.obtain(downTime, eventTime, action, 1,
- new MotionEvent.PointerProperties[]{properties},
- new MotionEvent.PointerCoords[]{coords},
- 0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
+ return coords;
}
private boolean hasTIS() {
@@ -1655,17 +1712,23 @@
public void sendPointer(long downTime, long currentTime, int action, Point point,
GestureScope gestureScope) {
final boolean hasTIS = hasTIS();
- switch (action) {
+ int pointerCount = 1;
+
+ switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
+ && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
+ && !mSwipeFromTrackpad) {
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
}
if (hasTIS && (isTrackpadGestureEnabled()
|| getNavigationModel() != NavigationModel.THREE_BUTTON)) {
expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
}
+ if (mSwipeFromTrackpad) {
+ mPointerCount = 1;
+ }
break;
case MotionEvent.ACTION_UP:
if (hasTIS && gestureScope != GestureScope.INSIDE
@@ -1676,7 +1739,8 @@
}
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
+ && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
+ && !mSwipeFromTrackpad) {
expectEvent(TestProtocol.SEQUENCE_MAIN,
gestureScope == GestureScope.INSIDE
|| gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER
@@ -1696,9 +1760,29 @@
case MotionEvent.ACTION_HOVER_EXIT:
expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_EXIT_TIS);
break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ mPointerCount++;
+ expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
+ "ACTION_POINTER_DOWN", mPointerCount));
+ pointerCount = mPointerCount;
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ pointerCount = 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));
+ }
+ mPointerCount--;
+ break;
}
- final MotionEvent event = getMotionEvent(downTime, currentTime, action, point.x, point.y);
+ final MotionEvent event = mSwipeFromTrackpad
+ ? getTrackpadThreeFingerMotionEvent(
+ downTime, currentTime, action, point.x, point.y, pointerCount)
+ : getMotionEvent(downTime, currentTime, action, point.x, point.y);
assertTrue("injectInputEvent failed",
mInstrumentation.getUiAutomation().injectInputEvent(event, true, false));
event.recycle();
@@ -1706,8 +1790,7 @@
public long movePointer(long downTime, long startTime, long duration, Point from, Point to,
GestureScope gestureScope) {
- return movePointer(
- downTime, startTime, duration, false, from, to, gestureScope);
+ return movePointer(downTime, startTime, duration, false, from, to, gestureScope);
}
public long movePointer(long downTime, long startTime, long duration, boolean isDecelerating,
@@ -1855,6 +1938,12 @@
return tasks;
}
+ /** Reinitializes the workspace to its default layout. */
+ public void reinitializeLauncherData() {
+ getTestInfo(TestProtocol.REQUEST_REINITIALIZE_DATA);
+ }
+
+ /** Clears the workspace, leaving it empty. */
public void clearLauncherData() {
getTestInfo(TestProtocol.REQUEST_CLEAR_DATA);
}