Merge "Draw focus outline in search app result" into main
diff --git a/Android.bp b/Android.bp
index eca0778..61042f6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -108,6 +108,7 @@
],
srcs: [
"tests/multivalentTests/tapl/**/*.java",
+ "tests/multivalentTests/tapl/**/*.kt",
],
resource_dirs: [],
manifest: "tests/multivalentTests/tapl/AndroidManifest.xml",
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index c13c68c..82ae4cb 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -92,6 +92,13 @@
}
flag {
+ name: "enable_predictive_back_gesture"
+ namespace: "launcher"
+ description: "Enable predictive back gesture on Launcher (including all apps and widget picker)."
+ bug: "238475505"
+}
+
+flag {
name: "enable_shortcut_dont_suggest_app"
namespace: "launcher"
description: "Enables don't suggest app shortcut for suggested apps"
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 823a86e..9d599c9 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -19,6 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/task"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index 60827cd..3cafcfd 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -19,6 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/task"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="true"
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index d20afd3..e91e773 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -24,6 +24,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/task"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index b23c283..325c255 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -267,7 +267,7 @@
<string name="taskbar_edu_features">Do more with the Taskbar</string>
<!-- Title in dialog that shows a user how to pin the Taskbar. [CHAR_LIMIT 60] -->
<string name="taskbar_edu_pinning_title">Always show the Taskbar</string>
- <!-- Text in dialog that shows a user how to pin the Taskbar. [CHAR_LIMIT 60] -->
+ <!-- Text in dialog that shows a user how to pin the Taskbar. [CHAR_LIMIT 150] -->
<string name="taskbar_edu_pinning_standalone">To always show the Taskbar on the bottom of your screen, touch & hold the divider</string>
<!-- Text on button to exit a tutorial [CHAR_LIMIT=16] -->
<string name="taskbar_edu_close">Close</string>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index e8a3d3e..05e1535 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1677,7 +1677,7 @@
}
};
- if (fromPredictiveBack) {
+ if (fromPredictiveBack && rectFSpringAnim != null) {
rectFSpringAnim.addAnimatorListener(endListener);
} else {
anim.addListener(endListener);
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index 6160378..f4cbf17 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -15,9 +15,11 @@
*/
package com.android.launcher3.model;
+import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
import android.app.prediction.AppTarget;
+import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.NonNull;
@@ -29,6 +31,7 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.PendingAddWidgetInfo;
+import com.android.launcher3.widget.picker.WidgetRecommendationCategoryProvider;
import java.util.ArrayList;
import java.util.List;
@@ -93,9 +96,21 @@
servicePredictedItems.addAll(localFilteredWidgets);
}
- List<ItemInfo> items = servicePredictedItems.stream()
- .map(it -> new PendingAddWidgetInfo(it.widgetInfo, CONTAINER_WIDGETS_PREDICTION))
- .collect(Collectors.toList());
+ List<ItemInfo> items;
+ if (enableCategorizedWidgetSuggestions()) {
+ Context context = appState.getContext();
+ WidgetRecommendationCategoryProvider categoryProvider =
+ WidgetRecommendationCategoryProvider.newInstance(context);
+ items = servicePredictedItems.stream()
+ .map(it -> new PendingAddWidgetInfo(it.widgetInfo, CONTAINER_WIDGETS_PREDICTION,
+ categoryProvider.getWidgetRecommendationCategory(context, it)))
+ .collect(Collectors.toList());
+ } else {
+ items = servicePredictedItems.stream()
+ .map(it -> new PendingAddWidgetInfo(it.widgetInfo,
+ CONTAINER_WIDGETS_PREDICTION)).collect(
+ Collectors.toList());
+ }
FixedContainerItems fixedContainerItems =
new FixedContainerItems(mPredictorState.containerId, items);
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 9b8ab33..2f11fd7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -780,9 +780,11 @@
handleSetupUi();
// Hide back button in SUW if keyboard is showing (IME draws its own back).
- mPropertyHolders.add(new StatePropertyHolder(
- mBackButtonAlpha.get(ALPHA_INDEX_SUW),
- flags -> (flags & FLAG_IME_VISIBLE) == 0));
+ if (mIsImeRenderingNavButtons) {
+ mPropertyHolders.add(new StatePropertyHolder(
+ mBackButtonAlpha.get(ALPHA_INDEX_SUW),
+ flags -> (flags & FLAG_IME_VISIBLE) == 0));
+ }
} else if (isInKidsMode) {
int iconSize = res.getDimensionPixelSize(
R.dimen.taskbar_icon_size_kids);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index c883759..db7d0eb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -60,8 +60,10 @@
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
+import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SystemUiProxy;
import java.io.PrintWriter;
@@ -951,6 +953,15 @@
if (mActivity.isHardwareKeyboard() && DisplayController.isPinnedTaskbar(mActivity)) {
return false;
}
+
+ // Do not stash if hardware keyboard is attached, in 3 button nav and desktop windowing mode
+ DesktopVisibilityController visibilityController =
+ LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+ if (visibilityController != null && mActivity.isHardwareKeyboard()
+ && mActivity.isThreeButtonNav() && visibilityController.areFreeformTasksVisible()) {
+ return false;
+ }
+
return mIsImeShowing || mIsImeSwitcherShowing;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 964d329..5424fcf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar.allapps;
import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.launcher3.Flags.enablePredictiveBackGesture;
import android.animation.Animator;
import android.content.Context;
@@ -168,7 +169,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mActivityContext.addOnDeviceProfileChangeListener(this);
- if (FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get()) {
+ if (enablePredictiveBackGesture()) {
mAppsView.getAppsRecyclerViewContainer().setOutlineProvider(mViewOutlineProvider);
mAppsView.getAppsRecyclerViewContainer().setClipToOutline(true);
OnBackInvokedDispatcher dispatcher = findOnBackInvokedDispatcher();
@@ -183,7 +184,7 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mActivityContext.removeOnDeviceProfileChangeListener(this);
- if (FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get()) {
+ if (enablePredictiveBackGesture()) {
mAppsView.getAppsRecyclerViewContainer().setOutlineProvider(null);
mAppsView.getAppsRecyclerViewContainer().setClipToOutline(false);
OnBackInvokedDispatcher dispatcher = findOnBackInvokedDispatcher();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index ac0e53e..c2a248d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -61,6 +61,7 @@
import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.launcher3.Flags.enablePredictiveBackGesture;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -645,7 +646,7 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (Utilities.ATLEAST_U && FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get()) {
+ if (Utilities.ATLEAST_U && enablePredictiveBackGesture()) {
getApplicationInfo().setEnableOnBackInvokedCallback(true);
}
if (savedInstanceState != null) {
@@ -833,7 +834,7 @@
@Override
protected void registerBackDispatcher() {
- if (!FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get()) {
+ if (!enablePredictiveBackGesture()) {
super.registerBackDispatcher();
return;
}
@@ -1355,7 +1356,7 @@
@Override
public boolean handleIncorrectSplitTargetSelection() {
- if (enableSplitContextually() && !mSplitSelectStateController.isSplitSelectActive()) {
+ if (!enableSplitContextually() || !mSplitSelectStateController.isSplitSelectActive()) {
return false;
}
mSplitSelectStateController.getSplitInstructionsView().goBoing();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index c961302..e6a115a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -69,6 +69,7 @@
super.setState(state);
if (state.overviewUi) {
mRecentsView.updateEmptyMessage();
+ } else {
mRecentsView.resetTaskVisuals();
}
setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig(), state);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
index d98e608..74ba006 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
@@ -31,6 +31,8 @@
import android.view.Window;
import android.view.WindowManager;
+import androidx.annotation.VisibleForTesting;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
@@ -51,12 +53,12 @@
private final Launcher mLauncher;
private final SystemUiProxy mSystemUiProxy;
- private final float mTouchSlop;
+ @VisibleForTesting final float mTouchSlop;
private int mLastAction;
private final SparseArray<PointF> mDownEvents;
/* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/
- private boolean mCanIntercept;
+ @VisibleForTesting boolean mCanIntercept;
private boolean mIsTrackpadReverseScroll;
@@ -85,9 +87,9 @@
@Override
public final boolean onControllerInterceptTouchEvent(MotionEvent ev) {
- int action = ev.getActionMasked();
- int idx = ev.getActionIndex();
- int pid = ev.getPointerId(idx);
+ final int action = ev.getActionMasked();
+ final int idx = ev.getActionIndex();
+ final int pid = ev.getPointerId(idx);
if (action == ACTION_DOWN) {
mCanIntercept = canInterceptTouch(ev);
if (!mCanIntercept) {
@@ -135,7 +137,6 @@
.log(LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN);
setWindowSlippery(false);
mIsTrackpadReverseScroll = false;
- return true;
}
return true;
}
@@ -149,7 +150,8 @@
* Touches can slide out of the window but they cannot necessarily slide
* back in (unless the other window with touch focus permits it).
*/
- private void setWindowSlippery(boolean enable) {
+ @VisibleForTesting
+ void setWindowSlippery(boolean enable) {
Window w = mLauncher.getWindow();
WindowManager.LayoutParams wlp = w.getAttributes();
if (enable) {
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index dffb882..8535a33 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -16,12 +16,15 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.TISBindHelper;
import com.android.quickstep.views.RecentsView;
+import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -37,6 +40,30 @@
public Bundle call(String method, String arg, @Nullable Bundle extras) {
final Bundle response = new Bundle();
switch (method) {
+ case TestProtocol.REQUEST_RECENT_TASKS_LIST: {
+ ArrayList<String> taskBaseIntentComponents = new ArrayList<>();
+ CountDownLatch latch = new CountDownLatch(1);
+ RecentsModel.INSTANCE.get(mContext).getTasks((taskGroups) -> {
+ for (GroupTask group : taskGroups) {
+ taskBaseIntentComponents.add(
+ group.task1.key.baseIntent.getComponent().flattenToString());
+ if (group.task2 != null) {
+ taskBaseIntentComponents.add(
+ group.task2.key.baseIntent.getComponent().flattenToString());
+ }
+ }
+ latch.countDown();
+ });
+ try {
+ latch.await(2, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ response.putStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ taskBaseIntentComponents);
+ return response;
+ }
+
case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
final float swipeHeight =
LayoutUtils.getDefaultSwipeHeight(mContext, mDeviceProfile);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index c8c7dc2..0f8ceba 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -154,6 +154,7 @@
mSquaredTouchSlop = mDeviceState.getSquaredTouchSlop();
mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;
+ mStartDisplacement = continuingPreviousGesture ? 0 : -mTouchSlop;
mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe;
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
}
@@ -280,7 +281,7 @@
if (mGestureState.isTrackpadGesture() || Math.abs(displacement)
> mTouchSlop) {
mPassedWindowMoveSlop = true;
- mStartDisplacement = Math.min(displacement, -mTouchSlop);
+ mStartDisplacement = -mTouchSlop;
}
}
}
@@ -336,7 +337,7 @@
}
if (!mPassedWindowMoveSlop) {
mPassedWindowMoveSlop = true;
- mStartDisplacement = Math.min(displacement, -mTouchSlop);
+ mStartDisplacement = -mTouchSlop;
}
notifyGestureStarted(isLikelyToStartNewTask);
}
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index 348e4dc..9268511 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.ArrayMap;
+import android.view.DisplayCutout;
import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowMetrics;
@@ -74,4 +75,10 @@
}
return result;
}
+
+ @Override
+ protected DisplayCutout rotateCutout(DisplayCutout original, int startWidth, int startHeight,
+ int fromRotation, int toRotation) {
+ return original.getRotated(startWidth, startHeight, fromRotation, toRotation);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
index 3a5873b..1c1e167 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
+++ b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
@@ -115,7 +115,7 @@
}
override fun draw(canvas: Canvas) {
- if (launcher.deviceProfile.isLandscape) {
+ if (launcher.deviceProfile.isLeftRightSplit) {
drawLeftRightSplit(canvas)
} else {
drawTopBottomSplit(canvas)
diff --git a/quickstep/src/com/android/quickstep/views/IconAppChipView.java b/quickstep/src/com/android/quickstep/views/IconAppChipView.java
index 0a261ef..3347665 100644
--- a/quickstep/src/com/android/quickstep/views/IconAppChipView.java
+++ b/quickstep/src/com/android/quickstep/views/IconAppChipView.java
@@ -52,9 +52,10 @@
private static final int MENU_BACKGROUND_REVEAL_DURATION = 417;
private static final int MENU_BACKGROUND_HIDE_DURATION = 333;
- private static final int NUM_ALPHA_CHANNELS = 2;
+ private static final int NUM_ALPHA_CHANNELS = 3;
private static final int INDEX_CONTENT_ALPHA = 0;
private static final int INDEX_COLOR_FILTER_ALPHA = 1;
+ private static final int INDEX_MODAL_ALPHA = 2;
private final MultiValueAlpha mMultiValueAlpha;
@@ -307,6 +308,11 @@
}
@Override
+ public void setModalAlpha(float alpha) {
+ mMultiValueAlpha.get(INDEX_MODAL_ALPHA).setValue(alpha);
+ }
+
+ @Override
public int getDrawableWidth() {
return mIconView == null ? 0 : mIconView.getDrawableWidth();
}
diff --git a/quickstep/src/com/android/quickstep/views/IconView.java b/quickstep/src/com/android/quickstep/views/IconView.java
index 042f581..4d33fda 100644
--- a/quickstep/src/com/android/quickstep/views/IconView.java
+++ b/quickstep/src/com/android/quickstep/views/IconView.java
@@ -149,6 +149,11 @@
}
@Override
+ public void setModalAlpha(float alpha) {
+ setAlpha(alpha);
+ }
+
+ @Override
public void setAlpha(float alpha) {
super.setAlpha(alpha);
if (alpha > 0) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 1b3e3c4..5057c38 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -632,7 +632,7 @@
return;
}
mModalness = modalness;
- mIconView.setContentAlpha(1 - modalness);
+ mIconView.setModalAlpha(1 - modalness);
mDigitalWellBeingToast.updateBannerOffset(modalness);
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskViewIcon.java b/quickstep/src/com/android/quickstep/views/TaskViewIcon.java
index 4e82725..94739cb 100644
--- a/quickstep/src/com/android/quickstep/views/TaskViewIcon.java
+++ b/quickstep/src/com/android/quickstep/views/TaskViewIcon.java
@@ -43,6 +43,11 @@
void setContentAlpha(float alpha);
/**
+ * Sets the opacity of the view for modal state.
+ */
+ void setModalAlpha(float alpha);
+
+ /**
* Returns this icon view's drawable.
*/
@Nullable Drawable getDrawable();
diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
index b12d98b..37dde10 100644
--- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
+++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
@@ -26,6 +26,8 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -36,11 +38,14 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.text.TextUtils;
+import androidx.test.core.content.pm.ApplicationInfoBuilder;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.launcher3.Flags;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
import com.android.launcher3.util.LauncherLayoutBuilder;
@@ -50,6 +55,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -61,6 +67,9 @@
@RunWith(AndroidJUnit4.class)
public final class WidgetsPredicationUpdateTaskTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private AppWidgetProviderInfo mApp1Provider1;
private AppWidgetProviderInfo mApp1Provider2;
private AppWidgetProviderInfo mApp2Provider1;
@@ -75,6 +84,7 @@
@Before
public void setup() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_CATEGORIZED_WIDGET_SUGGESTIONS);
mModelHelper = new LauncherModelHelper();
mUserHandle = myUserHandle();
@@ -93,6 +103,12 @@
allWidgets = Arrays.asList(mApp1Provider1, mApp1Provider2, mApp2Provider1,
mApp4Provider1, mApp4Provider2, mApp5Provider1);
+ doAnswer(i -> {
+ String pkg = i.getArgument(0);
+ return ApplicationInfoBuilder.newBuilder().setPackageName(pkg).setName(
+ "App " + pkg).build();
+ }).when(mModelHelper.sandboxContext.getPackageManager())
+ .getApplicationInfo(anyString(), anyInt());
AppWidgetManager manager = mModelHelper.sandboxContext.spyService(AppWidgetManager.class);
doReturn(allWidgets).when(manager).getInstalledProviders();
doReturn(allWidgets).when(manager).getInstalledProvidersForProfile(eq(myUserHandle()));
@@ -140,12 +156,16 @@
// 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
// excluded from the result.
// 2. app3 doesn't have a widget.
- // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
+ // 3. only 1 widget is picked from app1 because we only want to promote one widget
+ // per app.
List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
.stream()
.map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
.collect(Collectors.toList());
assertThat(recommendedWidgets).hasSize(2);
+ recommendedWidgets.forEach(pendingAddWidgetInfo ->
+ assertThat(pendingAddWidgetInfo.recommendationCategory).isNotNull()
+ );
assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
});
@@ -179,6 +199,9 @@
.map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
.collect(Collectors.toList());
assertThat(recommendedWidgets).hasSize(2);
+ recommendedWidgets.forEach(pendingAddWidgetInfo ->
+ assertThat(pendingAddWidgetInfo.recommendationCategory).isNotNull()
+ );
// Another widget from the same package
assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
@@ -192,7 +215,7 @@
}
private WidgetsPredictionUpdateTask newWidgetsPredicationTask(List<AppTarget> appTargets) {
- return new WidgetsPredictionUpdateTask(
+ return new WidgetsPredictionUpdateTask(
new PredictorState(CONTAINER_WIDGETS_PREDICTION, "test_widgets_prediction"),
appTargets);
}
diff --git a/quickstep/tests/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchControllerTest.kt b/quickstep/tests/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchControllerTest.kt
new file mode 100644
index 0000000..119b862
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchControllerTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides.touchcontrollers
+
+import android.view.MotionEvent
+import android.view.WindowManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.Launcher
+import com.android.launcher3.ui.AbstractLauncherUiTest
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class StatusBarTouchControllerTest : AbstractLauncherUiTest() {
+ @Before
+ @Throws(Exception::class)
+ fun setup() {
+ super.setUp()
+ initialize(this)
+ }
+
+ @Test
+ fun interceptActionDown_canIntercept() {
+ executeOnLauncher { launcher ->
+ val underTest = StatusBarTouchController(launcher)
+ assertFalse(underTest.mCanIntercept)
+ val downEvent = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
+
+ underTest.onControllerInterceptTouchEvent(downEvent)
+
+ assertTrue(underTest.mCanIntercept)
+ }
+ }
+
+ @Test
+ fun interceptVerticalActionMove_handledAndSetSlippery() {
+ executeOnLauncher { launcher ->
+ val underTest = StatusBarTouchController(launcher)
+ val downEvent = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
+ underTest.onControllerInterceptTouchEvent(downEvent)
+ val w = launcher.window
+ assertEquals(0, w.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY)
+ val moveEvent =
+ MotionEvent.obtain(
+ 2,
+ 2,
+ MotionEvent.ACTION_MOVE,
+ underTest.mTouchSlop,
+ underTest.mTouchSlop + 10,
+ 0
+ )
+
+ val handled = underTest.onControllerInterceptTouchEvent(moveEvent)
+
+ assertTrue(handled)
+ assertEquals(
+ WindowManager.LayoutParams.FLAG_SLIPPERY,
+ w.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY
+ )
+ }
+ }
+
+ @Test
+ fun interceptHorizontalActionMove_not_handled() {
+ executeOnLauncher { launcher ->
+ val underTest = StatusBarTouchController(launcher)
+ val downEvent = MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
+ underTest.onControllerInterceptTouchEvent(downEvent)
+ val moveEvent =
+ MotionEvent.obtain(
+ 2,
+ 2,
+ MotionEvent.ACTION_MOVE,
+ underTest.mTouchSlop + 10,
+ underTest.mTouchSlop,
+ 0
+ )
+
+ val handled = underTest.onControllerInterceptTouchEvent(moveEvent)
+
+ assertFalse(handled)
+ }
+ }
+
+ @Test
+ fun interceptActionMoveAsFirstGestureEvent_notCrashedNorHandled() {
+ executeOnLauncher { launcher ->
+ val underTest = StatusBarTouchController(launcher)
+ underTest.mCanIntercept = true
+ val moveEvent = MotionEvent.obtain(2, 2, MotionEvent.ACTION_MOVE, 10f, 10f, 0)
+
+ val handled = underTest.onControllerInterceptTouchEvent(moveEvent)
+
+ assertFalse(handled)
+ }
+ }
+
+ @Test
+ fun handleActionUp_setNotSlippery() {
+ executeOnLauncher { launcher: Launcher ->
+ val underTest = StatusBarTouchController(launcher)
+ underTest.mCanIntercept = true
+ underTest.setWindowSlippery(true)
+ val moveEvent = MotionEvent.obtain(2, 2, MotionEvent.ACTION_UP, 10f, 10f, 0)
+
+ val handled = underTest.onControllerTouchEvent(moveEvent)
+
+ assertTrue(handled)
+ assertEquals(
+ 0,
+ launcher.window.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY
+ )
+ }
+ }
+
+ @Test
+ fun handleActionCancel_setNotSlippery() {
+ executeOnLauncher { launcher ->
+ val underTest = StatusBarTouchController(launcher)
+ underTest.mCanIntercept = true
+ underTest.setWindowSlippery(true)
+ val moveEvent = MotionEvent.obtain(2, 2, MotionEvent.ACTION_CANCEL, 10f, 10f, 0)
+
+ val handled = underTest.onControllerTouchEvent(moveEvent)
+
+ assertTrue(handled)
+ assertEquals(
+ 0,
+ launcher.window.attributes.flags and WindowManager.LayoutParams.FLAG_SLIPPERY
+ )
+ }
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
index 3f806d1..7c1b7f3 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.ui.AbstractLauncherUiTest.initialize;
import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
@@ -25,6 +24,7 @@
import android.content.Intent;
import android.platform.test.annotations.PlatinumTest;
+import com.android.launcher3.tapl.OverviewTask.OverviewSplitTask;
import com.android.launcher3.tapl.OverviewTaskMenu;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.rule.TestStabilityRule;
@@ -86,7 +86,8 @@
taskMenu.touchOutsideTaskMenuToDismiss();
OverviewTaskMenu splitMenu =
- mLauncher.goHome().switchToOverview().getCurrentTask().tapSplitTaskMenu();
+ mLauncher.goHome().switchToOverview().getCurrentTask().tapMenu(
+ OverviewSplitTask.SPLIT_BOTTOM_OR_RIGHT);
assertTrue("App info item not appearing in expanded split task's menu.",
splitMenu.hasMenuItem("App info"));
splitMenu.touchOutsideTaskMenuToDismiss();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java b/quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java
index 36c591e..a050464 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java
@@ -22,6 +22,8 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.tapl.KeyboardQuickSwitch;
+import com.android.launcher3.tapl.LaunchedAppState;
+import com.android.launcher3.tapl.Taskbar;
import com.android.launcher3.taskbar.KeyboardQuickSwitchController;
import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -36,6 +38,7 @@
private enum TestSurface {
HOME(true),
LAUNCHED_APP(false),
+ TASKBAR_ALL_APPS(false),
HOME_ALL_APPS(true),
WIDGETS(true);
@@ -82,6 +85,11 @@
}
@Test
+ public void testDismiss_fromTaskbarAllApps() {
+ runTest(TestSurface.TASKBAR_ALL_APPS, TestCase.DISMISS);
+ }
+
+ @Test
public void testDismiss_fromHomeAllApps() {
runTest(TestSurface.HOME_ALL_APPS, TestCase.DISMISS);
}
@@ -102,6 +110,11 @@
}
@Test
+ public void testLaunchLastTask_fromTaskbarAllApps() {
+ runTest(TestSurface.TASKBAR_ALL_APPS, TestCase.LAUNCH_LAST_APP);
+ }
+
+ @Test
public void testLaunchLastTask_fromHomeAllApps() {
runTest(TestSurface.HOME_ALL_APPS, TestCase.LAUNCH_LAST_APP);
}
@@ -122,6 +135,11 @@
}
@Test
+ public void testLaunchSelectedTask_fromTaskbarAllApps() {
+ runTest(TestSurface.TASKBAR_ALL_APPS, TestCase.LAUNCH_SELECTED_APP);
+ }
+
+ @Test
public void testLaunchSelectedTask_fromHomeAllApps() {
runTest(TestSurface.HOME_ALL_APPS, TestCase.LAUNCH_SELECTED_APP);
}
@@ -142,6 +160,11 @@
}
@Test
+ public void testLaunchOverviewTask_fromTaskbarAllApps() {
+ runTest(TestSurface.TASKBAR_ALL_APPS, TestCase.LAUNCH_OVERVIEW);
+ }
+
+ @Test
public void testLaunchOverviewTask_fromHomeAllApps() {
runTest(TestSurface.HOME_ALL_APPS, TestCase.LAUNCH_OVERVIEW);
}
@@ -165,6 +188,12 @@
mLauncher.setIgnoreTaskbarVisibility(true);
kqs = mLauncher.getLaunchedAppState().showQuickSwitchView();
break;
+ case TASKBAR_ALL_APPS:
+ LaunchedAppState launchedApp = mLauncher.getLaunchedAppState();
+ Taskbar taskbar = mLauncher.isTransientTaskbar()
+ ? launchedApp.swipeUpToUnstashTaskbar() : launchedApp.getTaskbar();
+ kqs = taskbar.openAllApps().showQuickSwitchView();
+ break;
case HOME_ALL_APPS:
kqs = mLauncher.goHome().switchToAllApps().showQuickSwitchView();
break;
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index fcb8320..360d1a7 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -35,9 +35,9 @@
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.Until;
+import com.android.launcher3.Flags;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
import com.android.launcher3.tapl.Overview;
@@ -394,7 +394,7 @@
READ_DEVICE_CONFIG_PERMISSION);
// Debug if we need to goHome to prevent wrong previous state b/315525621
mLauncher.goHome();
- assumeFalse(FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get());
+ assumeFalse(Flags.enablePredictiveBackGesture());
mLauncher.getWorkspace().switchToAllApps().pressBackToWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index 1e33635..b7546c7 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -16,6 +16,7 @@
package com.android.quickstep;
+import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
@@ -40,6 +41,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -103,10 +105,18 @@
.getSplitScreenMenuItem()
.click();
- mLauncher.getLaunchedAppState()
- .getTaskbar()
- .getAppIcon(CALCULATOR_APP_NAME)
- .launchIntoSplitScreen();
+ if (enableSplitContextually()) {
+ // We're staying in all apps, use same instance
+ mLauncher.getAllApps()
+ .getAppIcon(CALCULATOR_APP_NAME)
+ .launchIntoSplitScreen();
+ } else {
+ // We're in overview, use taskbar instance
+ mLauncher.getLaunchedAppState()
+ .getTaskbar()
+ .getAppIcon(CALCULATOR_APP_NAME)
+ .launchIntoSplitScreen();
+ }
}
@Test
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index 3465f23..b0e91e4 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -28,7 +28,7 @@
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.Flags;
import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -77,7 +77,7 @@
@NavigationModeSwitch(mode = ZERO_BUTTON)
public void pressBack() throws Exception {
assumeTrue(mLauncher.isTablet());
- assumeFalse(FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get());
+ assumeFalse(Flags.enablePredictiveBackGesture());
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
try {
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
index b365173..9fa4b79 100644
--- a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -163,8 +163,7 @@
helper.sandboxContext.allow(SystemUiProxy.INSTANCE);
int rotation = mDisplaySize.x > mDisplaySize.y
? Surface.ROTATION_90 : Surface.ROTATION_0;
- CachedDisplayInfo cdi =
- new CachedDisplayInfo(mDisplaySize, rotation, new Rect());
+ CachedDisplayInfo cdi = new CachedDisplayInfo(mDisplaySize, rotation);
WindowBounds wm = new WindowBounds(
new Rect(0, 0, mDisplaySize.x, mDisplaySize.y),
mDisplayInsets);
@@ -186,7 +185,7 @@
ArrayMap<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache =
new ArrayMap<>();
- perDisplayBoundsCache.put(cdi.normalize(), allBounds);
+ perDisplayBoundsCache.put(cdi.normalize(wmProxy), allBounds);
Configuration configuration = new Configuration();
configuration.densityDpi = mDensityDpi;
diff --git a/res/drawable/ic_encrypted_with_background.xml b/res/drawable/ic_private_space_with_background.xml
similarity index 65%
rename from res/drawable/ic_encrypted_with_background.xml
rename to res/drawable/ic_private_space_with_background.xml
index c439b55..59a33dd 100644
--- a/res/drawable/ic_encrypted_with_background.xml
+++ b/res/drawable/ic_private_space_with_background.xml
@@ -21,6 +21,9 @@
android:pathData="M48 24A24 24 0 0 1 0 24A24 24 0 0 1 48 24Z"
android:fillColor="?attr/materialColorOutlineVariant" />
<path
- android:pathData="M24.0002 10.667L13.3335 14.667V22.787C13.3335 29.5203 17.8802 35.8003 24.0002 37.3337C30.1202 35.8003 34.6668 29.5203 34.6668 22.787V14.667L24.0002 10.667ZM32.0002 22.787C32.0002 28.1203 28.6002 33.0537 24.0002 34.5603C19.4002 33.0537 16.0002 28.1337 16.0002 22.787V16.5203L24.0002 13.5203L32.0002 16.5203V22.787ZM25.2402 23.6937L26.0002 28.0003H22.0002L22.7602 23.6937C21.9068 23.2537 21.3335 22.3603 21.3335 21.3337C21.3335 19.867 22.5335 18.667 24.0002 18.667C25.4668 18.667 26.6668 19.867 26.6668 21.3337C26.6668 22.3603 26.0935 23.2537 25.2402 23.6937Z"
+ android:pathData="M33.3333 14.6667V33.3333H14.6667V14.6667H33.3333ZM33.3333 12H14.6667C13.2 12 12 13.2 12 14.6667V33.3333C12 34.8 13.2 36 14.6667 36H33.3333C34.8 36 36 34.8 36 33.3333V14.6667C36 13.2 34.8 12 33.3333 12Z"
+ android:fillColor="?attr/materialColorOnSurface" />
+ <path
+ android:pathData="M25.2397 24.3597L25.9997 28.6663H21.9997L22.7597 24.3597C21.9063 23.9197 21.333 23.0263 21.333 21.9997C21.333 20.533 22.533 19.333 23.9997 19.333C25.4663 19.333 26.6663 20.533 26.6663 21.9997C26.6663 23.0263 26.093 23.9197 25.2397 24.3597Z"
android:fillColor="?attr/materialColorOnSurface" />
</vector>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index baa1ee3..2f0c096 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -213,6 +213,7 @@
mIsRtl = (getResources().getConfiguration().getLayoutDirection()
== View.LAYOUT_DIRECTION_RTL);
mDeviceProfile = mActivity.getDeviceProfile();
+ mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
mDisplay = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
final int defaultIconSize;
@@ -243,7 +244,6 @@
defaultIconSize = mDeviceProfile.iconSizePx;
}
- mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
mIconSize = a.getDimensionPixelSize(R.styleable.BubbleTextView_iconSizeOverride,
defaultIconSize);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index e9545c8..bf4f6c3 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1010,7 +1010,7 @@
* Returns the amount of extra (or unused) vertical space.
*/
private int updateAvailableDimensions(Resources res) {
- iconCenterVertically = mIsScalableGrid || mIsResponsiveGrid;
+ iconCenterVertically = (mIsScalableGrid || mIsResponsiveGrid) && isVerticalBarLayout();
if (mIsResponsiveGrid) {
iconSizePx = mResponsiveWorkspaceCellSpec.getIconSize();
@@ -1738,15 +1738,8 @@
// The hotseat icons will be placed in the middle of the hotseat cells.
// Changing the hotseatCellHeightPx is not affecting hotseat icon positions
// in vertical bar layout.
- // Workspace icons are moved up by a small factor. The variable diffOverlapFactor
- // is set to account for that difference.
- float diffOverlapFactor = mIsResponsiveGrid ? 0
- : iconSizePx * (ICON_OVERLAP_FACTOR - 1) / 2;
-
- int paddingTop = Math.max((int) (mInsets.top + cellLayoutPaddingPx.top
- - diffOverlapFactor), 0);
- int paddingBottom = Math.max((int) (mInsets.bottom + cellLayoutPaddingPx.bottom
- + diffOverlapFactor), 0);
+ int paddingTop = Math.max((int) (mInsets.top + cellLayoutPaddingPx.top), 0);
+ int paddingBottom = Math.max((int) (mInsets.bottom + cellLayoutPaddingPx.bottom), 0);
if (isSeascape()) {
hotseatBarPadding.set(mInsets.left + mHotseatBarEdgePaddingPx, paddingTop,
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 1b2cebd..60a6be6 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -34,6 +34,7 @@
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ArchiveCompatibilityParams;
import android.os.UserHandle;
import android.util.Log;
@@ -108,9 +109,11 @@
launcherApps.registerCallback(callbacks);
mOnTerminateCallback.add(() ->
mContext.getSystemService(LauncherApps.class).unregisterCallback(callbacks));
- if (Flags.enableSupportForArchiving()) {
- launcherApps.setArchiveCompatibilityOptions(/* enableIconOverlay= */ true,
- /* enableUnarchivalConfirmation= */ false);
+
+ if (Utilities.enableSupportForArchiving()) {
+ ArchiveCompatibilityParams params = new ArchiveCompatibilityParams();
+ params.setEnableUnarchivalConfirmation(false);
+ launcherApps.setArchiveCompatibility(params);
}
SimpleBroadcastReceiver modelChangeReceiver =
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 2b886e4..d44438f 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -830,4 +830,10 @@
// No-Op
}
}
+
+ /** Encapsulates two flag checks into a single one. */
+ public static boolean enableSupportForArchiving() {
+ return Flags.enableSupportForArchiving()
+ || getSystemProperty("pm.archiving.enabled", "false").equals("true");
+ }
}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index e65e614..a846e68 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -415,6 +415,8 @@
screenId, coordinates[0], coordinates[1]);
bindItem(info, accessibility);
} else if (item instanceof FolderInfo fi) {
+ Workspace<?> workspace = mContext.getWorkspace();
+ workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
mContext.getModelWriter().addItemToDatabase(fi,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screenId, coordinates[0],
coordinates[1]);
diff --git a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java b/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
index bc55597..fcdfaa6 100644
--- a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
+++ b/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
@@ -55,6 +55,9 @@
assert quietModeButton != null;
addQuietModeButton(quietModeButton);
+ //Trigger lock/unlock action from header.
+ addHeaderOnClickListener(parent);
+
//Add image and action for private space settings button
ImageButton settingsButton = parent.findViewById(R.id.ps_settings_button);
assert settingsButton != null;
@@ -71,26 +74,35 @@
case STATE_ENABLED -> {
quietModeButton.setVisibility(View.VISIBLE);
quietModeButton.setImageResource(R.drawable.bg_ps_lock_button);
- quietModeButton.setOnClickListener(
- view -> {
- mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_LOCK_TAP);
- mPrivateProfileManager.lockPrivateProfile();
- });
+ quietModeButton.setOnClickListener(view -> lockAction());
}
case STATE_DISABLED -> {
quietModeButton.setVisibility(View.VISIBLE);
quietModeButton.setImageResource(R.drawable.bg_ps_unlock_button);
- quietModeButton.setOnClickListener(
- view -> {
- mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP);
- mPrivateProfileManager.unlockPrivateProfile((this::
- onPrivateProfileUnlocked));
- });
+ quietModeButton.setOnClickListener(view -> unLockAction());
}
default -> quietModeButton.setVisibility(View.GONE);
}
}
+ private void addHeaderOnClickListener(RelativeLayout header) {
+ if (mPrivateProfileManager.getCurrentState() == STATE_DISABLED) {
+ header.setOnClickListener(view -> unLockAction());
+ } else {
+ header.setOnClickListener(null);
+ }
+ }
+
+ private void unLockAction() {
+ mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP);
+ mPrivateProfileManager.unlockPrivateProfile((this::onPrivateProfileUnlocked));
+ }
+
+ private void lockAction() {
+ mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_LOCK_TAP);
+ mPrivateProfileManager.lockPrivateProfile();
+ }
+
private void addPrivateSpaceSettingsButton(ImageButton settingsButton) {
if (mPrivateProfileManager.getCurrentState() == STATE_ENABLED
&& mPrivateProfileManager.isPrivateSpaceSettingsAvailable()) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 40c368b..e2902e9 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -199,11 +199,6 @@
"ENABLE_SMARTSPACE_REMOVAL", DISABLED, "Enable SmartSpace removal for "
+ "home screen");
- // TODO(Block 10): Clean up flags
- public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790,
- "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED,
- "Enables predictive back animation from all apps and widgets to home");
-
// TODO(Block 11): Clean up flags
public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274,
"FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace");
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index f058ae4..284b31e 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -29,6 +29,7 @@
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -633,6 +634,20 @@
}
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ boolean shouldCenterIcon = mActivity.getDeviceProfile().iconCenterVertically;
+ if (shouldCenterIcon) {
+ int iconSize = mActivity.getDeviceProfile().iconSizePx;
+ Paint.FontMetrics fm = mFolderName.getPaint().getFontMetrics();
+ int cellHeightPx = iconSize + mFolderName.getCompoundDrawablePadding()
+ + (int) Math.ceil(fm.bottom - fm.top);
+ setPadding(getPaddingLeft(), (MeasureSpec.getSize(heightMeasureSpec)
+ - cellHeightPx) / 2, getPaddingRight(), getPaddingBottom());
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
/** Sets the visibility of the icon's title text */
public void setTextVisible(boolean visible) {
if (visible) {
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index b41f011..8659471 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -16,7 +16,6 @@
package com.android.launcher3.model;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ARCHIVED;
@@ -34,6 +33,7 @@
import androidx.annotation.Nullable;
import com.android.launcher3.AppFilter;
+import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.BgDataModel.Callbacks;
@@ -330,7 +330,7 @@
PackageManagerHelper.getLoadingProgress(info),
PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
applicationInfo.intent = launchIntent;
- if (enableSupportForArchiving()) {
+ if (Utilities.enableSupportForArchiving()) {
// In case an app is archived, the respective item flag corresponding to
// archiving should also be applied during package updates
if (info.getActivityInfo().isArchived) {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 736b80a..71ab51c 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN;
import static com.android.launcher3.Flags.enableLauncherBrMetricsFixed;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE;
import static com.android.launcher3.LauncherPrefs.SHOULD_SHOW_SMARTSPACE;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
@@ -421,7 +420,7 @@
final HashMap<PackageUserKey, SessionInfo> installingPkgs =
mSessionHelper.getActiveSessions();
- if (enableSupportForArchiving()) {
+ if (Utilities.enableSupportForArchiving()) {
mInstallingPkgsCached = installingPkgs;
}
installingPkgs.forEach(mApp.getIconCache()::updateSessionCache);
@@ -656,7 +655,7 @@
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfo app = apps.get(i);
AppInfo appInfo = new AppInfo(app, mUserCache.getUserInfo(user), quietMode);
- if (enableSupportForArchiving() && app.getApplicationInfo().isArchived) {
+ if (Utilities.enableSupportForArchiving() && app.getApplicationInfo().isArchived) {
// For archived apps, include progress info in case there is a pending
// install session post restart of device.
String appPackageName = app.getApplicationInfo().packageName;
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 529a8f9..a41b663 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.model;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
@@ -39,6 +38,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.logging.FileLog;
@@ -274,7 +274,7 @@
PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
// In case an app is archived, we need to make sure that archived state
// in WorkspaceItemInfo is refreshed.
- if (enableSupportForArchiving() && !activities.isEmpty()) {
+ if (Utilities.enableSupportForArchiving() && !activities.isEmpty()) {
boolean newArchivalState = activities.get(
0).getActivityInfo().isArchived;
if (newArchivalState != si.isArchived()) {
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index 44c41c1..31ae7c2 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -26,7 +26,6 @@
import android.text.TextUtils
import android.util.Log
import android.util.LongSparseArray
-import com.android.launcher3.Flags
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherAppState
import com.android.launcher3.LauncherSettings.Favorites
@@ -323,7 +322,7 @@
}
if (
(c.restoreFlag != 0 ||
- Flags.enableSupportForArchiving() &&
+ Utilities.enableSupportForArchiving() &&
activityInfo != null &&
activityInfo.applicationInfo.isArchived) && !TextUtils.isEmpty(targetPkg)
) {
@@ -338,7 +337,7 @@
null // For archived apps, include progress info in case there is
// a pending install session post restart of device.
||
- (Flags.enableSupportForArchiving() &&
+ (Utilities.enableSupportForArchiving() &&
activityInfo.applicationInfo.isArchived)
) {
val installProgress = (si.getProgress() * 100).toInt()
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 72eda6c..b213fe3 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -16,7 +16,6 @@
package com.android.launcher3.model.data;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
import android.content.ComponentName;
@@ -179,7 +178,7 @@
if (PackageManagerHelper.isAppSuspended(appInfo)) {
info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
}
- if (enableSupportForArchiving() && lai.getActivityInfo().isArchived) {
+ if (Utilities.enableSupportForArchiving() && lai.getActivityInfo().isArchived) {
info.runtimeStatusFlags |= FLAG_ARCHIVED;
}
info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index c8ab09c..e46c502 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -16,14 +16,13 @@
package com.android.launcher3.model.data;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
-
import android.content.Context;
import android.content.Intent;
import android.os.Process;
import androidx.annotation.Nullable;
+import com.android.launcher3.Utilities;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -158,7 +157,7 @@
/**
* Returns true if the app corresponding to the item is archived. */
public boolean isArchived() {
- if (!enableSupportForArchiving()) {
+ if (!Utilities.enableSupportForArchiving()) {
return false;
}
return (runtimeStatusFlags & FLAG_ARCHIVED) != 0;
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index fd1b64f..df369c6 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -365,6 +365,13 @@
@Override
public void setMarkersCount(int numMarkers) {
mNumPages = numMarkers;
+
+ // If the last page gets removed we want to go to the previous page.
+ if (mNumPages == mActivePage) {
+ mActivePage--;
+ CURRENT_POSITION.set(this, (float) mActivePage);
+ }
+
requestLayout();
}
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 0d47462..605ef16 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -16,8 +16,6 @@
package com.android.launcher3.pm;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
-
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
@@ -33,6 +31,7 @@
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.SessionCommitReceiver;
+import com.android.launcher3.Utilities;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.util.IntArray;
@@ -228,7 +227,8 @@
public boolean verifySessionInfo(@Nullable final PackageInstaller.SessionInfo sessionInfo) {
// For archived apps we always want to show promise icons and the checks below don't apply.
- if (enableSupportForArchiving() && sessionInfo != null && sessionInfo.isUnarchival()) {
+ if (Utilities.enableSupportForArchiving() && sessionInfo != null
+ && sessionInfo.isUnarchival()) {
return true;
}
diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java
index e4a2045..eacbc11 100644
--- a/src/com/android/launcher3/pm/InstallSessionTracker.java
+++ b/src/com/android/launcher3/pm/InstallSessionTracker.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.pm;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle;
import static com.android.launcher3.pm.PackageInstallInfo.STATUS_FAILED;
import static com.android.launcher3.pm.PackageInstallInfo.STATUS_INSTALLED;
@@ -32,6 +31,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.launcher3.Utilities;
import com.android.launcher3.util.PackageUserKey;
import java.lang.ref.WeakReference;
@@ -80,7 +80,8 @@
helper.tryQueuePromiseAppIcon(sessionInfo);
- if (enableSupportForArchiving() && sessionInfo != null && sessionInfo.isUnarchival()) {
+ if (Utilities.enableSupportForArchiving() && sessionInfo != null
+ && sessionInfo.isUnarchival()) {
// For archived apps, icon could already be present on the workspace. To make sure
// the icon state is updated, we send a change event.
callback.onPackageStateChanged(PackageInstallInfo.fromInstallingState(sessionInfo));
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 5f17959..f1d837c 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -31,8 +31,10 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.ShortcutUtil;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
+import com.android.launcher3.widget.picker.WidgetRecommendationCategory;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -41,6 +43,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -218,6 +221,32 @@
.collect(Collectors.toList());
}
+ /** Returns the recommended widgets mapped by their category. */
+ public Map<WidgetRecommendationCategory, List<WidgetItem>> getCategorizedRecommendedWidgets() {
+ Map<ComponentKey, WidgetItem> allWidgetItems = mAllWidgets.stream()
+ .filter(entry -> entry instanceof WidgetsListContentEntry)
+ .flatMap(entry -> entry.mWidgets.stream())
+ .distinct()
+ .collect(Collectors.toMap(
+ widget -> new ComponentKey(widget.componentName, widget.user),
+ Function.identity()
+ ));
+ return mRecommendedWidgets.stream()
+ .filter(itemInfo -> itemInfo instanceof PendingAddWidgetInfo)
+ .collect(Collectors.groupingBy(
+ it -> ((PendingAddWidgetInfo) it).recommendationCategory,
+ Collectors.collectingAndThen(
+ Collectors.toList(),
+ list -> list.stream()
+ .map(it -> allWidgetItems.get(
+ new ComponentKey(it.getTargetComponent(),
+ it.user)))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList())
+ )
+ ));
+ }
+
public List<WidgetItem> getWidgetsForPackageUser(PackageUserKey packageUserKey) {
return mAllWidgets.stream()
.filter(row -> row instanceof WidgetsListContentEntry
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 5636405..1623ad8 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
+import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
+import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.app.Activity;
@@ -208,6 +210,11 @@
return response;
}
+ case TestProtocol.REQUEST_GET_SPLIT_SELECTION_ACTIVE:
+ response.putBoolean(TEST_INFO_RESPONSE_FIELD, enableSplitContextually()
+ && Launcher.ACTIVITY_TRACKER.getCreatedActivity().isSplitSelectionActive());
+ return response;
+
case TestProtocol.REQUEST_ENABLE_ROTATION:
MAIN_EXECUTOR.submit(() ->
Launcher.ACTIVITY_TRACKER.getCreatedActivity().getRotationHelper()
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index f47ab90..ded4da6 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.touch;
-import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_BIND_PENDING_APPWIDGET;
import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_RECONFIGURE_APPWIDGET;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
@@ -331,7 +330,7 @@
// Check for abandoned promise
if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()
- && (!enableSupportForArchiving() || !shortcut.isArchived())) {
+ && (!Utilities.enableSupportForArchiving() || !shortcut.isArchived())) {
String packageName = shortcut.getIntent().getComponent() != null
? shortcut.getIntent().getComponent().getPackageName()
: shortcut.getIntent().getPackage();
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 1419dc4..ff95212 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -362,10 +362,10 @@
WindowManagerProxy wmProxy,
Map<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache) {
CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(displayInfoContext);
- normalizedDisplayInfo = displayInfo.normalize();
+ normalizedDisplayInfo = displayInfo.normalize(wmProxy);
rotation = displayInfo.rotation;
currentSize = displayInfo.size;
- cutout = displayInfo.cutout;
+ cutout = WindowManagerProxy.getSafeInsets(displayInfo.cutout);
Configuration config = displayInfoContext.getResources().getConfiguration();
fontScale = config.fontScale;
diff --git a/src/com/android/launcher3/util/window/CachedDisplayInfo.java b/src/com/android/launcher3/util/window/CachedDisplayInfo.java
index 23f37aa..c5084ad 100644
--- a/src/com/android/launcher3/util/window/CachedDisplayInfo.java
+++ b/src/com/android/launcher3/util/window/CachedDisplayInfo.java
@@ -16,13 +16,16 @@
package com.android.launcher3.util.window;
import static com.android.launcher3.util.RotationUtils.deltaRotation;
-import static com.android.launcher3.util.RotationUtils.rotateRect;
import static com.android.launcher3.util.RotationUtils.rotateSize;
+import android.graphics.Insets;
import android.graphics.Point;
-import android.graphics.Rect;
+import android.view.DisplayCutout;
import android.view.Surface;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.util.Objects;
/**
@@ -30,36 +33,40 @@
*/
public class CachedDisplayInfo {
+ private static final DisplayCutout NO_CUTOUT =
+ new DisplayCutout(Insets.NONE, null, null, null, null);
+
public final Point size;
public final int rotation;
- public final Rect cutout;
+ @NonNull
+ public final DisplayCutout cutout;
public CachedDisplayInfo() {
this(new Point(0, 0), 0);
}
public CachedDisplayInfo(Point size, int rotation) {
- this(size, rotation, new Rect());
+ this(size, rotation, NO_CUTOUT);
}
- public CachedDisplayInfo(Point size, int rotation, Rect cutout) {
+ public CachedDisplayInfo(Point size, int rotation, @Nullable DisplayCutout cutout) {
this.size = size;
this.rotation = rotation;
- this.cutout = cutout;
+ this.cutout = cutout == null ? NO_CUTOUT : cutout;
}
/**
* Returns a CachedDisplayInfo where the properties are normalized to {@link Surface#ROTATION_0}
*/
- public CachedDisplayInfo normalize() {
+ public CachedDisplayInfo normalize(WindowManagerProxy windowManagerProxy) {
if (rotation == Surface.ROTATION_0) {
return this;
}
Point newSize = new Point(size);
rotateSize(newSize, deltaRotation(rotation, Surface.ROTATION_0));
- Rect newCutout = new Rect(cutout);
- rotateRect(newCutout, deltaRotation(rotation, Surface.ROTATION_0));
+ DisplayCutout newCutout = windowManagerProxy.rotateCutout(
+ cutout, size.x, size.y, rotation, Surface.ROTATION_0);
return new CachedDisplayInfo(newSize, Surface.ROTATION_0, newCutout);
}
@@ -79,11 +86,16 @@
CachedDisplayInfo that = (CachedDisplayInfo) o;
return rotation == that.rotation
&& Objects.equals(size, that.size)
- && Objects.equals(cutout, that.cutout);
+ && cutout.getSafeInsetLeft() == that.cutout.getSafeInsetLeft()
+ && cutout.getSafeInsetTop() == that.cutout.getSafeInsetTop()
+ && cutout.getSafeInsetRight() == that.cutout.getSafeInsetRight()
+ && cutout.getSafeInsetBottom() == that.cutout.getSafeInsetBottom();
}
@Override
public int hashCode() {
- return Objects.hash(size, rotation, cutout);
+ return Objects.hash(size, rotation,
+ cutout.getSafeInsetLeft(), cutout.getSafeInsetTop(),
+ cutout.getSafeInsetRight(), cutout.getSafeInsetBottom());
}
}
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 209a3dc..32f1736 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -95,7 +95,7 @@
*/
public ArrayMap<CachedDisplayInfo, List<WindowBounds>> estimateInternalDisplayBounds(
Context displayInfoContext) {
- CachedDisplayInfo info = getDisplayInfo(displayInfoContext).normalize();
+ CachedDisplayInfo info = getDisplayInfo(displayInfoContext).normalize(this);
List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
ArrayMap<CachedDisplayInfo, List<WindowBounds>> result = new ArrayMap<>();
result.put(info, bounds);
@@ -186,10 +186,9 @@
* Returns a list of possible WindowBounds for the display keyed on the 4 surface rotations
*/
protected List<WindowBounds> estimateWindowBounds(Context context,
- CachedDisplayInfo displayInfo) {
+ final CachedDisplayInfo displayInfo) {
int densityDpi = context.getResources().getConfiguration().densityDpi;
- int rotation = displayInfo.rotation;
- Rect safeCutout = displayInfo.cutout;
+ final int rotation = displayInfo.rotation;
int minSize = Math.min(displayInfo.size.x, displayInfo.size.y);
int swDp = (int) dpiFromPx(minSize, densityDpi);
@@ -247,8 +246,9 @@
statusBarHeight = statusBarHeightLandscape;
}
- Rect insets = new Rect(safeCutout);
- rotateRect(insets, rotationChange);
+ DisplayCutout rotatedCutout = rotateCutout(
+ displayInfo.cutout, displayInfo.size.x, displayInfo.size.y, rotation, i);
+ Rect insets = getSafeInsets(rotatedCutout);
insets.top = Math.max(insets.top, statusBarHeight);
insets.bottom = Math.max(insets.bottom, navBarHeight);
@@ -298,8 +298,7 @@
Point size = new Point();
Display display = getDisplay(displayInfoContext);
display.getRealSize(size);
- Rect cutoutRect = new Rect();
- return new CachedDisplayInfo(size, rotation, cutoutRect);
+ return new CachedDisplayInfo(size, rotation);
}
}
@@ -309,13 +308,8 @@
@TargetApi(Build.VERSION_CODES.S)
protected CachedDisplayInfo getDisplayInfo(WindowMetrics windowMetrics, int rotation) {
Point size = new Point(windowMetrics.getBounds().right, windowMetrics.getBounds().bottom);
- Rect cutoutRect = new Rect();
- DisplayCutout cutout = windowMetrics.getWindowInsets().getDisplayCutout();
- if (cutout != null) {
- cutoutRect.set(cutout.getSafeInsetLeft(), cutout.getSafeInsetTop(),
- cutout.getSafeInsetRight(), cutout.getSafeInsetBottom());
- }
- return new CachedDisplayInfo(size, rotation, cutoutRect);
+ return new CachedDisplayInfo(size, rotation,
+ windowMetrics.getWindowInsets().getDisplayCutout());
}
/**
@@ -355,6 +349,16 @@
}
/**
+ * Returns a DisplayCutout which represents a rotated version of the original
+ */
+ protected DisplayCutout rotateCutout(DisplayCutout original, int startWidth, int startHeight,
+ int fromRotation, int toRotation) {
+ Rect safeCutout = getSafeInsets(original);
+ rotateRect(safeCutout, deltaRotation(fromRotation, toRotation));
+ return new DisplayCutout(Insets.of(safeCutout), null, null, null, null);
+ }
+
+ /**
* Returns the current navigation mode from resource.
*/
public NavigationMode getNavigationMode(Context context) {
@@ -373,4 +377,12 @@
return Utilities.ATLEAST_S ? NavigationMode.NO_BUTTON :
NavigationMode.THREE_BUTTONS;
}
+
+ /**
+ * @see DisplayCutout#getSafeInsets
+ */
+ public static Rect getSafeInsets(DisplayCutout cutout) {
+ return new Rect(cutout.getSafeInsetLeft(), cutout.getSafeInsetTop(),
+ cutout.getSafeInsetRight(), cutout.getSafeInsetBottom());
+ }
}
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index ccf4b2e..a501960 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -27,6 +27,7 @@
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.widget.picker.WidgetRecommendationCategory;
import com.android.launcher3.widget.util.WidgetSizes;
/**
@@ -42,6 +43,16 @@
public Bundle bindOptions = null;
public int sourceContainer;
+ public WidgetRecommendationCategory recommendationCategory = null;
+
+ public PendingAddWidgetInfo(
+ LauncherAppWidgetProviderInfo i,
+ int container,
+ WidgetRecommendationCategory recommendationCategory) {
+ this(i, container);
+ this.recommendationCategory = recommendationCategory;
+ }
+
public PendingAddWidgetInfo(LauncherAppWidgetProviderInfo i, int container) {
if (i.isCustomWidget()) {
itemType = LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
index d99c5d1..801b1f6 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
@@ -80,6 +80,28 @@
/** Maps application category to an appropriate displayable category. */
private static WidgetRecommendationCategory getCategoryFromApplicationCategory(
Context context, int applicationCategory, String componentName) {
+ // Weather categories don't map to a specific application category, so, we maintain an
+ // allowlist.
+ String[] weatherRecommendationAllowlist =
+ context.getResources().getStringArray(R.array.weather_recommendations);
+ for (String allowedWeatherComponentName : weatherRecommendationAllowlist) {
+ if (componentName.equalsIgnoreCase(allowedWeatherComponentName)) {
+ return new WidgetRecommendationCategory(
+ R.string.weather_widget_recommendation_category_label, /*order=*/3);
+ }
+ }
+
+ // Fitness categories don't map to a specific application category, so, we maintain an
+ // allowlist.
+ String[] fitnessRecommendationAllowlist =
+ context.getResources().getStringArray(R.array.fitness_recommendations);
+ for (String allowedFitnessComponentName : fitnessRecommendationAllowlist) {
+ if (componentName.equalsIgnoreCase(allowedFitnessComponentName)) {
+ return new WidgetRecommendationCategory(
+ R.string.fitness_widget_recommendation_category_label, /*order=*/2);
+ }
+ }
+
if (applicationCategory == ApplicationInfo.CATEGORY_PRODUCTIVITY) {
return new WidgetRecommendationCategory(
R.string.productivity_widget_recommendation_category_label, /*order=*/0);
@@ -99,26 +121,6 @@
/*order=*/4);
}
- // Fitness & weather categories don't map to a specific application category, so, we
- // maintain an allowlist.
- String[] weatherRecommendationAllowlist =
- context.getResources().getStringArray(R.array.weather_recommendations);
- for (String allowedWeatherComponentName : weatherRecommendationAllowlist) {
- if (componentName.equalsIgnoreCase(allowedWeatherComponentName)) {
- return new WidgetRecommendationCategory(
- R.string.weather_widget_recommendation_category_label, /*order=*/2);
- }
- }
-
- String[] fitnessRecommendationAllowlist =
- context.getResources().getStringArray(R.array.fitness_recommendations);
- for (String allowedFitnessComponentName : fitnessRecommendationAllowlist) {
- if (componentName.equalsIgnoreCase(allowedFitnessComponentName)) {
- return new WidgetRecommendationCategory(
- R.string.fitness_widget_recommendation_category_label, /*order=*/3);
- }
- }
-
return new WidgetRecommendationCategory(
R.string.others_widget_recommendation_category_label, /*order=*/5);
}
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
index 920ba6f..361247b 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
@@ -80,8 +80,8 @@
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
springLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)
- getHotseatLayoutPadding(context).top: 64.0px (24.380953dp)
- getHotseatLayoutPadding(context).bottom: 112.0px (42.666668dp)
+ getHotseatLayoutPadding(context).top: 74.0px (28.190475dp)
+ getHotseatLayoutPadding(context).bottom: 103.0px (39.238094dp)
getHotseatLayoutPadding(context).left: 42.0px (16.0dp)
getHotseatLayoutPadding(context).right: 63.0px (24.0dp)
numShownHotseatIcons: 5
@@ -123,8 +123,8 @@
dropTargetBarSizePx: 95.0px (36.190475dp)
dropTargetBarBottomMarginPx: 16.0px (6.095238dp)
getCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)
- getCellLayoutSpringLoadShrunkBottom(): 952.0px (362.66666dp)
+ getCellLayoutSpringLoadShrunkBottom(): 961.0px (366.09525dp)
workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
- getWorkspaceSpringLoadScale(): 0.79639447px (0.30338836dp)
+ getWorkspaceSpringLoadScale(): 0.8059385px (0.30702418dp)
getCellLayoutHeight(): 943.0px (359.2381dp)
getCellLayoutWidth(): 2073.0px (789.7143dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
index 65460ec..d93ec58 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
@@ -80,8 +80,8 @@
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
springLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)
- getHotseatLayoutPadding(context).top: 64.0px (24.380953dp)
- getHotseatLayoutPadding(context).bottom: 49.0px (18.666666dp)
+ getHotseatLayoutPadding(context).top: 74.0px (28.190475dp)
+ getHotseatLayoutPadding(context).bottom: 40.0px (15.238095dp)
getHotseatLayoutPadding(context).left: 42.0px (16.0dp)
getHotseatLayoutPadding(context).right: 189.0px (72.0dp)
numShownHotseatIcons: 5
@@ -123,8 +123,8 @@
dropTargetBarSizePx: 95.0px (36.190475dp)
dropTargetBarBottomMarginPx: 16.0px (6.095238dp)
getCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)
- getCellLayoutSpringLoadShrunkBottom(): 1008.0px (384.0dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1017.0px (387.42856dp)
workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
- getWorkspaceSpringLoadScale(): 0.8021869px (0.305595dp)
+ getWorkspaceSpringLoadScale(): 0.8111332px (0.3090031dp)
getCellLayoutHeight(): 1006.0px (383.2381dp)
getCellLayoutWidth(): 1947.0px (741.7143dp)
diff --git a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 2f9945d..8d40ff2 100644
--- a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -150,6 +150,7 @@
public static final String REQUEST_GET_OVERVIEW_PAGE_SPACING = "get-overview-page-spacing";
public static final String REQUEST_GET_OVERVIEW_CURRENT_PAGE_INDEX =
"get-overview-current-page-index";
+ public static final String REQUEST_GET_SPLIT_SELECTION_ACTIVE = "get-split-selection-active";
public static final String REQUEST_ENABLE_ROTATION = "enable_rotation";
public static final String REQUEST_ENABLE_SUGGESTION = "enable-suggestion";
public static final String REQUEST_MODEL_QUEUE_CLEARED = "model-queue-cleared";
diff --git a/tests/multivalentTests/tapl/com/android/launcher3/tapl/Background.java b/tests/multivalentTests/tapl/com/android/launcher3/tapl/Background.java
index 9f2ce22..988aa94 100644
--- a/tests/multivalentTests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/multivalentTests/tapl/com/android/launcher3/tapl/Background.java
@@ -16,6 +16,7 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.tapl.BaseOverview.TASK_RES_ID;
import static com.android.launcher3.tapl.OverviewTask.TASK_START_EVENT;
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL;
@@ -116,10 +117,10 @@
// non-tablet overview, snapshots can be on either side of the swiped
// task, but we still check that they become visible after swiping and
// pausing.
- mLauncher.waitForOverviewObject("snapshot");
+ mLauncher.waitForOverviewObject(TASK_RES_ID);
if (mLauncher.isTablet()) {
List<UiObject2> tasks = mLauncher.getDevice().findObjects(
- mLauncher.getOverviewObjectSelector("snapshot"));
+ mLauncher.getOverviewObjectSelector(TASK_RES_ID));
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
mLauncher.assertTrue(
"All tasks not to the left of the swiped task",
diff --git a/tests/multivalentTests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/multivalentTests/tapl/com/android/launcher3/tapl/BaseOverview.java
index d337b91..ad95ecf 100644
--- a/tests/multivalentTests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/multivalentTests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -44,6 +44,7 @@
* Common overview panel for both Launcher and fallback recents
*/
public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
+ protected static final String TASK_RES_ID = "task";
private static final Pattern EVENT_ALT_ESC_DOWN = Pattern.compile(
"Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
@@ -281,10 +282,10 @@
// The widest, and most top-right task should be the current task
UiObject2 currentTask = Collections.max(taskViews,
- Comparator.comparingInt((UiObject2 t) -> t.getParent().getVisibleBounds().width())
- .thenComparingInt((UiObject2 t) -> t.getParent().getVisibleCenter().x)
+ Comparator.comparingInt((UiObject2 t) -> t.getVisibleBounds().width())
+ .thenComparingInt((UiObject2 t) -> t.getVisibleCenter().x)
.thenComparing(Comparator.comparing(
- (UiObject2 t) -> t.getParent().getVisibleCenter().y).reversed()));
+ (UiObject2 t) -> t.getVisibleCenter().y).reversed()));
return new OverviewTask(mLauncher, currentTask, this);
}
@@ -329,10 +330,11 @@
"want to get overview tasks")) {
verifyActiveContainer();
return mLauncher.getDevice().findObjects(
- mLauncher.getOverviewObjectSelector("snapshot"));
+ mLauncher.getOverviewObjectSelector(TASK_RES_ID));
}
}
+
int getTaskCount() {
return getTasks().size();
}
diff --git a/tests/multivalentTests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/multivalentTests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 6c9f5ed..cdde605 100644
--- a/tests/multivalentTests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/multivalentTests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -28,7 +28,9 @@
import static com.android.launcher3.tapl.Folder.FOLDER_CONTENT_RES_ID;
import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
+import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_GET_SPLIT_SELECTION_ACTIVE;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_NUM_ALL_APPS_COLUMNS;
+import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD;
import android.app.ActivityManager;
import android.app.Instrumentation;
@@ -878,7 +880,6 @@
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
waitUntilSystemLauncherObjectGone(OVERVIEW_RES_ID);
- waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
waitUntilLauncherObjectGone(KEYBOARD_QUICK_SWITCH_RES_ID);
if (is3PLauncher() && isTablet() && !isTransientTaskbar()) {
@@ -887,6 +888,12 @@
waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
}
+ boolean splitSelectionActive = getTestInfo(REQUEST_GET_SPLIT_SELECTION_ACTIVE)
+ .getBoolean(TEST_INFO_RESPONSE_FIELD);
+ if (!splitSelectionActive) {
+ waitUntilSystemLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+ } // do nothing, we expect that view
+
return waitForLauncherObject(APPS_RES_ID);
}
case OVERVIEW:
diff --git a/tests/multivalentTests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/multivalentTests/tapl/com/android/launcher3/tapl/OverviewTask.java
index f383e99..afe5722 100644
--- a/tests/multivalentTests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/multivalentTests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -16,6 +16,10 @@
package com.android.launcher3.tapl;
+import static com.android.launcher3.tapl.OverviewTask.OverviewSplitTask.DEFAULT;
+import static com.android.launcher3.tapl.OverviewTask.OverviewSplitTask.SPLIT_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.tapl.OverviewTask.OverviewSplitTask.SPLIT_TOP_OR_LEFT;
+
import android.graphics.Rect;
import androidx.annotation.NonNull;
@@ -34,9 +38,6 @@
*/
public final class OverviewTask {
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
- private static final String TASK_SNAPSHOT_1 = "snapshot";
- private static final String TASK_SNAPSHOT_2 = "bottomright_snapshot";
-
static final Pattern TASK_START_EVENT = Pattern.compile("startActivityFromRecentsAsync");
static final Pattern SPLIT_SELECT_EVENT = Pattern.compile("enterSplitSelect");
static final Pattern SPLIT_START_EVENT = Pattern.compile("launchSplitTasks");
@@ -64,15 +65,16 @@
return getCombinedSplitTaskHeight();
}
- return mTask.getVisibleBounds().height();
+ UiObject2 taskSnapshot1 = findObjectInTask(DEFAULT.snapshotRes);
+ return taskSnapshot1.getVisibleBounds().height();
}
/**
* Calculates the visible height for split tasks, containing 2 snapshot tiles and a divider.
*/
private int getCombinedSplitTaskHeight() {
- UiObject2 taskSnapshot1 = findObjectInTask(TASK_SNAPSHOT_1);
- UiObject2 taskSnapshot2 = findObjectInTask(TASK_SNAPSHOT_2);
+ UiObject2 taskSnapshot1 = findObjectInTask(SPLIT_TOP_OR_LEFT.snapshotRes);
+ UiObject2 taskSnapshot2 = findObjectInTask(SPLIT_BOTTOM_OR_RIGHT.snapshotRes);
// If the split task is partly off screen, taskSnapshot1 can be invisible.
if (taskSnapshot1 == null) {
@@ -96,15 +98,16 @@
return getCombinedSplitTaskWidth();
}
- return mTask.getVisibleBounds().width();
+ UiObject2 taskSnapshot1 = findObjectInTask(DEFAULT.snapshotRes);
+ return taskSnapshot1.getVisibleBounds().width();
}
/**
* Calculates the visible width for split tasks, containing 2 snapshot tiles and a divider.
*/
private int getCombinedSplitTaskWidth() {
- UiObject2 taskSnapshot1 = findObjectInTask(TASK_SNAPSHOT_1);
- UiObject2 taskSnapshot2 = findObjectInTask(TASK_SNAPSHOT_2);
+ UiObject2 taskSnapshot1 = findObjectInTask(SPLIT_TOP_OR_LEFT.snapshotRes);
+ UiObject2 taskSnapshot2 = findObjectInTask(SPLIT_BOTTOM_OR_RIGHT.snapshotRes);
int left = Math.min(
taskSnapshot1.getVisibleBounds().left, taskSnapshot2.getVisibleBounds().left);
@@ -115,15 +118,15 @@
}
int getTaskCenterX() {
- return mTask.getParent().getVisibleCenter().x;
+ return mTask.getVisibleCenter().x;
}
int getTaskCenterY() {
- return mTask.getParent().getVisibleCenter().y;
+ return mTask.getVisibleCenter().y;
}
float getExactCenterX() {
- return mTask.getParent().getVisibleBounds().exactCenterX();
+ return mTask.getVisibleBounds().exactCenterX();
}
UiObject2 getUiObject() {
@@ -225,11 +228,17 @@
/** Taps the task menu. Returns the task menu object. */
@NonNull
public OverviewTaskMenu tapMenu() {
+ return tapMenu(DEFAULT);
+ }
+
+ /** Taps the task menu of the split task. Returns the split task's menu object. */
+ @NonNull
+ public OverviewTaskMenu tapMenu(OverviewSplitTask task) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to tap the task menu")) {
mLauncher.clickLauncherObject(
- mLauncher.waitForObjectInContainer(mTask.getParent(), "icon"));
+ mLauncher.waitForObjectInContainer(mTask, task.iconAppRes));
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"tapped the task menu")) {
@@ -238,27 +247,31 @@
}
}
- /** Taps the task menu of the split task. Returns the split task's menu object. */
- @NonNull
- public OverviewTaskMenu tapSplitTaskMenu() {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to tap the split task's menu")) {
- mLauncher.clickLauncherObject(
- mLauncher.waitForObjectInContainer(mTask.getParent(), "bottomRight_icon"));
-
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "tapped the split task's menu")) {
- return new OverviewTaskMenu(mLauncher);
- }
- }
- }
-
boolean isTaskSplit() {
- return findObjectInTask(TASK_SNAPSHOT_2) != null;
+ return findObjectInTask(SPLIT_BOTTOM_OR_RIGHT.snapshotRes) != null;
}
private UiObject2 findObjectInTask(String resName) {
- return mTask.getParent().findObject(mLauncher.getOverviewObjectSelector(resName));
+ return mTask.findObject(mLauncher.getOverviewObjectSelector(resName));
+ }
+
+ /**
+ * Enum used to specify which task is retrieved when it is a split task.
+ */
+ public enum OverviewSplitTask {
+ // The main task when the task is not split.
+ DEFAULT("snapshot", "icon"),
+ // The first task in split task.
+ SPLIT_TOP_OR_LEFT("snapshot", "icon"),
+ // The second task in split task.
+ SPLIT_BOTTOM_OR_RIGHT("bottomright_snapshot", "bottomRight_icon");
+
+ public final String snapshotRes;
+ public final String iconAppRes;
+
+ OverviewSplitTask(String snapshotRes, String iconAppRes) {
+ this.snapshotRes = snapshotRes;
+ this.iconAppRes = iconAppRes;
+ }
}
}
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index d44ccf5..dbafe79 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -60,8 +60,8 @@
private val windowManagerProxy: WindowManagerProxy = mock()
private val launcherPrefs: LauncherPrefs = mock()
private val allowLeftRightSplitInPortrait: Boolean = initAllowLeftRightSplitInPortrait()
- fun initAllowLeftRightSplitInPortrait() : Boolean {
- val res = Resources.getSystem();
+ fun initAllowLeftRightSplitInPortrait(): Boolean {
+ val res = Resources.getSystem()
val resId = res.getIdentifier("config_leftRightSplitInPortrait", "bool", "android")
return Flags.enableLeftRightSplitInPortrait() && resId > 0 && res.getBoolean(resId)
}
@@ -124,8 +124,7 @@
) {
val (naturalX, naturalY) = deviceSpec.naturalSize
val windowsBounds = phoneWindowsBounds(deviceSpec, isGestureMode, naturalX, naturalY)
- val displayInfo =
- CachedDisplayInfo(Point(naturalX, naturalY), Surface.ROTATION_0, Rect(0, 0, 0, 0))
+ val displayInfo = CachedDisplayInfo(Point(naturalX, naturalY), Surface.ROTATION_0)
val perDisplayBoundsCache = mapOf(displayInfo to windowsBounds)
initializeCommonVars(
@@ -144,8 +143,7 @@
) {
val (naturalX, naturalY) = deviceSpec.naturalSize
val windowsBounds = tabletWindowsBounds(deviceSpec, naturalX, naturalY)
- val displayInfo =
- CachedDisplayInfo(Point(naturalX, naturalY), Surface.ROTATION_0, Rect(0, 0, 0, 0))
+ val displayInfo = CachedDisplayInfo(Point(naturalX, naturalY), Surface.ROTATION_0)
val perDisplayBoundsCache = mapOf(displayInfo to windowsBounds)
initializeCommonVars(
@@ -168,21 +166,13 @@
val unfoldedWindowsBounds =
tabletWindowsBounds(deviceSpecUnfolded, unfoldedNaturalX, unfoldedNaturalY)
val unfoldedDisplayInfo =
- CachedDisplayInfo(
- Point(unfoldedNaturalX, unfoldedNaturalY),
- Surface.ROTATION_0,
- Rect(0, 0, 0, 0)
- )
+ CachedDisplayInfo(Point(unfoldedNaturalX, unfoldedNaturalY), Surface.ROTATION_0)
val (foldedNaturalX, foldedNaturalY) = deviceSpecFolded.naturalSize
val foldedWindowsBounds =
phoneWindowsBounds(deviceSpecFolded, isGestureMode, foldedNaturalX, foldedNaturalY)
val foldedDisplayInfo =
- CachedDisplayInfo(
- Point(foldedNaturalX, foldedNaturalY),
- Surface.ROTATION_0,
- Rect(0, 0, 0, 0)
- )
+ CachedDisplayInfo(Point(foldedNaturalX, foldedNaturalY), Surface.ROTATION_0)
val perDisplayBoundsCache =
mapOf(
@@ -325,12 +315,16 @@
// TODO(b/315230497): We don't currently have device-specific device profile dumps, so just
// update the result before we do the comparison
if (allowLeftRightSplitInPortrait) {
- val isLeftRightSplitInPortrait = when {
- allowLeftRightSplitInPortrait && dp.isTablet -> !dp.isLandscape
- else -> dp.isLandscape
- }
- expected = expected.replace(Regex("isLeftRightSplit:\\w+"),
- "isLeftRightSplit:$isLeftRightSplitInPortrait")
+ val isLeftRightSplitInPortrait =
+ when {
+ allowLeftRightSplitInPortrait && dp.isTablet -> !dp.isLandscape
+ else -> dp.isLandscape
+ }
+ expected =
+ expected.replace(
+ Regex("isLeftRightSplit:\\w+"),
+ "isLeftRightSplit:$isLeftRightSplitInPortrait"
+ )
}
Truth.assertThat(dump).isEqualTo(expected)
diff --git a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
index da0beb1..6fce4c6 100644
--- a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
+++ b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
@@ -16,7 +16,6 @@
package com.android.launcher3.allapps;
import static com.android.launcher3.util.TestUtil.expectFail;
-import static com.android.launcher3.ui.AbstractLauncherUiTest.initialize;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -30,8 +29,8 @@
import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.launcher3.Flags;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.tapl.AllApps;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
@@ -208,7 +207,7 @@
public void testPressBackFromAllAppsToHome() {
InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
READ_DEVICE_CONFIG_PERMISSION);
- assumeFalse(FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get());
+ assumeFalse(Flags.enablePredictiveBackGesture());
mLauncher
.getWorkspace()
.switchToAllApps()
diff --git a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
index 8670d40..706ab27 100644
--- a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
+++ b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
@@ -95,8 +95,7 @@
whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false)
// Mock WindowManagerProxy
- val displayInfo =
- CachedDisplayInfo(Point(width, height), Surface.ROTATION_0, Rect(0, 0, 0, 0))
+ val displayInfo = CachedDisplayInfo(Point(width, height), Surface.ROTATION_0)
whenever(windowManagerProxy.getDisplayInfo(any())).thenReturn(displayInfo)
whenever(windowManagerProxy.estimateInternalDisplayBounds(any()))
.thenAnswer(
@@ -135,8 +134,7 @@
@Test
@UiThreadTest
fun testRotation() {
- val displayInfo =
- CachedDisplayInfo(Point(height, width), Surface.ROTATION_90, Rect(0, 0, 0, 0))
+ val displayInfo = CachedDisplayInfo(Point(height, width), Surface.ROTATION_90)
whenever(windowManagerProxy.getDisplayInfo(any())).thenReturn(displayInfo)
whenever(display.rotation).thenReturn(displayInfo.rotation)
val configuration =