Merge "Bubble bar user education" into main
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index b024418..f32f204 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -306,7 +306,7 @@
<dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_icon_size_kids">32dp</dimen>
<dimen name="taskbar_all_apps_button_translation_x_offset">6dp</dimen>
-
+ <dimen name="taskbar_all_apps_search_button_translation_x_offset">4.5dp</dimen>
<!-- Transient taskbar -->
<dimen name="transient_taskbar_padding">12dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index f8ea932..5f0da1c 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -151,6 +151,7 @@
import com.android.quickstep.views.RecentsView;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController;
+import com.android.systemui.animation.LaunchableView;
import com.android.systemui.animation.RemoteAnimationDelegate;
import com.android.systemui.shared.system.BlurUtils;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
@@ -1777,7 +1778,7 @@
@Nullable
private static ContainerAnimationRunner from(View v, Launcher launcher,
StartingWindowListener startingWindowListener, RunnableList onEndCallback) {
- View viewToUse = findViewWithBackground(v);
+ View viewToUse = findLaunchableViewWithBackground(v);
if (viewToUse == null) {
viewToUse = v;
}
@@ -1820,11 +1821,15 @@
new ActivityLaunchAnimator.AnimationDelegate(controller, callback, listener));
}
- /** Finds the closest parent of [view] (inclusive) with a background drawable. */
+ /**
+ * Finds the closest parent of [view] (inclusive) that implements {@link LaunchableView} and
+ * has a background drawable.
+ */
@Nullable
- private static View findViewWithBackground(View view) {
+ private static <T extends View & LaunchableView> T findLaunchableViewWithBackground(
+ View view) {
View current = view;
- while (current.getBackground() == null) {
+ while (current.getBackground() == null || !(current instanceof LaunchableView)) {
if (!(current.getParent() instanceof View)) {
return null;
}
@@ -1832,7 +1837,7 @@
current = (View) view.getParent();
}
- return current;
+ return (T) current;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 0b83a88..cfdf900 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -32,6 +32,7 @@
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
import static com.android.launcher3.taskbar.TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW;
import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
+import static com.android.launcher3.util.VibratorWrapper.EFFECT_CLICK;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
@@ -108,6 +109,7 @@
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.views.RecentsView;
@@ -1063,6 +1065,7 @@
* Called when we want to unstash taskbar when user performs swipes up gesture.
*/
public void onSwipeToUnstashTaskbar() {
+ VibratorWrapper.INSTANCE.get(this).vibrate(EFFECT_CLICK);
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(/* stash= */ false);
mControllers.taskbarEduTooltipController.hide();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
index e215bc9..b200858 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -59,6 +59,7 @@
return taskMenuViewWithArrow.populateForView(view)
}
}
+
private lateinit var dividerView: View
private val menuWidth =
@@ -178,13 +179,19 @@
override fun closeComplete() {
onCloseCallback(didPreferenceChange)
+ onCloseCallback = {}
super.closeComplete()
}
private fun onClickAlwaysShowTaskbarSwitchOption() {
didPreferenceChange = true
changePreference()
+ changePreference = {}
// Allow switch animation to finish and then close the popup.
- postDelayed(DIVIDER_POPUP_CLOSING_DELAY) { close(true) }
+ postDelayed(DIVIDER_POPUP_CLOSING_DELAY) {
+ if (isOpen) {
+ close(false)
+ }
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 3c7196a..4ad5c88 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -259,6 +259,8 @@
DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source,
ItemInfo dragInfo, Rect dragRegion, float initialDragViewScale,
float dragViewScaleOnDrop, DragOptions options) {
+ mActivity.hideKeyboard();
+
mOptions = options;
mRegistrationX = mMotionDown.x - dragLayerX;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index c423fb3..81cff57 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -64,6 +64,7 @@
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.util.AssistUtils;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
@@ -176,7 +177,8 @@
service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null);
mNavButtonController = new TaskbarNavButtonController(service,
- SystemUiProxy.INSTANCE.get(mContext), new Handler());
+ SystemUiProxy.INSTANCE.get(mContext), new Handler(),
+ AssistUtils.newInstance(mContext));
mComponentCallbacks = new ComponentCallbacks() {
private Configuration mOldConfig = mContext.getResources().getConfiguration();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 6d86b1e..533785f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -109,15 +109,17 @@
private final TouchInteractionService mService;
private final SystemUiProxy mSystemUiProxy;
private final Handler mHandler;
+ private final AssistUtils mAssistUtils;
@Nullable private StatsLogManager mStatsLogManager;
private final Runnable mResetLongPress = this::resetScreenUnpin;
public TaskbarNavButtonController(TouchInteractionService service,
- SystemUiProxy systemUiProxy, Handler handler) {
+ SystemUiProxy systemUiProxy, Handler handler, AssistUtils assistUtils) {
mService = service;
mSystemUiProxy = systemUiProxy;
mHandler = handler;
+ mAssistUtils = assistUtils;
}
public void onButtonClick(@TaskbarButton int buttonType, View view) {
@@ -313,8 +315,7 @@
return;
}
// Attempt to start Assist with AssistUtils, otherwise fall back to SysUi's implementation.
- if (!AssistUtils.newInstance(mService.getApplicationContext()).tryStartAssistOverride(
- INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS)) {
+ if (!mAssistUtils.tryStartAssistOverride(INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS)) {
Bundle args = new Bundle();
args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
mSystemUiProxy.startAssistant(args);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index fa5a1ae..0e5ab71 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
@@ -33,6 +34,8 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
+import androidx.annotation.DimenRes;
+import androidx.annotation.DrawableRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -90,11 +93,11 @@
// Only non-null when device supports having an All Apps button.
private @Nullable IconButtonView mTaskbarDivider;
- private View mQsb;
+ private final View mQsb;
- private float mTransientTaskbarMinWidth;
+ private final float mTransientTaskbarMinWidth;
- private float mTransientTaskbarAllAppsButtonTranslationXOffset;
+ private final float mTaskbarAllAppsButtonTranslationXOffset;
private boolean mShouldTryStartAlign;
@@ -120,12 +123,9 @@
boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivityContext)
&& !TaskbarManager.isPhoneMode(mActivityContext.getDeviceProfile());
mIsRtl = Utilities.isRtl(resources);
- mTransientTaskbarMinWidth = mContext.getResources().getDimension(
- R.dimen.transient_taskbar_min_width);
- mTransientTaskbarAllAppsButtonTranslationXOffset =
- resources.getDimension(isTransientTaskbar
- ? R.dimen.transient_taskbar_all_apps_button_translation_x_offset
- : R.dimen.taskbar_all_apps_button_translation_x_offset);
+ mTransientTaskbarMinWidth = resources.getDimension(R.dimen.transient_taskbar_min_width);
+ mTaskbarAllAppsButtonTranslationXOffset =
+ resources.getDimension(getAllAppsButtonTranslationXOffset(isTransientTaskbar));
onDeviceProfileChanged(mActivityContext.getDeviceProfile());
@@ -149,9 +149,8 @@
if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
.inflate(R.layout.taskbar_all_apps_button, this, false);
- mAllAppsButton.setIconDrawable(resources.getDrawable(isTransientTaskbar
- ? R.drawable.ic_transient_taskbar_all_apps_button
- : R.drawable.ic_taskbar_all_apps_button));
+ mAllAppsButton.setIconDrawable(resources.getDrawable(
+ getAllAppsButton(isTransientTaskbar)));
mAllAppsButton.setScaleX(mIsRtl ? -1 : 1);
mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
mAllAppsButton.setForegroundTint(
@@ -171,6 +170,30 @@
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
}
+ @DrawableRes
+ private int getAllAppsButton(boolean isTransientTaskbar) {
+ if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
+ return isTransientTaskbar
+ ? R.drawable.ic_transient_taskbar_all_apps_search_button
+ : R.drawable.ic_taskbar_all_apps_search_button;
+ } else {
+ return isTransientTaskbar
+ ? R.drawable.ic_transient_taskbar_all_apps_button
+ : R.drawable.ic_taskbar_all_apps_button;
+ }
+ }
+
+ @DimenRes
+ private int getAllAppsButtonTranslationXOffset(boolean isTransientTaskbar) {
+ if (isTransientTaskbar) {
+ return R.dimen.transient_taskbar_all_apps_button_translation_x_offset;
+ } else {
+ return ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()
+ ? R.dimen.taskbar_all_apps_search_button_translation_x_offset
+ : R.dimen.taskbar_all_apps_button_translation_x_offset;
+ }
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -336,7 +359,7 @@
if (mAllAppsButton != null) {
mAllAppsButton.setTranslationXForTaskbarAllAppsIcon(getChildCount() > 0
- ? mTransientTaskbarAllAppsButtonTranslationXOffset : 0f);
+ ? mTaskbarAllAppsButtonTranslationXOffset : 0f);
addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
// if only all apps button present, don't include divider view.
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 537d2c6..001c3bc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -21,12 +21,16 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import android.window.OnBackInvokedDispatcher;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
@@ -40,8 +44,11 @@
/** Wrapper for taskbar all apps with slide-in behavior. */
public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverlayContext>
implements Insettable, DeviceProfile.OnDeviceProfileChangeListener {
+ private final Handler mHandler;
+
private TaskbarAllAppsContainerView mAppsView;
private float mShiftRange;
+ private @Nullable Runnable mShowOnFullyAttachedToWindowRunnable;
// Initialized in init.
private TaskbarAllAppsCallbacks mAllAppsCallbacks;
@@ -53,6 +60,7 @@
public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ mHandler = new Handler(Looper.myLooper());
}
void init(TaskbarAllAppsCallbacks callbacks) {
@@ -65,14 +73,14 @@
return;
}
mIsOpen = true;
- attachToContainer();
addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
removeOnAttachStateChangeListener(this);
// Wait for view and its descendants to be fully attached before starting open.
- post(() -> showOnFullyAttachedToWindow(animate));
+ mShowOnFullyAttachedToWindowRunnable = () -> showOnFullyAttachedToWindow(animate);
+ mHandler.post(mShowOnFullyAttachedToWindowRunnable);
}
@Override
@@ -80,6 +88,7 @@
removeOnAttachStateChangeListener(this);
}
});
+ attachToContainer();
}
private void showOnFullyAttachedToWindow(boolean animate) {
@@ -114,6 +123,10 @@
@Override
protected void handleClose(boolean animate) {
+ if (mShowOnFullyAttachedToWindowRunnable != null) {
+ mHandler.removeCallbacks(mShowOnFullyAttachedToWindowRunnable);
+ mShowOnFullyAttachedToWindowRunnable = null;
+ }
if (mIsOpen) {
mAllAppsCallbacks.onAllAppsTransitionStart(false);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
index d4e2be9..2dba263 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
@@ -70,6 +70,18 @@
// New front task will be below existing overlay, so move out of the way.
hideWindow();
}
+
+ @Override
+ public void onTaskStackChanged() {
+ // The other callbacks are insufficient for All Apps, because there are many cases where
+ // it can relaunch the same task already behind it. However, this callback needs to be a
+ // no-op when only EDU is shown, because going between the EDU steps invokes this
+ // callback.
+ if (mControllers.getSharedState() != null
+ && mControllers.getSharedState().allAppsVisible) {
+ hideWindow();
+ }
+ }
};
private DeviceProfile mLauncherDeviceProfile;
@@ -199,8 +211,10 @@
@Override
protected void handleClose(boolean animate) {
- mTaskbarContext.getDragLayer().removeView(this);
- Optional.ofNullable(mOverlayContext).ifPresent(c -> closeAllOpenViews(c, animate));
+ if (mIsOpen) {
+ mTaskbarContext.getDragLayer().removeView(this);
+ Optional.ofNullable(mOverlayContext).ifPresent(c -> closeAllOpenViews(c, animate));
+ }
}
@Override
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
index b3d04c6..58be345 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
@@ -17,6 +17,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -33,6 +34,7 @@
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.util.AssistUtils;
import org.junit.Before;
import org.junit.Test;
@@ -54,6 +56,8 @@
@Mock
Handler mockHandler;
@Mock
+ AssistUtils mockAssistUtils;
+ @Mock
StatsLogManager mockStatsLogManager;
@Mock
StatsLogManager.StatsLogger mockStatsLogger;
@@ -79,7 +83,7 @@
.thenReturn(mockTaskbarActivityContext);
doReturn(mockStatsLogManager).when(mockTaskbarActivityContext).getStatsLogManager();
mNavButtonController = new TaskbarNavButtonController(mockService,
- mockSystemUiProxy, mockHandler);
+ mockSystemUiProxy, mockHandler, mockAssistUtils);
}
@Test
@@ -108,16 +112,42 @@
}
@Test
- public void testLongPressHome_enabled() {
+ public void testLongPressHome_enabled_withoutOverride() {
mNavButtonController.setAssistantLongPressEnabled(true /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(false);
+
mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, times(1)).tryStartAssistOverride(anyInt());
verify(mockSystemUiProxy, times(1)).startAssistant(any());
}
@Test
- public void testLongPressHome_disabled() {
- mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+ public void testLongPressHome_enabled_withOverride() {
+ mNavButtonController.setAssistantLongPressEnabled(true /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(true);
+
mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, times(1)).tryStartAssistOverride(anyInt());
+ verify(mockSystemUiProxy, never()).startAssistant(any());
+ }
+
+ @Test
+ public void testLongPressHome_disabled_withoutOverride() {
+ mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(false);
+
+ mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, never()).tryStartAssistOverride(anyInt());
+ verify(mockSystemUiProxy, never()).startAssistant(any());
+ }
+
+ @Test
+ public void testLongPressHome_disabled_withOverride() {
+ mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(true);
+
+ mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, never()).tryStartAssistOverride(anyInt());
verify(mockSystemUiProxy, never()).startAssistant(any());
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 25f90ca..2be38b0 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -271,24 +271,6 @@
}
@Test
- @PortraitLandscape
- public void testAllAppsFromHome() throws Exception {
- // Test opening all apps
- assertNotNull("switchToAllApps() returned null",
- mLauncher.getWorkspace().switchToAllApps());
-
- TaplTestsLauncher3.runAllAppsTest(this, mLauncher.getAllApps());
-
- // Testing pressHome.
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- assertNotNull("pressHome returned null", mLauncher.goHome());
- assertTrue("Launcher internal state is not Home",
- isInState(() -> LauncherState.NORMAL));
- assertNotNull("getHome returned null", mLauncher.getWorkspace());
- }
-
- @Test
@NavigationModeSwitch
@PortraitLandscape
@PlatinumTest(focusArea = "launcher")
@@ -502,7 +484,6 @@
}
@Test
- @ScreenRecord // b/242163205
public void testDisableRotationCheckForPhone() throws Exception {
assumeFalse(mLauncher.isTablet());
try {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index a90c326..cc56faf 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -37,6 +37,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -107,6 +108,7 @@
}
@Test
+ @Ignore("Enable once App Pairs flagged on. These cause memory leaks b/297135374")
public void testSaveAppPairMenuItemExistsOnSplitPair() throws Exception {
assumeTrue("App pairs feature is currently not enabled, no test needed",
FeatureFlags.ENABLE_APP_PAIRS.get());
@@ -122,6 +124,7 @@
}
@Test
+ @Ignore("Enable once App Pairs flagged on. These cause memory leaks b/297135374")
public void testSaveAppPairMenuItemDoesNotExistOnSingleTask() throws Exception {
assumeTrue("App pairs feature is currently not enabled, no test needed",
FeatureFlags.ENABLE_APP_PAIRS.get());
diff --git a/res/drawable-sw720dp/ic_transient_taskbar_all_apps_search_button.xml b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_search_button.xml
new file mode 100644
index 0000000..22f5d6b
--- /dev/null
+++ b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_search_button.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="52dp"
+ android:height="52dp"
+ android:viewportWidth="52"
+ android:viewportHeight="52">
+ <path
+ android:pathData="M42.647,43.855L37.215,38.423C36.784,38.768 36.288,39.041 35.727,39.242C35.167,39.443 34.57,39.544 33.938,39.544C32.372,39.544 31.042,39.005 29.95,37.927C28.872,36.835 28.333,35.505 28.333,33.939C28.333,32.372 28.872,31.05 29.95,29.972C31.042,28.88 32.372,28.334 33.938,28.334C35.505,28.334 36.827,28.88 37.904,29.972C38.997,31.05 39.543,32.372 39.543,33.939C39.543,34.571 39.442,35.167 39.241,35.728C39.04,36.289 38.767,36.784 38.422,37.215L43.854,42.648L42.647,43.855ZM33.938,37.819C35.016,37.819 35.929,37.445 36.676,36.698C37.437,35.936 37.818,35.017 37.818,33.939C37.818,32.861 37.437,31.948 36.676,31.201C35.929,30.439 35.016,30.059 33.938,30.059C32.86,30.059 31.94,30.439 31.179,31.201C30.431,31.948 30.058,32.861 30.058,33.939C30.058,35.017 30.431,35.936 31.179,36.698C31.94,37.445 32.86,37.819 33.938,37.819Z"
+ android:fillColor="#48473A"/>
+ <path
+ android:pathData="M39.42,17.543C39.42,20.605 36.938,23.086 33.876,23.086C30.815,23.086 28.333,20.605 28.333,17.543C28.333,14.482 30.815,12 33.876,12C36.938,12 39.42,14.482 39.42,17.543Z"
+ android:fillColor="#48473A"/>
+ <path
+ android:pathData="M23.086,17.543C23.086,20.605 20.605,23.086 17.543,23.086C14.482,23.086 12,20.605 12,17.543C12,14.482 14.482,12 17.543,12C20.605,12 23.086,14.482 23.086,17.543Z"
+ android:fillColor="#48473A"/>
+ <path
+ android:pathData="M17.543,33.877m-5.543,0a5.543,5.543 0,1 1,11.086 0a5.543,5.543 0,1 1,-11.086 0"
+ android:fillColor="#48473A"/>
+</vector>
diff --git a/res/drawable/ic_taskbar_all_apps_search_button.xml b/res/drawable/ic_taskbar_all_apps_search_button.xml
new file mode 100644
index 0000000..8a42dc7
--- /dev/null
+++ b/res/drawable/ic_taskbar_all_apps_search_button.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="44dp"
+ android:height="44dp"
+ android:viewportWidth="44"
+ android:viewportHeight="44">
+ <path
+ android:pathData="M36.938,38L32.164,33.225C31.785,33.528 31.349,33.769 30.856,33.945C30.363,34.122 29.839,34.211 29.283,34.211C27.906,34.211 26.738,33.737 25.778,32.79C24.83,31.83 24.357,30.661 24.357,29.284C24.357,27.907 24.83,26.745 25.778,25.798C26.738,24.837 27.906,24.357 29.283,24.357C30.66,24.357 31.822,24.837 32.77,25.798C33.73,26.745 34.21,27.907 34.21,29.284C34.21,29.84 34.121,30.364 33.945,30.857C33.768,31.349 33.528,31.785 33.225,32.164L38,36.939L36.938,38ZM29.283,32.695C30.231,32.695 31.033,32.366 31.69,31.709C32.359,31.04 32.694,30.232 32.694,29.284C32.694,28.337 32.359,27.535 31.69,26.878C31.033,26.208 30.231,25.873 29.283,25.873C28.336,25.873 27.527,26.208 26.858,26.878C26.201,27.535 25.873,28.337 25.873,29.284C25.873,30.232 26.201,31.04 26.858,31.709C27.527,32.366 28.336,32.695 29.283,32.695Z"
+ android:fillColor="#52443C"/>
+ <path
+ android:pathData="M34.102,14.873C34.102,17.563 31.92,19.745 29.229,19.745C26.538,19.745 24.357,17.563 24.357,14.873C24.357,12.182 26.538,10 29.229,10C31.92,10 34.102,12.182 34.102,14.873Z"
+ android:fillColor="#52443C"/>
+ <path
+ android:pathData="M19.745,14.873C19.745,17.563 17.563,19.745 14.873,19.745C12.182,19.745 10,17.563 10,14.873C10,12.182 12.182,10 14.873,10C17.563,10 19.745,12.182 19.745,14.873Z"
+ android:fillColor="#52443C"/>
+ <path
+ android:pathData="M14.873,29.23m-4.872,0a4.872,4.872 0,1 1,9.745 0a4.872,4.872 0,1 1,-9.745 0"
+ android:fillColor="#52443C"/>
+</vector>
diff --git a/res/drawable/ic_transient_taskbar_all_apps_search_button.xml b/res/drawable/ic_transient_taskbar_all_apps_search_button.xml
new file mode 100644
index 0000000..52d6818
--- /dev/null
+++ b/res/drawable/ic_transient_taskbar_all_apps_search_button.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:pathData="M40.647,41.855L35.215,36.423C34.784,36.768 34.288,37.041 33.727,37.242C33.167,37.443 32.57,37.544 31.938,37.544C30.372,37.544 29.042,37.005 27.95,35.927C26.872,34.835 26.333,33.505 26.333,31.939C26.333,30.372 26.872,29.05 27.95,27.972C29.042,26.88 30.372,26.334 31.938,26.334C33.505,26.334 34.827,26.88 35.904,27.972C36.997,29.05 37.543,30.372 37.543,31.939C37.543,32.571 37.442,33.167 37.241,33.728C37.04,34.289 36.767,34.784 36.422,35.215L41.854,40.648L40.647,41.855ZM31.938,35.819C33.016,35.819 33.929,35.445 34.676,34.698C35.437,33.936 35.818,33.017 35.818,31.939C35.818,30.861 35.437,29.948 34.676,29.201C33.929,28.439 33.016,28.059 31.938,28.059C30.86,28.059 29.94,28.439 29.179,29.201C28.431,29.948 28.058,30.861 28.058,31.939C28.058,33.017 28.431,33.936 29.179,34.698C29.94,35.445 30.86,35.819 31.938,35.819Z"
+ android:fillColor="#52443C"/>
+ <path
+ android:pathData="M37.42,15.543C37.42,18.605 34.938,21.086 31.876,21.086C28.815,21.086 26.333,18.605 26.333,15.543C26.333,12.482 28.815,10 31.876,10C34.938,10 37.42,12.482 37.42,15.543Z"
+ android:fillColor="#52443C"/>
+ <path
+ android:pathData="M21.086,15.543C21.086,18.605 18.605,21.086 15.543,21.086C12.482,21.086 10,18.605 10,15.543C10,12.482 12.482,10 15.543,10C18.605,10 21.086,12.482 21.086,15.543Z"
+ android:fillColor="#52443C"/>
+ <path
+ android:pathData="M15.543,31.877m-5.543,0a5.543,5.543 0,1 1,11.086 0a5.543,5.543 0,1 1,-11.086 0"
+ android:fillColor="#52443C"/>
+</vector>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 0a5524b..e7d1db4 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -296,6 +296,7 @@
public final int taskbarIconSize;
// If true, used to layout taskbar in 3 button navigation mode.
public final boolean startAlignTaskbar;
+ public final boolean isTransientTaskbar;
// DragController
public int flingToDeleteThresholdVelocity;
@@ -363,7 +364,8 @@
}
}
- if (DisplayController.isTransientTaskbar(context)) {
+ isTransientTaskbar = DisplayController.isTransientTaskbar(context);
+ if (isTransientTaskbar) {
float invTransientIconSizeDp = inv.transientTaskbarIconSize[mTypeIndex];
taskbarIconSize = pxFromDp(invTransientIconSizeDp, mMetrics);
taskbarHeight = Math.round((taskbarIconSize * ICON_VISIBLE_AREA_FACTOR)
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index e8c6ff9..7b27a71 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -16,13 +16,14 @@
package com.android.launcher3;
+import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction;
+
import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
-import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ICON_BADGED;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
-import android.annotation.TargetApi;
+import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.Person;
@@ -33,6 +34,9 @@
import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BlendMode;
+import android.graphics.BlendModeColorFilter;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
@@ -43,8 +47,10 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.DeadObjectException;
@@ -59,6 +65,7 @@
import android.text.style.TtsSpan;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Pair;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
@@ -68,10 +75,13 @@
import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import androidx.core.graphics.ColorUtils;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.graphics.TintedDrawableSpan;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.ShortcutCachingLogic;
import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.ItemInfo;
@@ -571,103 +581,112 @@
}
/**
- * Returns the full drawable for info without any flattening or pre-processing.
+ * Returns the full drawable for info as multiple layers of AdaptiveIconDrawable. The second
+ * drawable in the Pair is the badge used with the icon.
*
- * @param shouldThemeIcon If true, will theme icons when applicable
- * @param outObj this is set to the internal data associated with {@code info},
- * eg {@link LauncherActivityInfo} or {@link ShortcutInfo}.
+ * @param useTheme If true, will theme icons when applicable
*/
- @TargetApi(Build.VERSION_CODES.TIRAMISU)
- public static Drawable getFullDrawable(Context context, ItemInfo info, int width, int height,
- boolean shouldThemeIcon, Object[] outObj, boolean[] outIsIconThemed) {
- Drawable icon = loadFullDrawableWithoutTheme(context, info, width, height, outObj);
- if (ATLEAST_T && icon instanceof AdaptiveIconDrawable && shouldThemeIcon) {
- AdaptiveIconDrawable aid = (AdaptiveIconDrawable) icon.mutate();
- Drawable mono = aid.getMonochrome();
- if (mono != null && Themes.isThemedIconEnabled(context)) {
- outIsIconThemed[0] = true;
- int[] colors = ThemedIconDrawable.getColors(context);
- mono = mono.mutate();
- mono.setTint(colors[1]);
- return new AdaptiveIconDrawable(new ColorDrawable(colors[0]), mono);
- }
- }
- return icon;
- }
-
- private static Drawable loadFullDrawableWithoutTheme(Context context, ItemInfo info,
- int width, int height, Object[] outObj) {
- ActivityContext activity = ActivityContext.lookupContext(context);
+ @SuppressLint("UseCompatLoadingForDrawables")
+ @Nullable
+ @WorkerThread
+ public static <T extends Context & ActivityContext> Pair<AdaptiveIconDrawable, Drawable>
+ getFullDrawable(T context, ItemInfo info, int width, int height, boolean useTheme) {
+ useTheme &= Themes.isThemedIconEnabled(context);
LauncherAppState appState = LauncherAppState.getInstance(context);
+ Drawable mainIcon = null;
+
+ Drawable badge = null;
+ if ((info instanceof ItemInfoWithIcon iiwi) && !iiwi.usingLowResIcon()) {
+ badge = iiwi.bitmap.getBadgeDrawable(context, useTheme);
+ }
+
if (info instanceof PendingAddShortcutInfo) {
ShortcutConfigActivityInfo activityInfo =
((PendingAddShortcutInfo) info).getActivityInfo(context);
- outObj[0] = activityInfo;
- return activityInfo.getFullResIcon(appState.getIconCache());
- }
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ mainIcon = activityInfo.getFullResIcon(appState.getIconCache());
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
LauncherActivityInfo activityInfo = context.getSystemService(LauncherApps.class)
.resolveActivity(info.getIntent(), info.user);
- outObj[0] = activityInfo;
- return activityInfo == null ? null : LauncherAppState.getInstance(context)
- .getIconProvider().getIcon(
- activityInfo, activity.getDeviceProfile().inv.fillResIconDpi);
+ if (activityInfo == null) {
+ return null;
+ }
+ mainIcon = appState.getIconProvider().getIcon(
+ activityInfo, appState.getInvariantDeviceProfile().fillResIconDpi);
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- List<ShortcutInfo> si = ShortcutKey.fromItemInfo(info)
+ List<ShortcutInfo> siList = ShortcutKey.fromItemInfo(info)
.buildRequest(context)
.query(ShortcutRequest.ALL);
- if (si.isEmpty()) {
+ if (siList.isEmpty()) {
return null;
} else {
- outObj[0] = si.get(0);
- return ShortcutCachingLogic.getIcon(context, si.get(0),
+ ShortcutInfo si = siList.get(0);
+ mainIcon = ShortcutCachingLogic.getIcon(context, si,
appState.getInvariantDeviceProfile().fillResIconDpi);
+ // Only fetch badge if the icon is on workspace
+ if (info.id != ItemInfo.NO_ID && badge == null) {
+ badge = appState.getIconCache().getShortcutInfoBadge(si)
+ .newIcon(context, FLAG_THEMED);
+ }
}
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
FolderAdaptiveIcon icon = FolderAdaptiveIcon.createFolderAdaptiveIcon(
- activity, info.id, new Point(width, height));
+ context, info.id, new Point(width, height));
if (icon == null) {
return null;
}
- outObj[0] = icon;
- return icon;
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION
- && info instanceof ItemInfoWithIcon) {
- return ((ItemInfoWithIcon) info).bitmap.newIcon(context);
- } else {
+ mainIcon = icon;
+ badge = icon.getBadge();
+ }
+
+ if (mainIcon == null) {
return null;
}
- }
-
- /**
- * For apps icons and shortcut icons that have badges, this method creates a drawable that can
- * later on be rendered on top of the layers for the badges. For app icons, work profile badges
- * can only be applied. For deep shortcuts, when dragged from the pop up container, there's no
- * badge. When dragged from workspace or folder, it may contain app AND/OR work profile badge
- **/
- @TargetApi(Build.VERSION_CODES.O)
- public static Drawable getBadge(Context context, ItemInfo info, Object obj,
- boolean isIconThemed) {
- LauncherAppState appState = LauncherAppState.getInstance(context);
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- boolean iconBadged = (info instanceof ItemInfoWithIcon)
- && (((ItemInfoWithIcon) info).runtimeStatusFlags & FLAG_ICON_BADGED) > 0;
- if ((info.id == ItemInfo.NO_ID && !iconBadged)
- || !(obj instanceof ShortcutInfo)) {
- // The item is not yet added on home screen.
- return new ColorDrawable(Color.TRANSPARENT);
- }
- ShortcutInfo si = (ShortcutInfo) obj;
- return LauncherAppState.getInstance(appState.getContext())
- .getIconCache().getShortcutInfoBadge(si).newIcon(context, FLAG_THEMED);
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
- return ((FolderAdaptiveIcon) obj).getBadge();
+ AdaptiveIconDrawable result;
+ if (mainIcon instanceof AdaptiveIconDrawable aid) {
+ result = aid;
} else {
- return Process.myUserHandle().equals(info.user)
- ? new ColorDrawable(Color.TRANSPARENT)
- : context.getDrawable(isIconThemed
- ? R.drawable.ic_work_app_badge_themed : R.drawable.ic_work_app_badge);
+ // Wrap the main icon in AID
+ try (LauncherIcons li = LauncherIcons.obtain(context)) {
+ result = li.wrapToAdaptiveIcon(mainIcon);
+ }
}
+ if (result == null) {
+ return null;
+ }
+
+ // Inject monochrome icon drawable
+ if (ATLEAST_T && useTheme) {
+ result.mutate();
+ int[] colors = ThemedIconDrawable.getColors(context);
+ Drawable mono = result.getMonochrome();
+
+ if (mono != null) {
+ mono.setTint(colors[1]);
+ } else if (info instanceof ItemInfoWithIcon iiwi) {
+ // Inject a previously generated monochrome icon
+ Bitmap monoBitmap = iiwi.bitmap.getMono();
+ if (monoBitmap != null) {
+ // Use BitmapDrawable instead of FastBitmapDrawable so that the colorState is
+ // preserved in constantState
+ mono = new BitmapDrawable(monoBitmap);
+ mono.setColorFilter(new BlendModeColorFilter(colors[1], BlendMode.SRC_IN));
+ // Inset the drawable according to the AdaptiveIconDrawable layers
+ mono = new InsetDrawable(mono, getExtraInsetFraction() / 2);
+ }
+ }
+ if (mono != null) {
+ result = new AdaptiveIconDrawable(new ColorDrawable(colors[0]), mono);
+ }
+ }
+
+ if (badge == null) {
+ badge = Process.myUserHandle().equals(info.user)
+ ? new ColorDrawable(Color.TRANSPARENT)
+ : context.getDrawable(useTheme
+ ? R.drawable.ic_work_app_badge_themed
+ : R.drawable.ic_work_app_badge);
+ }
+ return Pair.create(result, badge);
}
public static float squaredHypot(float x, float y) {
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index adfdc89..c2d9e02 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -20,7 +20,6 @@
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
-import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -45,6 +44,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
+import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -244,13 +244,12 @@
public void setItemInfo(final ItemInfo info) {
// Load the adaptive icon on a background thread and add the view in ui thread.
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(() -> {
- Object[] outObj = new Object[1];
- boolean[] outIsIconThemed = new boolean[1];
int w = mWidth;
int h = mHeight;
- Drawable dr = Utilities.getFullDrawable(mActivity, info, w, h,
- true /* shouldThemeIcon */, outObj, outIsIconThemed);
- if (dr instanceof AdaptiveIconDrawable) {
+ Pair<AdaptiveIconDrawable, Drawable> fullDrawable = Utilities.getFullDrawable(
+ mActivity, info, w, h, true /* shouldThemeIcon */);
+ if (fullDrawable != null) {
+ AdaptiveIconDrawable adaptiveIcon = fullDrawable.first;
int blurMargin = (int) mActivity.getResources()
.getDimension(R.dimen.blur_size_medium_outline) / 2;
@@ -258,24 +257,15 @@
bounds.inset(blurMargin, blurMargin);
// Badge is applied after icon normalization so the bounds for badge should not
// be scaled down due to icon normalization.
- mBadge = getBadge(mActivity, info, outObj[0], outIsIconThemed[0]);
+ mBadge = fullDrawable.second;
FastBitmapDrawable.setBadgeBounds(mBadge, bounds);
- // Do not draw the background in case of folder as its translucent
- final boolean shouldDrawBackground = !(dr instanceof FolderAdaptiveIcon);
-
try (LauncherIcons li = LauncherIcons.obtain(mActivity)) {
- Drawable nDr; // drawable to be normalized
- if (shouldDrawBackground) {
- nDr = dr;
- } else {
- // Since we just want the scale, avoid heavy drawing operations
- nDr = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
- }
- Utilities.scaleRectAboutCenter(bounds,
- li.getNormalizer().getScale(nDr, null, null, null));
+ // Since we just want the scale, avoid heavy drawing operations
+ Utilities.scaleRectAboutCenter(bounds, li.getNormalizer().getScale(
+ new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null),
+ null, null, null));
}
- AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
// Shrink very tiny bit so that the clip path is smaller than the original bitmap
// that has anti aliased edges and shadows.
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 7e6cbef..6c2f589 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -23,8 +23,6 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
-import android.os.Build;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
@@ -177,12 +175,6 @@
info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
- if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O
- && Process.myUserHandle().equals(lai.getUser())) {
- // The icon for a non-primary user is badged, hence it's not exactly an adaptive icon.
- info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON;
- }
-
// Sets the progress level, installation and incremental download flags.
info.setProgressLevel(
PackageManagerHelper.getLoadingProgress(lai),
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index b4a935a..dc180d8 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -83,17 +83,6 @@
public static final int FLAG_SYSTEM_MASK = FLAG_SYSTEM_YES | FLAG_SYSTEM_NO;
/**
- * Flag indicating that the icon is an {@link android.graphics.drawable.AdaptiveIconDrawable}
- * that can be optimized in various way.
- */
- public static final int FLAG_ADAPTIVE_ICON = 1 << 8;
-
- /**
- * Flag indicating that the icon is badged.
- */
- public static final int FLAG_ICON_BADGED = 1 << 9;
-
- /**
* The icon is being installed. If {@link WorkspaceItemInfo#FLAG_RESTORED_ICON} or
* {@link WorkspaceItemInfo#FLAG_AUTOINSTALL_ICON} is set, then the icon is either being
* installed or is in a broken state.
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 5d412ff..07a1b82 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -17,7 +17,6 @@
import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
import static com.android.launcher3.config.FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TRACKPAD_GESTURE;
import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -236,12 +235,6 @@
return response;
}
- case TestProtocol.REQUEST_IS_TRACKPAD_GESTURE_ENABLED: {
- response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
- ENABLE_TRACKPAD_GESTURE.get());
- return response;
- }
-
case TestProtocol.REQUEST_ALL_APPS_TOP_PADDING: {
return getLauncherUIProperty(Bundle::putInt,
l -> l.getAppsView().getActiveRecyclerView().getClipBounds().top);
diff --git a/src/com/android/launcher3/testing/TestLogging.java b/src/com/android/launcher3/testing/TestLogging.java
index 3db2ddf..70691f8 100644
--- a/src/com/android/launcher3/testing/TestLogging.java
+++ b/src/com/android/launcher3/testing/TestLogging.java
@@ -70,15 +70,12 @@
public static void recordMotionEvent(String sequence, String message, MotionEvent event) {
final int action = event.getAction();
if (Utilities.isRunningInTestHarness() && action != MotionEvent.ACTION_MOVE) {
- // "Expecting" in TAPL ACTION_DOWN, UP and CANCEL events was thought to be producing
- // considerable noise in tests due to failed checks for expected events. So we are not
- // sending them to TAPL.
+ // "Expecting" in TAPL motion events was thought to be producing considerable noise in
+ // tests due to failed checks for expected events. So we are not sending them to TAPL.
// Other events, such as EVENT_PILFER_POINTERS produce less noise and are thought to
// be more useful.
- final boolean reportToTapl = action != MotionEvent.ACTION_DOWN
- && action != MotionEvent.ACTION_UP
- && action != MotionEvent.ACTION_CANCEL;
- recordEventSlow(sequence, message + ": " + event, reportToTapl);
+ // That's why we pass false as the value for the 'reportToTapl' parameter.
+ recordEventSlow(sequence, message + ": " + event, false);
registerEventNotFromTest(event);
}
}
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 6a972eb..dc4621e 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -582,7 +582,8 @@
? splitInfo.dividerHeightPercent
: splitInfo.dividerWidthPercent;
- float scale = (float) outRect.height() / dp.availableHeightPx;
+ int taskbarHeight = dp.isTransientTaskbar ? 0 : dp.taskbarHeight;
+ float scale = (float) outRect.height() / (dp.availableHeightPx - taskbarHeight);
float topTaskHeight = dp.availableHeightPx * topLeftTaskPercent;
float scaledTopTaskHeight = topTaskHeight * scale;
float dividerHeight = dp.availableHeightPx * dividerBarPercent;
@@ -639,7 +640,8 @@
// Reset unused translations
primarySnapshot.setTranslationY(0);
} else {
- float scale = (float) totalThumbnailHeight / dp.availableHeightPx;
+ int taskbarHeight = dp.isTransientTaskbar ? 0 : dp.taskbarHeight;
+ float scale = (float) totalThumbnailHeight / (dp.availableHeightPx - taskbarHeight);
float topTaskHeight = dp.availableHeightPx * taskPercent;
float finalDividerHeight = Math.round(totalThumbnailHeight * dividerScale);
float scaledTopTaskHeight = topTaskHeight * scale;
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 41b98c7..32c70a3 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -18,7 +18,6 @@
import static android.view.Gravity.LEFT;
import static com.android.app.animation.Interpolators.LINEAR;
-import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.Utilities.getFullDrawable;
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -36,6 +35,7 @@
import android.os.CancellationSignal;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -288,28 +288,20 @@
} else {
int width = (int) pos.width();
int height = (int) pos.height();
- Object[] tmpObjArray = new Object[1];
- boolean[] outIsIconThemed = new boolean[1];
+ Pair<AdaptiveIconDrawable, Drawable> fullIcon = null;
if (supportsAdaptiveIcons) {
- boolean shouldThemeIcon = btvIcon instanceof FastBitmapDrawable
- && ((FastBitmapDrawable) btvIcon).isThemed();
- drawable = getFullDrawable(
- l, info, width, height, shouldThemeIcon, tmpObjArray, outIsIconThemed);
- if (drawable instanceof AdaptiveIconDrawable) {
- badge = getBadge(l, info, tmpObjArray[0], outIsIconThemed[0]);
- } else {
- // The drawable we get back is not an adaptive icon, so we need to use the
- // BubbleTextView icon that is already legacy treated.
- drawable = btvIcon;
- }
+ boolean shouldThemeIcon = (btvIcon instanceof FastBitmapDrawable fbd)
+ && fbd.isCreatedForTheme();
+ fullIcon = getFullDrawable(l, info, width, height, shouldThemeIcon);
+ } else if (!(originalView instanceof BubbleTextView)) {
+ fullIcon = getFullDrawable(l, info, width, height, true /* shouldThemeIcon */);
+ }
+
+ if (fullIcon != null) {
+ drawable = fullIcon.first;
+ badge = fullIcon.second;
} else {
- if (originalView instanceof BubbleTextView) {
- // Similar to DragView, we simply use the BubbleTextView icon here.
- drawable = btvIcon;
- } else {
- drawable = getFullDrawable(l, info, width, height, true /* shouldThemeIcon */,
- tmpObjArray, outIsIconThemed);
- }
+ drawable = btvIcon;
}
}
diff --git a/tests/Android.bp b/tests/Android.bp
index d40efce..d45e9eb 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -42,6 +42,7 @@
filegroup {
name: "launcher-oop-tests-src",
srcs: [
+ "src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java",
"src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
"src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
"src/com/android/launcher3/ui/TaplTestsLauncher3.java",
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index cdf8f08..9c95397 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -120,7 +120,6 @@
"get-activities-created-count";
public static final String REQUEST_GET_ACTIVITIES = "get-activities";
public static final String REQUEST_HAS_TIS = "has-touch-interaction-service";
- public static final String REQUEST_IS_TRACKPAD_GESTURE_ENABLED = "is-trackpad-gesture-enabled";
public static final String REQUEST_TASKBAR_ALL_APPS_TOP_PADDING =
"taskbar-all-apps-top-padding";
public static final String REQUEST_ALL_APPS_TOP_PADDING = "all-apps-top-padding";
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index dd79ca8..ed8e324 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -26,6 +26,7 @@
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.NavigationMode
import com.android.launcher3.util.WindowBounds
+import com.android.launcher3.util.rule.TestStabilityRule
import com.android.launcher3.util.window.CachedDisplayInfo
import com.android.launcher3.util.window.WindowManagerProxy
import java.io.BufferedReader
@@ -36,6 +37,7 @@
import kotlin.math.min
import org.junit.After
import org.junit.Before
+import org.junit.Rule
import org.mockito.ArgumentMatchers
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when` as whenever
@@ -54,6 +56,8 @@
private lateinit var originalDisplayController: DisplayController
private lateinit var originalWindowManagerProxy: WindowManagerProxy
+ @Rule @JvmField val testStabilityRule = TestStabilityRule()
+
@Before
open fun setUp() {
val appContext: Context = ApplicationProvider.getApplicationContext()
diff --git a/tests/src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java b/tests/src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java
new file mode 100644
index 0000000..7d6b7f9
--- /dev/null
+++ b/tests/src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import static com.android.launcher3.ui.TaplTestsLauncher3.expectFail;
+import static com.android.launcher3.ui.TaplTestsLauncher3.initialize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.tapl.AllApps;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test that we can open and close the all apps in multiple situations.
+ * The test runs in Out of process (Oop) and in process.
+ */
+public class OopTaplOpenCloseAllApps extends AbstractLauncherUiTest {
+
+ /**
+ * Calls static method initialize
+ */
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ initialize(this);
+ }
+
+ /**
+ * Make sure we can go home after pressing the context menu on an Icon on the AllApps.
+ */
+ @Test
+ public void testPressHomeOnAllAppsContextMenu() {
+ final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ allApps.getAppIcon("TestActivity7").openMenu();
+ } finally {
+ allApps.unfreeze();
+ }
+ mLauncher.goHome();
+ }
+
+ /**
+ * Make sure we can open AllApps from the Workspace.
+ */
+ @Test
+ @PortraitLandscape
+ public void testWorkspaceSwitchToAllApps() {
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+ assertTrue("Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ }
+
+ /**
+ * Make sure we can go to Workspace from AllApps
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsSwitchToWorkspace() {
+ assertNotNull("switchToWorkspace() returned null",
+ mLauncher.getWorkspace().switchToAllApps()
+ .switchToWorkspace(/* swipeDown= */ true));
+ assertTrue("Launcher internal state is not Workspace",
+ isInState(() -> LauncherState.NORMAL));
+ }
+
+ /**
+ * Make sure the swipe up gesture can take us back to the workspace from AllApps
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsSwipeUpToWorkspace() {
+ assertNotNull("testAllAppsSwipeUpToWorkspace() returned null",
+ mLauncher.getWorkspace().switchToAllApps()
+ .switchToWorkspace(/* swipeDown= */ false));
+ assertTrue("Launcher internal state is not Workspace",
+ isInState(() -> LauncherState.NORMAL));
+ }
+
+ /**
+ * Make sure we can go to the Workspace from AllApps on tablets by tapping on the background.
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsDeadzoneForTablet() {
+ assumeTrue(mLauncher.isTablet());
+
+ mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
+ true /* tapRight */);
+ mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
+ false /* tapRight */);
+ }
+
+ /**
+ * Make sure that AllApps closes when pressing the home button
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsFromHome() {
+ // Test opening all apps
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+
+ runAllAppsTest(mLauncher.getAllApps());
+
+ // Testing pressHome.
+ assertTrue("Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ assertNotNull("pressHome returned null", mLauncher.goHome());
+ assertTrue("Launcher internal state is not Home",
+ isInState(() -> LauncherState.NORMAL));
+ assertNotNull("getHome returned null", mLauncher.getWorkspace());
+ }
+
+ /**
+ * Makes sure the state of AllApps is correct.
+ */
+ public void runAllAppsTest(AllApps allApps) {
+ allApps.freeze();
+ try {
+ assertNotNull("allApps parameter is null", allApps);
+
+ assertTrue(
+ "Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+
+ // Test flinging forward and backward.
+ executeOnLauncher(launcher -> assertEquals(
+ "All Apps started in already scrolled state", 0,
+ getAllAppsScroll(launcher)));
+
+ allApps.flingForward();
+ assertTrue("Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ final Integer flingForwardY = getFromLauncher(
+ launcher -> getAllAppsScroll(launcher));
+ executeOnLauncher(
+ launcher -> assertTrue("flingForward() didn't scroll App Apps",
+ flingForwardY > 0));
+
+ allApps.flingBackward();
+ assertTrue(
+ "Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ final Integer flingBackwardY = getFromLauncher(
+ launcher -> getAllAppsScroll(launcher));
+ executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps",
+ flingBackwardY < flingForwardY));
+
+ // Test scrolling down to YouTube.
+ assertNotNull("All apps: can't find YouTube", allApps.getAppIcon("YouTube"));
+ // Test scrolling up to Camera.
+ assertNotNull("All apps: can't find Camera", allApps.getAppIcon("Camera"));
+ // Test failing to find a non-existing app.
+ final AllApps allAppsFinal = allApps;
+ expectFail("All apps: could find a non-existing app",
+ () -> allAppsFinal.getAppIcon("NO APP"));
+
+ assertTrue(
+ "Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
index 7e9d9da..c7431f2 100644
--- a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
+++ b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
@@ -184,7 +184,7 @@
mStartPoint = icon.getVisibleCenter();
mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
assertThat(findObjectByResourceName("popup_container")).isNotNull();
return appName;
}
@@ -206,7 +206,7 @@
mStartPoint = icon.getVisibleCenter();
mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
assertThat(findObjectByResourceName("popup_container")).isNotNull();
return appName;
}
@@ -214,12 +214,12 @@
private void moveAppToCenterOfScreen() {
mEndPoint.set(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight() / 2);
mLauncher.movePointer(mDownTime, SystemClock.uptimeMillis(), DRAG_TIME_MS, true,
- mStartPoint, mEndPoint, LauncherInstrumentation.GestureScope.INSIDE);
+ mStartPoint, mEndPoint, LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
private void dropApp() {
mLauncher.sendPointer(mDownTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,
- mEndPoint, LauncherInstrumentation.GestureScope.INSIDE);
+ mEndPoint, LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
private void removeAppByName(String appName) {
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index c462f59..abb193a 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -29,7 +29,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
import android.content.Intent;
import android.graphics.Point;
@@ -157,107 +156,6 @@
mLauncher.goHome();
}
- @Test
- public void testPressHomeOnAllAppsContextMenu() throws Exception {
- final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- allApps.getAppIcon("TestActivity7").openMenu();
- } finally {
- allApps.unfreeze();
- }
- mLauncher.goHome();
- }
-
- public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) {
- allApps.freeze();
- try {
- assertNotNull("allApps parameter is null", allApps);
-
- assertTrue(
- "Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
-
- // Test flinging forward and backward.
- test.executeOnLauncher(launcher -> assertEquals(
- "All Apps started in already scrolled state", 0,
- test.getAllAppsScroll(launcher)));
-
- allApps.flingForward();
- assertTrue("Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
- final Integer flingForwardY = test.getFromLauncher(
- launcher -> test.getAllAppsScroll(launcher));
- test.executeOnLauncher(
- launcher -> assertTrue("flingForward() didn't scroll App Apps",
- flingForwardY > 0));
-
- allApps.flingBackward();
- assertTrue(
- "Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
- final Integer flingBackwardY = test.getFromLauncher(
- launcher -> test.getAllAppsScroll(launcher));
- test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps",
- flingBackwardY < flingForwardY));
-
- // Test scrolling down to YouTube.
- assertNotNull("All apps: can't find YouTube", allApps.getAppIcon("YouTube"));
- // Test scrolling up to Camera.
- assertNotNull("All apps: can't find Camera", allApps.getAppIcon("Camera"));
- // Test failing to find a non-existing app.
- final AllApps allAppsFinal = allApps;
- expectFail("All apps: could find a non-existing app",
- () -> allAppsFinal.getAppIcon("NO APP"));
-
- assertTrue(
- "Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
- } finally {
- allApps.unfreeze();
- }
- }
-
- @Test
- @PortraitLandscape
- public void testWorkspaceSwitchToAllApps() {
- assertNotNull("switchToAllApps() returned null",
- mLauncher.getWorkspace().switchToAllApps());
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- }
-
- @Test
- @PortraitLandscape
- public void testAllAppsSwitchToWorkspace() {
- assertNotNull("switchToWorkspace() returned null",
- mLauncher.getWorkspace().switchToAllApps()
- .switchToWorkspace(/* swipeDown= */ true));
- assertTrue("Launcher internal state is not Workspace",
- isInState(() -> LauncherState.NORMAL));
- }
-
- @Test
- @PortraitLandscape
- public void testAllAppsSwipeUpToWorkspace() {
- assertNotNull("testAllAppsSwipeUpToWorkspace() returned null",
- mLauncher.getWorkspace().switchToAllApps()
- .switchToWorkspace(/* swipeDown= */ false));
- assertTrue("Launcher internal state is not Workspace",
- isInState(() -> LauncherState.NORMAL));
- }
-
- @Test
- @PortraitLandscape
- public void testAllAppsDeadzoneForTablet() throws Exception {
- assumeTrue(mLauncher.isTablet());
-
- mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
- true /* tapRight */);
- mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
- false /* tapRight */);
- }
-
@PlatinumTest(focusArea = "launcher")
@Test
public void testWorkspace() throws Exception {
@@ -622,7 +520,6 @@
* Adds three icons to the workspace and removes one of them by dragging to uninstall.
*/
@Test
- @ScreenRecord // b/241821721
@PlatinumTest(focusArea = "launcher")
public void uninstallWorkspaceIcon() throws IOException {
Point[] gridPositions = getCornersAndCenterPositions();
@@ -645,10 +542,6 @@
mLauncher.getWorkspace().verifyWorkspaceAppIconIsGone(
DUMMY_APP_NAME + " was expected to disappear after uninstall.", DUMMY_APP_NAME);
- // Debug for b/288944469 I want to test if we are not waiting enough after removing
- // the icon to request the list of icons again, since the items are not removed
- // immediately. This should reduce the flake rate
- SystemClock.sleep(500);
Map<String, Point> finalPositions =
mLauncher.getWorkspace().getWorkspaceIconsPositions();
assertThat(finalPositions).doesNotContainKey(DUMMY_APP_NAME);
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index f2ae9d3..62d70ad 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -103,7 +103,8 @@
if (viewCaptureDataSupplier != null) {
out.putNextEntry(new ZipEntry("FS/data/misc/wmtrace/failed_test.vc"));
- viewCaptureDataSupplier.get().writeTo(out);
+ final ExportedData exportedData = viewCaptureDataSupplier.get();
+ if (exportedData != null) exportedData.writeTo(out);
out.closeEntry();
}
} catch (Exception ignored) {
diff --git a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
index 0f08eef..ccbae4f 100644
--- a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
+++ b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
@@ -20,6 +20,7 @@
import android.media.permission.SafeCloseable
import android.os.Bundle
import androidx.test.core.app.ApplicationProvider
+import androidx.test.platform.app.InstrumentationRegistry
import com.android.app.viewcapture.SimpleViewCapture
import com.android.app.viewcapture.ViewCapture.MAIN_EXECUTOR
import com.android.app.viewcapture.data.ExportedData
@@ -50,6 +51,13 @@
private set
override fun apply(base: Statement, description: Description): Statement {
+ // Skip view capture collection in Launcher3 tests to avoid hidden API check exception.
+ if (
+ "com.android.launcher3.tests" ==
+ InstrumentationRegistry.getInstrumentation().context.packageName
+ )
+ return base
+
return object : Statement() {
override fun evaluate() {
viewCaptureData = null
diff --git a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
index 10afe13..425c3c0 100644
--- a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
+++ b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
@@ -45,8 +45,8 @@
mLauncher.clickObject(
mLauncher.waitForObjectInContainer(
mWidgetCell.getParent().getParent().getParent().getParent(),
- By.text(ADD_AUTOMATICALLY)),
- LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER);
+ By.text(ADD_AUTOMATICALLY))
+ );
mLauncher.waitUntilLauncherObjectGone(getSelector());
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index ebcca00..677f204 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -66,10 +66,6 @@
}
- protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
- return mLauncher.isTablet();
- }
-
protected boolean zeroButtonToOverviewGestureStateTransitionWhileHolding() {
return false;
}
@@ -146,12 +142,9 @@
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
final int startY = getSwipeStartY();
final Point start = new Point(centerX, startY);
- final LauncherInstrumentation.GestureScope gestureScope =
- zeroButtonToOverviewGestureStartsInLauncher()
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
- mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start,
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
if (!mLauncher.isLauncher3()) {
mLauncher.expectEvent(TestProtocol.SEQUENCE_PILFER,
@@ -167,10 +160,6 @@
final Point start = new Point(centerX, startY);
final Point end =
new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
- final LauncherInstrumentation.GestureScope gestureScope =
- zeroButtonToOverviewGestureStartsInLauncher()
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
mLauncher.movePointer(
downTime,
@@ -178,7 +167,7 @@
ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION,
start,
end,
- gestureScope);
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
}
private void sendUpPointerToEnterOverviewToLauncher(long downTime) {
@@ -189,13 +178,9 @@
final Point end =
new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
- final LauncherInstrumentation.GestureScope gestureScope =
- zeroButtonToOverviewGestureStartsInLauncher()
- ? LauncherInstrumentation.GestureScope.INSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER;
-
mLauncher.sendPointer(downTime, SystemClock.uptimeMillis(),
- MotionEvent.ACTION_UP, end, gestureScope);
+ MotionEvent.ACTION_UP, end,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
/**
@@ -227,7 +212,6 @@
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to quick switch to the previous app")) {
verifyActiveContainer();
- final boolean launcherWasVisible = mLauncher.isLauncherVisible();
if (mLauncher.getNavigationModel() == NavigationModel.ZERO_BUTTON
|| mLauncher.getTrackpadGestureType() == TrackpadGestureType.FOUR_FINGER) {
final int startX;
@@ -249,13 +233,10 @@
endY = startY;
}
- LauncherInstrumentation.GestureScope gestureScope =
- launcherWasVisible
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
mLauncher.executeAndWaitForEvent(
() -> mLauncher.linearGesture(
- startX, startY, endX, endY, 20, false, gestureScope),
+ startX, startY, endX, endY, 20, false,
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER),
event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
() -> "Quick switch gesture didn't change window state", "swiping");
} else {
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index ee9dd1a..252435b 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -59,11 +59,6 @@
}
@Override
- protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
- return true;
- }
-
- @Override
protected boolean zeroButtonToOverviewGestureStateTransitionWhileHolding() {
return true;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
index 33c6334..2951901 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
@@ -60,8 +60,8 @@
endY,
5 /* steps */,
NORMAL_STATE_ORDINAL,
- swipeDown ? LauncherInstrumentation.GestureScope.INSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+ swipeDown ? LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER
+ : LauncherInstrumentation.GestureScope.EXPECT_PILFER);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped to workspace")) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 48e327f..3450ea7 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -16,10 +16,14 @@
package com.android.launcher3.tapl;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+
import static com.android.launcher3.testing.shared.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
+import android.app.UiAutomation;
import android.graphics.Point;
import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
@@ -83,12 +87,18 @@
* fired when the click is executed.
*/
public LaunchedAppState launchIntoSplitScreen() {
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "want to launch split tasks from " + launchableType())) {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "want to launch split tasks from " + launchableType())) {
LauncherInstrumentation.log("Launchable.launch before click "
- + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
-
- mLauncher.clickLauncherObject(mObject);
+ + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(
+ mObject));
+ mLauncher.executeAndWaitForLauncherEvent(
+ () -> mLauncher.clickLauncherObject(mObject),
+ accessibilityEvent ->
+ accessibilityEvent.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Unable to click object to launch split",
+ "Click launcher object to launch split");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_START_EVENT);
@@ -152,7 +162,7 @@
downTime,
MotionEvent.ACTION_DOWN,
iconCenter,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
LauncherInstrumentation.log("movePointerForStartDrag: sent down");
expectLongClickEvents.run();
waitForLongPressConfirmation();
@@ -165,7 +175,7 @@
downTime,
downTime,
/* slowDown= */ true,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
private int getStartDragThreshold() {
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index 230be06..30417c0 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -128,13 +128,13 @@
mLauncher.getRealDisplaySize().x / 2, unstashTargetY);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, unstashTarget,
- LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
LauncherInstrumentation.log("showTaskbar: sent down");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget,
- LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
return new Taskbar(mLauncher);
}
@@ -183,7 +183,7 @@
downTime,
SystemClock.uptimeMillis(),
/* slowDown= */ false,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
"moved pointer to drop point")) {
@@ -194,7 +194,7 @@
SystemClock.uptimeMillis(),
MotionEvent.ACTION_UP,
endPoint,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+ "after drop");
@@ -326,7 +326,7 @@
null, InputDevice.SOURCE_MOUSE);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
- LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER,
InputDevice.SOURCE_MOUSE);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_BUTTON_PRESS,
new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
@@ -336,7 +336,7 @@
null, InputDevice.SOURCE_MOUSE);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP,
new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
- LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER,
InputDevice.SOURCE_MOUSE);
return mLauncher.getWorkspace();
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index e6fc244..1bbef36 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -21,7 +21,6 @@
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
-
import static com.android.launcher3.tapl.Folder.FOLDER_CONTENT_RES_ID;
import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -29,12 +28,14 @@
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.UiAutomation;
+import android.app.UiModeManager;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Point;
@@ -102,12 +103,6 @@
static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
static final Pattern EVENT_START = Pattern.compile("start:");
- static final Pattern EVENT_HOVER_ENTER_TIS = getTouchEventPatternTIS("ACTION_HOVER_ENTER");
- static final Pattern EVENT_HOVER_EXIT_TIS = getTouchEventPatternTIS("ACTION_HOVER_EXIT");
- static final Pattern EVENT_BUTTON_PRESS_TIS = getTouchEventPatternTIS("ACTION_BUTTON_PRESS");
- static final Pattern EVENT_BUTTON_RELEASE_TIS =
- getTouchEventPatternTIS("ACTION_BUTTON_RELEASE");
-
private static final Pattern EVENT_KEY_BACK_DOWN =
getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK");
private static final Pattern EVENT_KEY_BACK_UP =
@@ -127,12 +122,10 @@
public enum NavigationModel {ZERO_BUTTON, THREE_BUTTON}
- // Where the gesture happens: outside of Launcher, inside or from inside to outside and
- // whether the gesture recognition triggers pilfer.
+ // Defines whether the gesture recognition triggers pilfer.
public enum GestureScope {
- OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE,
- INSIDE_TO_OUTSIDE_WITH_KEYCODE, // For gestures that will trigger a keycode from TIS.
- OUTSIDE_WITH_KEYCODE,
+ DONT_EXPECT_PILFER,
+ EXPECT_PILFER,
}
public enum TrackpadGestureType {
@@ -181,6 +174,8 @@
static final long DEFAULT_POLL_INTERVAL = 1000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static final String ANDROID_PACKAGE = "android";
+ private static final String ASSISTANT_PACKAGE = "com.google.android.googlequicksearchbox";
+ private static final String ASSISTANT_GO_HOME_RES_ID = "home_icon";
private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
@@ -204,28 +199,6 @@
private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
private int mPointerCount = 0;
- private static Pattern getTouchEventPatternWithPointerCount(String prefix, String action,
- int pointerCount) {
- return Pattern.compile(
- prefix + ": MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
- + ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount="
- + pointerCount);
- }
-
- private static Pattern getTouchEventPatternWithPointerCount(String action, int pointerCount) {
- return getTouchEventPatternWithPointerCount("Touch event", action, pointerCount);
- }
-
- private static Pattern getTouchEventPatternTIS(String action) {
- return getTouchEventPatternWithPointerCount("TouchInteractionService.onInputEvent", action,
- 1);
- }
-
- private static Pattern getTouchEventPatternTIS(String action, int pointerCount) {
- return getTouchEventPatternWithPointerCount("TouchInteractionService.onInputEvent", action,
- pointerCount);
- }
-
private static Pattern getKeyEventPattern(String action, String keyCode) {
return Pattern.compile("Key event: KeyEvent.*action=" + action + ".*keyCode=" + keyCode);
}
@@ -973,8 +946,8 @@
GestureScope gestureScope = gestureStartFromLauncher
// Without the navigation bar layer, the gesture scope on tablets remains inside the
// launcher process.
- ? (isTablet() ? GestureScope.INSIDE : GestureScope.INSIDE_TO_OUTSIDE)
- : GestureScope.OUTSIDE_WITH_PILFER;
+ ? (isTablet() ? GestureScope.DONT_EXPECT_PILFER : GestureScope.EXPECT_PILFER)
+ : GestureScope.EXPECT_PILFER;
linearGesture(
displaySize.x / 2, displaySize.y - 1,
displaySize.x / 2, 0,
@@ -1046,8 +1019,7 @@
displaySize.x / 2, startY,
displaySize.x / 2, endY,
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
- gestureStartFromLauncher ? GestureScope.INSIDE_TO_OUTSIDE
- : GestureScope.OUTSIDE_WITH_PILFER);
+ GestureScope.EXPECT_PILFER);
}
} else {
log("Hierarchy before clicking home:");
@@ -1055,7 +1027,7 @@
action = "clicking home button";
runToState(
- waitForNavigationUiObject("home")::click,
+ getHomeButton()::click,
NORMAL_STATE_ORDINAL,
!hasLauncherObject(WORKSPACE_RES_ID)
&& (hasLauncherObject(APPS_RES_ID)
@@ -1082,15 +1054,12 @@
if (getNavigationModel() == NavigationModel.ZERO_BUTTON
|| isThreeFingerTrackpadGesture) {
final Point displaySize = getRealDisplaySize();
- final GestureScope gestureScope =
- launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
- : GestureScope.OUTSIDE_WITH_KEYCODE;
// TODO(b/225505986): change startY and endY back to displaySize.y / 2 once the
// issue is solved.
int startX = isThreeFingerTrackpadGesture ? displaySize.x / 4 : 0;
int endX = isThreeFingerTrackpadGesture ? displaySize.x * 3 / 4 : displaySize.x / 2;
linearGesture(startX, displaySize.y / 4, endX, displaySize.y / 4,
- 10, false, gestureScope);
+ 10, false, GestureScope.DONT_EXPECT_PILFER);
} else {
waitForNavigationUiObject("back").click();
}
@@ -1239,6 +1208,28 @@
}
@NonNull
+ private UiObject2 getHomeButton() {
+ UiModeManager uiManager =
+ (UiModeManager) getContext().getSystemService(Context.UI_MODE_SERVICE);
+ if (uiManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
+ return waitForAssistantHomeButton();
+ } else {
+ return waitForNavigationUiObject("home");
+ }
+ }
+
+ /* Assistant Home button is present when system is in car mode. */
+ @NonNull
+ UiObject2 waitForAssistantHomeButton() {
+ final UiObject2 object = mDevice.wait(
+ Until.findObject(By.res(ASSISTANT_PACKAGE, ASSISTANT_GO_HOME_RES_ID)),
+ WAIT_TIME_MS);
+ assertNotNull(
+ "Can't find an assistant UI object with id: " + ASSISTANT_GO_HOME_RES_ID, object);
+ return object;
+ }
+
+ @NonNull
UiObject2 waitForNavigationUiObject(String resId) {
String resPackage = getNavigationButtonResPackage();
final UiObject2 object = mDevice.wait(
@@ -1500,15 +1491,17 @@
* animations because in some scenarios there is a playing animations when the click is
* attempted.
*/
- void clickObject(UiObject2 uiObject, GestureScope gestureScope) {
+ void clickObject(UiObject2 uiObject) {
final long clickTime = SystemClock.uptimeMillis();
final Point center = uiObject.getVisibleCenter();
- sendPointer(clickTime, clickTime, MotionEvent.ACTION_DOWN, center, gestureScope);
- sendPointer(clickTime, clickTime, MotionEvent.ACTION_UP, center, gestureScope);
+ sendPointer(clickTime, clickTime, MotionEvent.ACTION_DOWN, center,
+ GestureScope.DONT_EXPECT_PILFER);
+ sendPointer(clickTime, clickTime, MotionEvent.ACTION_UP, center,
+ GestureScope.DONT_EXPECT_PILFER);
}
void clickLauncherObject(UiObject2 object) {
- clickObject(object, GestureScope.INSIDE);
+ clickObject(object);
}
void scrollToLastVisibleRow(
@@ -1601,7 +1594,8 @@
executeAndWaitForLauncherEvent(
() -> linearGesture(
- startX, startY, endX, endY, steps, slowDown, GestureScope.INSIDE),
+ startX, startY, endX, endY, steps, slowDown,
+ GestureScope.DONT_EXPECT_PILFER),
event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
() -> "Didn't receive a scroll end message: " + startX + ", " + startY
+ ", " + endX + ", " + endY,
@@ -1721,11 +1715,6 @@
TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
- boolean isTrackpadGestureEnabled() {
- return getTestInfo(TestProtocol.REQUEST_IS_TRACKPAD_GESTURE_ENABLED).getBoolean(
- TestProtocol.TEST_INFO_RESPONSE_FIELD);
- }
-
boolean isGridOnlyOverviewEnabled() {
return getTestInfo(TestProtocol.REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW).getBoolean(
TestProtocol.TEST_INFO_RESPONSE_FIELD);
@@ -1743,7 +1732,6 @@
int pointerCount = mPointerCount;
boolean isTrackpadGesture = mTrackpadGestureType != TrackpadGestureType.NONE;
- boolean isTwoFingerTrackpadGesture = mTrackpadGestureType == TrackpadGestureType.TWO_FINGER;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (isTrackpadGesture) {
@@ -1752,59 +1740,18 @@
}
break;
case MotionEvent.ACTION_UP:
- if (hasTIS
- && (gestureScope == GestureScope.OUTSIDE_WITH_PILFER
- || gestureScope == GestureScope.INSIDE_TO_OUTSIDE)) {
+ if (hasTIS && gestureScope == GestureScope.EXPECT_PILFER) {
expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);
}
break;
- case MotionEvent.ACTION_HOVER_ENTER:
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_ENTER_TIS);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_EXIT_TIS);
- break;
case MotionEvent.ACTION_POINTER_DOWN:
mPointerCount++;
- if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
- && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
- expectEvent(TestProtocol.SEQUENCE_MAIN, getTouchEventPatternWithPointerCount(
- "ACTION_POINTER_DOWN", mPointerCount));
- }
- if (hasTIS && (isTrackpadGestureEnabled()
- || getNavigationModel() != NavigationModel.THREE_BUTTON)) {
- expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
- "ACTION_POINTER_DOWN", mPointerCount));
- }
pointerCount = mPointerCount;
break;
case MotionEvent.ACTION_POINTER_UP:
- if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
- && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
- expectEvent(TestProtocol.SEQUENCE_MAIN, getTouchEventPatternWithPointerCount(
- "ACTION_POINTER_UP", mPointerCount));
- }
// When the gesture is handled outside, it's cancelled within launcher.
- if (hasTIS && (isTrackpadGestureEnabled()
- || getNavigationModel() != NavigationModel.THREE_BUTTON)) {
- if (gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
- && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
- expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
- "ACTION_POINTER_UP", mPointerCount));
- }
- }
mPointerCount--;
break;
- case MotionEvent.ACTION_BUTTON_PRESS:
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_BUTTON_PRESS_TIS);
- break;
- case MotionEvent.ACTION_BUTTON_RELEASE:
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_BUTTON_RELEASE_TIS);
- break;
}
final MotionEvent event = isTrackpadGesture
@@ -1883,11 +1830,12 @@
@NonNull final UiObject2 target, @NonNull String resName, Pattern longClickEvent) {
final Point targetCenter = target.getVisibleCenter();
final long downTime = SystemClock.uptimeMillis();
- sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetCenter, GestureScope.INSIDE);
+ sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetCenter,
+ GestureScope.DONT_EXPECT_PILFER);
expectEvent(TestProtocol.SEQUENCE_MAIN, longClickEvent);
final UiObject2 result = waitForLauncherObject(resName);
sendPointer(downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, targetCenter,
- GestureScope.INSIDE);
+ GestureScope.DONT_EXPECT_PILFER);
return result;
}
@@ -2168,9 +2116,9 @@
final long downTime = SystemClock.uptimeMillis();
final Point tapTarget = new Point(x, y);
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 39b93b4..e4cfc52 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -124,7 +124,7 @@
final int centerY = taskBounds.centerY();
mLauncher.executeAndWaitForLauncherEvent(
() -> mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
- LauncherInstrumentation.GestureScope.INSIDE),
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER),
event -> TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE.equals(event.getClassName()),
() -> "Didn't receive a dismiss animation ends message: " + centerX + ", "
+ centerY, "swiping to dismiss");
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
index d02e747..0895d93 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -91,7 +91,7 @@
* Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only.
* @param tapRight Tap on the right of bottom sheet if true, or left otherwise.
*/
- public Workspace dismissByTappingOutsideForTablet(boolean tapRight) {
+ public void dismissByTappingOutsideForTablet(boolean tapRight) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to tap outside AllApps bottom sheet on the "
@@ -101,8 +101,12 @@
mLauncher.touchOutsideContainer(allAppsBottomSheet, tapRight);
try (LauncherInstrumentation.Closable tapped = mLauncher.addContextLayer(
"tapped outside AllApps bottom sheet")) {
- return mLauncher.getWorkspace();
+ verifyVisibleContainerOnDismiss();
}
}
}
+
+ protected void verifyVisibleContainerOnDismiss() {
+ mLauncher.getWorkspace();
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromTaskbarQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromTaskbarQsb.java
index 6c6ab05..00291a3 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromTaskbarQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromTaskbarQsb.java
@@ -45,4 +45,9 @@
protected TaskbarSearchWebSuggestion createWebSuggestion(UiObject2 webSuggestion) {
return new TaskbarSearchWebSuggestion(mLauncher, webSuggestion);
}
+
+ @Override
+ protected void verifyVisibleContainerOnDismiss() {
+ mLauncher.getLaunchedAppState().assertTaskbarVisible();
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
index 051630e..4293ee8 100644
--- a/tests/tapl/com/android/launcher3/tapl/Taskbar.java
+++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
@@ -76,13 +76,13 @@
mLauncher.getRealDisplaySize().x - 1, mLauncher.getRealDisplaySize().y - 1);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, stashTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
LauncherInstrumentation.log("hideTaskbar: sent down");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, stashTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
} finally {
mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
@@ -92,7 +92,7 @@
/**
* Opens the Taskbar all apps page.
*/
- public AllAppsFromTaskbar openAllApps() {
+ public TaskbarAllApps openAllApps() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to open taskbar all apps");
LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
@@ -101,7 +101,15 @@
mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID),
getAllAppsButtonSelector()));
- return new AllAppsFromTaskbar(mLauncher);
+ return getAllApps();
+ }
+ }
+
+ /** Returns {@link TaskbarAllApps} if it is open, otherwise fails. */
+ public TaskbarAllApps getAllApps() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get taskbar all apps object")) {
+ return new TaskbarAllApps(mLauncher);
}
}
@@ -147,9 +155,9 @@
mLauncher.getRealDisplaySize().y - 1);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAllApps.java
similarity index 94%
rename from tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
rename to tests/tapl/com/android/launcher3/tapl/TaskbarAllApps.java
index 0e0291f..63185f9 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAllApps.java
@@ -23,9 +23,9 @@
/**
* Operations on AllApps opened from the Taskbar.
*/
-public class AllAppsFromTaskbar extends AllApps {
+public class TaskbarAllApps extends AllApps {
- AllAppsFromTaskbar(LauncherInstrumentation launcher) {
+ TaskbarAllApps(LauncherInstrumentation launcher) {
super(launcher);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 8604988..cf48ebc 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -27,6 +27,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -104,7 +105,8 @@
windowCornerRadius,
startY - swipeHeight - mLauncher.getTouchSlop(),
12,
- ALL_APPS_STATE_ORDINAL, LauncherInstrumentation.GestureScope.INSIDE);
+ ALL_APPS_STATE_ORDINAL,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped to all apps")) {
@@ -285,6 +287,10 @@
final UiObject2 workspace = verifyActiveContainer();
List<UiObject2> workspaceIcons =
mLauncher.waitForObjectsInContainer(workspace, AppIcon.getAnyAppIconSelector());
+ Log.d("b/288944469", "List size = " + workspaceIcons.size());
+ for (int i = 0; i < workspaceIcons.size(); i++) {
+ Log.d("b/288944469", "index = " + i + " tesxt = " + workspaceIcons.get(i).getText());
+ }
return workspaceIcons.stream()
.collect(
Collectors.toMap(
@@ -386,7 +392,7 @@
Until.hasObject(installerAlert), LauncherInstrumentation.WAIT_TIME_MS));
final UiObject2 ok = device.findObject(By.text("OK"));
assertNotNull("OK button is not shown", ok);
- launcher.clickObject(ok, LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER);
+ launcher.clickObject(ok);
assertTrue("Uninstall alert is not dismissed after clicking OK", device.wait(
Until.gone(installerAlert), LauncherInstrumentation.WAIT_TIME_MS));
@@ -453,7 +459,7 @@
launcher.runToState(
() -> launcher.sendPointer(
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest,
- LauncherInstrumentation.GestureScope.INSIDE),
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER),
NORMAL_STATE_ORDINAL,
"sending UP event");
if (expectedEvents != null) {
@@ -542,7 +548,7 @@
executeAndWaitForPageScroll(launcher,
() -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
true, downTime, downTime, true,
- LauncherInstrumentation.GestureScope.INSIDE));
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER));
targetDest.x += displayX * (targetDest.x > 0 ? -1 : 1);
dragStart = screenEdge;
}
@@ -551,7 +557,7 @@
// we just have to put move the icon to the destination and drop it
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating,
downTime, SystemClock.uptimeMillis(), false,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}
}
@@ -584,7 +590,7 @@
// we just have to put move the icon to the destination and drop it
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating,
downTime, SystemClock.uptimeMillis(), false,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}
}
@@ -621,7 +627,7 @@
executeAndWaitForPageScroll(launcher,
() -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
true, downTime, downTime, true,
- LauncherInstrumentation.GestureScope.INSIDE));
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER));
currentPage = Workspace.geCurrentPage(launcher);
currentPosition = screenEdge;
}
@@ -650,7 +656,7 @@
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, true,
downTime, SystemClock.uptimeMillis(), false,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}