Merge "Recents Go: Conform to device default style" into ub-launcher3-qt-dev
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 819e6bc..ef5bb26 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -154,13 +154,13 @@
<!--
The content provider for exposing various launcher grid options.
- TODO: Enable when all apps columns are correct
TODO: Add proper permissions
+ -->
<provider
android:name="com.android.launcher3.graphics.GridOptionsProvider"
android:authorities="${packageName}.grid_control"
+ android:enabled="false"
android:exported="true" />
- -->
<!--
The settings activity. To extend point settings_fragment_name to appropriate fragment class
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 70f0c01..b031ffb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,7 +20,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
- <uses-sdk android:targetSdkVersion="28" android:minSdkVersion="25"/>
+ <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
<!--
Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
Refer comments around specific entries on how to extend individual components.
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
index ebae1cd..336cdc9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -76,8 +76,13 @@
@Override
public void mapInsets(Context context, Rect insets, Rect out) {
+ // If there is a display cutout, the top insets in portrait would also include the
+ // cutout, which we will get as the left inset in landscape. Using the max of left and
+ // top allows us to cover both cases (with or without cutout).
if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
- out.set(insets);
+ out.top = Math.max(insets.top, insets.left);
+ out.bottom = Math.max(insets.right, insets.bottom);
+ out.left = out.right = 0;
} else {
out.top = Math.max(insets.top, insets.left);
out.bottom = insets.right;
@@ -99,7 +104,9 @@
@Override
public void mapInsets(Context context, Rect insets, Rect out) {
if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
- out.set(insets);
+ out.top = Math.max(insets.top, insets.right);
+ out.bottom = Math.max(insets.left, insets.bottom);
+ out.left = out.right = 0;
} else {
out.top = Math.max(insets.top, insets.right);
out.bottom = insets.left;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index c3a7698..1d36d1a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.LauncherState.RECENTS_CLEAR_ALL_BUTTON;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
+import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
@@ -64,6 +65,7 @@
}
}
setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state.getVisibleElements(mLauncher));
+ mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
}
@Override
@@ -95,7 +97,10 @@
builder.addOnFinishRunnable(() -> mRecentsView.setHintVisibility(1f));
}
- setAlphas(config.getPropertySetter(builder), toState.getVisibleElements(mLauncher));
+ PropertySetter propertySetter = config.getPropertySetter(builder);
+ setAlphas(propertySetter, toState.getVisibleElements(mLauncher));
+ float fullscreenProgress = toState.getOverviewFullscreenProgress();
+ propertySetter.setFloat(mRecentsView, FULLSCREEN_PROGRESS, fullscreenProgress, LINEAR);
}
private void setAlphas(PropertySetter propertySetter, int visibleElements) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 140e45c..a662d74 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -17,14 +17,14 @@
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
-import android.os.RemoteException;
-
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.quickstep.RecentsModel;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.recents.ISystemUiProxy;
+import com.android.quickstep.views.TaskView;
/**
* State indicating that the Launcher is behind an app
@@ -35,7 +35,18 @@
FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
public BackgroundAppState(int id) {
- super(id, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
+ this(id, LauncherLogProto.ContainerType.TASKSWITCHER);
+ }
+
+ protected BackgroundAppState(int id, int logContainer) {
+ super(id, logContainer, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
+ }
+
+ @Override
+ public void onStateEnabled(Launcher launcher) {
+ RecentsView rv = launcher.getOverviewPanel();
+ rv.setOverviewStateEnabled(true);
+ AbstractFloatingView.closeAllOpenViews(launcher, false);
}
@Override
@@ -55,23 +66,17 @@
public ScaleAndTranslation getOverviewScaleAndTranslation(Launcher launcher) {
// Initialize the recents view scale to what it would be when starting swipe up
RecentsView recentsView = launcher.getOverviewPanel();
- recentsView.getTaskSize(sTempRect);
- int appWidth = launcher.getDragLayer().getWidth();
- if (recentsView.shouldUseMultiWindowTaskSizeStrategy()) {
- ISystemUiProxy sysUiProxy = RecentsModel.INSTANCE.get(launcher).getSystemUiProxy();
- if (sysUiProxy != null) {
- try {
- // Try to use the actual non-minimized app width (launcher will be resized to
- // the non-minimized bounds, which differs from the app width in landscape
- // multi-window mode
- appWidth = sysUiProxy.getNonMinimizedSplitScreenSecondaryBounds().width();
- } catch (RemoteException e) {
- // Ignore, fall back to just using the drag layer width
- }
- }
+ if (recentsView.getTaskViewCount() == 0) {
+ return super.getOverviewScaleAndTranslation(launcher);
}
- float scale = (float) appWidth / sTempRect.width();
- return new ScaleAndTranslation(scale, 0f, 0f);
+ TaskView dummyTask = recentsView.getTaskViewAt(recentsView.getCurrentPage());
+ return recentsView.getTempClipAnimationHelper().updateForFullscreenOverview(dummyTask)
+ .getScaleAndTranslation();
+ }
+
+ @Override
+ public float getOverviewFullscreenProgress() {
+ return 1;
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
index c26a1d0..ed511f5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
@@ -15,11 +15,8 @@
*/
package com.android.launcher3.uioverrides.states;
-import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
-
import com.android.launcher3.Launcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -28,23 +25,10 @@
* quick switching from launcher; quick switching from an app uses WindowTransformSwipeHelper.
* @see com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget#NEW_TASK
*/
-public class QuickSwitchState extends OverviewState {
- private static final int STATE_FLAGS =
- FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
+public class QuickSwitchState extends BackgroundAppState {
public QuickSwitchState(int id) {
- super(id, LauncherLogProto.ContainerType.APP, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
- }
-
- @Override
- public ScaleAndTranslation getOverviewScaleAndTranslation(Launcher launcher) {
- RecentsView recentsView = launcher.getOverviewPanel();
- if (recentsView.getTaskViewCount() == 0) {
- return super.getOverviewScaleAndTranslation(launcher);
- }
- TaskView dummyTask = recentsView.getTaskViewAt(0);
- ClipAnimationHelper clipAnimationHelper = new ClipAnimationHelper(launcher);
- return clipAnimationHelper.getOverviewFullscreenScaleAndTranslation(dummyTask);
+ super(id, LauncherLogProto.ContainerType.APP);
}
@Override
@@ -56,11 +40,6 @@
}
@Override
- public float getVerticalProgress(Launcher launcher) {
- return BACKGROUND_APP.getVerticalProgress(launcher);
- }
-
- @Override
public int getVisibleElements(Launcher launcher) {
return NONE;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 8b4aa07..8e32bb3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -18,8 +18,8 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
-import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -231,7 +231,8 @@
} else {
mFlingBlockCheck.onEvent();
}
- mCurrentAnimation.setPlayFraction(totalDisplacement * mProgressMultiplier);
+ mCurrentAnimation.setPlayFraction(Utilities.boundToRange(
+ totalDisplacement * mProgressMultiplier, 0, 1));
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsView.getCurrentPage() != 0 || isGoingUp) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
index 434353d..90b5536 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -55,7 +55,6 @@
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -185,6 +184,12 @@
@Override
public void createActivityController(long transitionLength) {
createActivityControllerInternal(activity, fromState, transitionLength, callback);
+ // Creating the activity controller animation sometimes reapplies the launcher state
+ // (because we set the animation as the current state animation), so we reapply the
+ // attached state here as well to ensure recents is shown/hidden appropriately.
+ if (SysUINavigationMode.getMode(activity) == Mode.NO_BUTTON) {
+ setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
+ }
}
@Override
@@ -266,7 +271,7 @@
endState.getVerticalProgress(activity));
anim.play(shiftAnim);
}
- playScaleDownAnim(anim, activity, endState);
+ playScaleDownAnim(anim, activity, fromState, endState);
anim.setDuration(transitionLength * 2);
AnimatorPlaybackController controller =
@@ -292,7 +297,7 @@
/**
* Scale down recents from the center task being full screen to being in overview.
*/
- private void playScaleDownAnim(AnimatorSet anim, Launcher launcher,
+ private void playScaleDownAnim(AnimatorSet anim, Launcher launcher, LauncherState fromState,
LauncherState endState) {
RecentsView recentsView = launcher.getOverviewPanel();
TaskView v = recentsView.getTaskViewAt(recentsView.getCurrentPage());
@@ -300,19 +305,23 @@
return;
}
- ClipAnimationHelper clipHelper = new ClipAnimationHelper(launcher);
LauncherState.ScaleAndTranslation fromScaleAndTranslation
- = clipHelper.getOverviewFullscreenScaleAndTranslation(v);
+ = fromState.getOverviewScaleAndTranslation(launcher);
LauncherState.ScaleAndTranslation endScaleAndTranslation
= endState.getOverviewScaleAndTranslation(launcher);
+ float fromFullscreenProgress = fromState.getOverviewFullscreenProgress();
+ float endFullscreenProgress = endState.getOverviewFullscreenProgress();
Animator scale = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY,
fromScaleAndTranslation.scale, endScaleAndTranslation.scale);
Animator translateY = ObjectAnimator.ofFloat(recentsView, TRANSLATION_Y,
fromScaleAndTranslation.translationY, endScaleAndTranslation.translationY);
+ Animator applyFullscreenProgress = ObjectAnimator.ofFloat(recentsView,
+ RecentsView.FULLSCREEN_PROGRESS, fromFullscreenProgress, endFullscreenProgress);
scale.setInterpolator(LINEAR);
translateY.setInterpolator(LINEAR);
- anim.playTogether(scale, translateY);
+ applyFullscreenProgress.setInterpolator(LINEAR);
+ anim.playTogether(scale, translateY, applyFullscreenProgress);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
index 194d073..5a039cd 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java
@@ -22,6 +22,7 @@
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
+import java.io.PrintWriter;
/**
* Utility class used to store state information shared across multiple transitions.
@@ -134,4 +135,13 @@
nextRunningTaskId = -1;
goingToLauncher = false;
}
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "goingToLauncher=" + goingToLauncher);
+ pw.println(prefix + "canGestureBeContinued=" + canGestureBeContinued);
+ pw.println(prefix + "recentsAnimationFinishInterrupted=" + recentsAnimationFinishInterrupted);
+ pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId);
+ pw.println(prefix + "lastAnimationCancelled=" + mLastAnimationCancelled);
+ pw.println(prefix + "lastAnimationRunning=" + mLastAnimationRunning);
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
index 2c919b3..213c5d3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
@@ -226,7 +226,7 @@
// TODO(b/118266305): Temporarily disable splitscreen for secondary display while new
// implementation is enabled
return !activity.getDeviceProfile().isMultiWindowMode
- && displayId == DEFAULT_DISPLAY;
+ && (displayId == -1 || displayId == DEFAULT_DISPLAY);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 128fd45..0c997dd 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -84,9 +84,32 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
/**
+ * Wrapper around a list for processing arguments.
+ */
+class ArgList extends LinkedList<String> {
+ public ArgList(List<String> l) {
+ super(l);
+ }
+
+ public String peekArg() {
+ return peekFirst();
+ }
+
+ public String nextArg() {
+ return pollFirst().toLowerCase();
+ }
+
+ public String nextArgExact() {
+ return pollFirst();
+ }
+}
+
+/**
* Service connected by system-UI for handling touch interaction.
*/
@TargetApi(Build.VERSION_CODES.Q)
@@ -308,21 +331,29 @@
defaultDisplay.getRealSize(realSize);
mSwipeTouchRegion.set(0, 0, realSize.x, realSize.y);
if (mMode == Mode.NO_BUTTON) {
- mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(
- ResourceUtils.NAVBAR_VERTICAL_SIZE);
+ switch (defaultDisplay.getRotation()) {
+ case Surface.ROTATION_90:
+ case Surface.ROTATION_270:
+ mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(
+ ResourceUtils.NAVBAR_LANDSCAPE_BOTTOM_SIZE);
+ break;
+ default:
+ mSwipeTouchRegion.top = mSwipeTouchRegion.bottom - getNavbarSize(
+ ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE);
+ }
} else {
switch (defaultDisplay.getRotation()) {
case Surface.ROTATION_90:
mSwipeTouchRegion.left = mSwipeTouchRegion.right
- - getNavbarSize(ResourceUtils.NAVBAR_HORIZONTAL_SIZE);
+ - getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
break;
case Surface.ROTATION_270:
mSwipeTouchRegion.right = mSwipeTouchRegion.left
- + getNavbarSize(ResourceUtils.NAVBAR_HORIZONTAL_SIZE);
+ + getNavbarSize(ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
break;
default:
mSwipeTouchRegion.top = mSwipeTouchRegion.bottom
- - getNavbarSize(ResourceUtils.NAVBAR_VERTICAL_SIZE);
+ - getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE);
}
}
}
@@ -439,12 +470,18 @@
mUncheckedConsumer.onMotionEvent(event);
}
+ private boolean validSystemUiFlags() {
+ return (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
+ && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0;
+ }
+
+ private boolean topTaskLocked() {
+ return ActivityManagerWrapper.getInstance().isLockToAppActive();
+ }
private InputConsumer newConsumer(boolean useSharedState, MotionEvent event) {
- boolean validSystemUIFlags = (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
- && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0;
- boolean topTaskLocked = ActivityManagerWrapper.getInstance().isLockToAppActive();
- boolean isInValidSystemUiState = validSystemUIFlags && !topTaskLocked;
+ boolean topTaskLocked = topTaskLocked();
+ boolean isInValidSystemUiState = validSystemUiFlags() && !topTaskLocked;
if (!mIsUserUnlocked) {
if (isInValidSystemUiState) {
@@ -476,7 +513,7 @@
if ((mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0) {
base = new AccessibilityInputConsumer(this, mISystemUiProxy,
(mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0, base,
- mInputMonitorCompat);
+ mInputMonitorCompat, mSwipeTouchRegion);
}
}
return base;
@@ -527,7 +564,7 @@
return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
mOverviewComponentObserver.getOverviewIntent(), activityControl,
shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive,
- mSwipeSharedState, mInputMonitorCompat);
+ mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion);
}
/**
@@ -540,7 +577,55 @@
}
@Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- TOUCH_INTERACTION_LOG.dump("", pw);
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
+ if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) {
+ ArgList args = new ArgList(Arrays.asList(rawArgs));
+ switch (args.nextArg()) {
+ case "cmd":
+ if (args.peekArg() == null) {
+ printAvailableCommands(pw);
+ } else {
+ onCommand(pw, args);
+ }
+ break;
+ }
+ } else {
+ // Dump everything
+ pw.println("TouchState:");
+ pw.println(" navMode=" + mMode);
+ pw.println(" validSystemUiFlags=" + validSystemUiFlags()
+ + " flags=" + mSystemUiStateFlags);
+ pw.println(" topTaskLocked=" + topTaskLocked());
+ pw.println(" isDeviceLocked=" + mKM.isDeviceLocked());
+ pw.println(" screenPinned=" +
+ ActivityManagerWrapper.getInstance().isScreenPinningActive());
+ pw.println(" assistantAvailable=" + mAssistantAvailable);
+ pw.println(" a11yClickable="
+ + ((mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0));
+ pw.println(" a11yLongClickable="
+ + ((mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0));
+ pw.println(" resumed="
+ + mOverviewComponentObserver.getActivityControlHelper().isResumed());
+ pw.println(" useSharedState=" + mConsumer.useSharedSwipeState());
+ if (mConsumer.useSharedSwipeState()) {
+ mSwipeSharedState.dump(" ", pw);
+ }
+ pw.println(" mConsumer=" + mConsumer.getName());
+ TOUCH_INTERACTION_LOG.dump("", pw);
+
+ }
+ }
+
+ private void printAvailableCommands(PrintWriter pw) {
+ pw.println("Available commands:");
+ pw.println(" clear-touch-log: Clears the touch interaction log");
+ }
+
+ private void onCommand(PrintWriter pw, ArgList args) {
+ switch (args.nextArg()) {
+ case "clear-touch-log":
+ TOUCH_INTERACTION_LOG.clear();
+ break;
+ }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 29034ea..2ff5c0c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -170,8 +170,7 @@
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
public enum GestureEndTarget {
- HOME(1, STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT, true, false,
- ContainerType.WORKSPACE, false),
+ HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE, false),
RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
| STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER, true),
@@ -332,8 +331,9 @@
| STATE_SCALED_CONTROLLER_RECENTS,
this::finishCurrentTransitionToRecents);
- mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
- | STATE_SCALED_CONTROLLER_HOME,
+ mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_COMPLETED
+ | STATE_SCALED_CONTROLLER_HOME | STATE_APP_CONTROLLER_RECEIVED
+ | STATE_LAUNCHER_DRAWN,
this::finishCurrentTransitionToHome);
mStateCallback.addCallback(STATE_SCALED_CONTROLLER_HOME | STATE_CURRENT_TASK_FINISHED,
this::reset);
@@ -504,6 +504,7 @@
private void setupRecentsViewUi() {
if (mContinuingLastGesture) {
+ updateSysUiFlags(mCurrentShift.value);
return;
}
mRecentsView.onGestureAnimationStart(mRunningTaskId);
@@ -677,15 +678,6 @@
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
- // Update insets of the non-running tasks, as we might switch to them.
- int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex();
- if (runningTaskIndex >= 0) {
- for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) {
- if (i != runningTaskIndex || !mRecentsAnimationWrapper.hasTargets()) {
- mRecentsView.getTaskViewAt(i).setFullscreenProgress(1 - mCurrentShift.value);
- }
- }
- }
if (mLauncherTransitionController == null || mLauncherTransitionController
.getAnimationPlayer().isStarted()) {
@@ -706,12 +698,15 @@
private void updateSysUiFlags(float windowProgress) {
if (mRecentsView != null) {
+ TaskView centermostTask = mRecentsView.getTaskViewAt(mRecentsView
+ .getPageNearestToCenterOfScreen());
+ int centermostTaskFlags = centermostTask == null ? 0
+ : centermostTask.getThumbnail().getSysUiStatusNavFlags();
+ boolean useHomeScreenFlags = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
// We will handle the sysui flags based on the centermost task view.
- mRecentsAnimationWrapper.setWindowThresholdCrossed(true);
- int sysuiFlags = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD
- ? 0
- : mRecentsView.getTaskViewAt(mRecentsView.getPageNearestToCenterOfScreen())
- .getThumbnail().getSysUiStatusNavFlags();
+ mRecentsAnimationWrapper.setWindowThresholdCrossed(centermostTaskFlags != 0
+ || useHomeScreenFlags);
+ int sysuiFlags = useHomeScreenFlags ? 0 : centermostTaskFlags;
mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, sysuiFlags);
}
}
@@ -907,7 +902,7 @@
float minFlingVelocity = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_min_velocity);
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
- if (endTarget == RECENTS) {
+ if (endTarget == RECENTS && mMode != Mode.NO_BUTTON) {
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
startShift, endShift, endShift, velocityPxPerMs.y,
mTransitionDragLength);
@@ -923,6 +918,10 @@
// derivative of the scroll interpolator at zero, ie. 2.
long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y));
duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
+
+ if (endTarget == RECENTS) {
+ interpolator = OVERSHOOT_1_2;
+ }
}
}
}
@@ -937,7 +936,8 @@
} else if (endTarget == RECENTS) {
mLiveTileOverlay.startIconAnimation();
if (mRecentsView != null) {
- duration = Math.max(duration, mRecentsView.getScroller().getDuration());
+ duration = Utilities.boundToRange(mRecentsView.getScroller().getDuration(),
+ duration, MAX_SWIPE_DURATION);
}
if (mMode == Mode.NO_BUTTON) {
setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
index f8475ca..1f73a28 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
@@ -23,6 +23,7 @@
import static android.view.MotionEvent.ACTION_UP;
import android.content.Context;
+import android.graphics.RectF;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
@@ -46,6 +47,7 @@
private final VelocityTracker mVelocityTracker;
private final MotionPauseDetector mMotionPauseDetector;
private final boolean mAllowLongClick;
+ private final RectF mSwipeTouchRegion;
private final float mMinGestureDistance;
private final float mMinFlingVelocity;
@@ -55,13 +57,15 @@
private float mTotalY;
public AccessibilityInputConsumer(Context context, ISystemUiProxy systemUiProxy,
- boolean allowLongClick, InputConsumer delegate, InputMonitorCompat inputMonitor) {
+ boolean allowLongClick, InputConsumer delegate, InputMonitorCompat inputMonitor,
+ RectF swipeTouchRegion) {
super(delegate, inputMonitor);
mSystemUiProxy = systemUiProxy;
mVelocityTracker = VelocityTracker.obtain();
mMinGestureDistance = context.getResources()
.getDimension(R.dimen.accessibility_gesture_min_swipe_distance);
mMinFlingVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
+ mSwipeTouchRegion = swipeTouchRegion;
mMotionPauseDetector = new MotionPauseDetector(context);
mAllowLongClick = allowLongClick;
@@ -98,10 +102,11 @@
}
case ACTION_POINTER_DOWN: {
if (mState == STATE_INACTIVE) {
- if (mDelegate.allowInterceptByParent()) {
+ int pointerIndex = ev.getActionIndex();
+ if (mSwipeTouchRegion.contains(ev.getX(pointerIndex), ev.getY(pointerIndex))
+ && mDelegate.allowInterceptByParent()) {
setActive(ev);
- int pointerIndex = ev.getActionIndex();
mActivePointerId = ev.getPointerId(pointerIndex);
mDownY = ev.getY(pointerIndex);
} else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java
index 0448fd1..bf276e1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java
@@ -19,8 +19,11 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
+
+import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.FLING;
@@ -38,6 +41,8 @@
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
@@ -78,7 +83,7 @@
private final float mDistThreshold;
private final long mTimeThreshold;
private final int mAngleThreshold;
- private final float mSlop;
+ private final float mSquaredSlop;
private final ISystemUiProxy mSysUiProxy;
private final Context mContext;
private final SwipeDetector mSwipeDetector;
@@ -93,7 +98,10 @@
mDistThreshold = res.getDimension(R.dimen.gestures_assistant_drag_threshold);
mTimeThreshold = res.getInteger(R.integer.assistant_gesture_min_time_threshold);
mAngleThreshold = res.getInteger(R.integer.assistant_gesture_corner_deg_threshold);
- mSlop = QuickStepContract.getQuickStepDragSlopPx();
+
+ float slop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+ mSquaredSlop = slop * slop;
mActivityControlHelper = activityControlHelper;
mSwipeDetector = new SwipeDetector(mContext, this, SwipeDetector.VERTICAL);
mSwipeDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false);
@@ -117,6 +125,12 @@
mTimeFraction = 0;
break;
}
+ case ACTION_POINTER_DOWN: {
+ if (mState != STATE_ACTIVE) {
+ mState = STATE_DELEGATE_ACTIVE;
+ break;
+ }
+ }
case ACTION_POINTER_UP: {
int ptrIdx = ev.getActionIndex();
int ptrId = ev.getPointerId(ptrIdx);
@@ -146,7 +160,8 @@
if (!mPassedSlop) {
// Normal gesture, ensure we pass the slop before we start tracking the gesture
- if (Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) > mSlop) {
+ if (squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y)
+ > mSquaredSlop) {
mPassedSlop = true;
mStartDragPos.set(mLastPos.x, mLastPos.y);
@@ -209,31 +224,35 @@
private void updateAssistantProgress() {
if (!mLaunchedAssistant) {
mLastProgress = Math.min(mDistance * 1f / mDistThreshold, 1) * mTimeFraction;
- updateAssistant(SWIPE);
+ try {
+ if (mDistance >= mDistThreshold && mTimeFraction >= 1) {
+ mSysUiProxy.onAssistantGestureCompletion(0);
+ startAssistantInternal(SWIPE);
+
+ Bundle args = new Bundle();
+ args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE);
+ mSysUiProxy.startAssistant(args);
+ mLaunchedAssistant = true;
+ } else {
+ mSysUiProxy.onAssistantProgress(mLastProgress);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + mLastProgress,
+ e);
+ }
}
}
- private void updateAssistant(int gestureType) {
- try {
- mSysUiProxy.onAssistantProgress(mLastProgress);
- if (gestureType == FLING || (mDistance >= mDistThreshold && mTimeFraction >= 1)) {
- UserEventDispatcher.newInstance(mContext)
- .logActionOnContainer(gestureType, mDirection, NAVBAR);
- Bundle args = new Bundle();
- args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE);
+ private void startAssistantInternal(int gestureType) {
+ UserEventDispatcher.newInstance(mContext)
+ .logActionOnContainer(gestureType, mDirection, NAVBAR);
- BaseDraggingActivity launcherActivity = mActivityControlHelper.getCreatedActivity();
- if (launcherActivity != null) {
- launcherActivity.getRootView().performHapticFeedback(
- 13, // HapticFeedbackConstants.GESTURE_END
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- }
-
- mSysUiProxy.startAssistant(args);
- mLaunchedAssistant = true;
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + mLastProgress, e);
+ BaseDraggingActivity launcherActivity = mActivityControlHelper
+ .getCreatedActivity();
+ if (launcherActivity != null) {
+ launcherActivity.getRootView().performHapticFeedback(
+ 13, // HapticFeedbackConstants.GESTURE_END
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
@@ -257,9 +276,20 @@
@Override
public void onDragEnd(float velocity, boolean fling) {
- if (fling) {
+ if (fling && !mLaunchedAssistant && mState != STATE_DELEGATE_ACTIVE) {
mLastProgress = 1;
- updateAssistant(FLING);
+ try {
+ mSysUiProxy.onAssistantGestureCompletion(velocity);
+ startAssistantInternal(FLING);
+
+ Bundle args = new Bundle();
+ args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE);
+ mSysUiProxy.startAssistant(args);
+ mLaunchedAssistant = true;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + mLastProgress,
+ e);
+ }
}
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index b1d175d..d01b5ec 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -15,11 +15,13 @@
*/
package com.android.quickstep.inputconsumers;
+import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.Utilities.squaredTouchSlop;
+
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
import android.view.MotionEvent;
-import android.view.ViewConfiguration;
/**
* A dummy input consumer used when the device is still locked, e.g. from secure camera.
@@ -32,8 +34,7 @@
public DeviceLockedInputConsumer(Context context) {
mContext = context;
- float touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
- mTouchSlopSquared = touchSlop * touchSlop;
+ mTouchSlopSquared = squaredTouchSlop(context);
}
@Override
@@ -48,9 +49,7 @@
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mTouchDown.set(x, y);
} else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
- float xSquared = (x - mTouchDown.x) * (x - mTouchDown.x);
- float ySquared = (y - mTouchDown.y) * (y - mTouchDown.y);
- if (xSquared + ySquared > mTouchSlopSquared) {
+ if (squaredHypot(x - mTouchDown.x, y - mTouchDown.y) > mTouchSlopSquared) {
// For now, just start the home intent so user is prompted to unlock the device.
mContext.startActivity(new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
index 2e8880d..6e7cb8f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
@@ -63,4 +63,23 @@
onKeyEvent((KeyEvent) ev);
}
}
+
+ default String getName() {
+ switch (getType()) {
+ case TYPE_OVERVIEW:
+ return "OVERVIEW";
+ case TYPE_OTHER_ACTIVITY:
+ return "OTHER_ACTIVITY";
+ case TYPE_ASSISTANT:
+ return "ASSISTANT";
+ case TYPE_DEVICE_LOCKED:
+ return "DEVICE_LOCKED";
+ case TYPE_ACCESSIBILITY:
+ return "ACCESSIBILITY";
+ case TYPE_SCREEN_PINNED:
+ return "SCREEN_PINNED";
+ default:
+ return "NO_OP";
+ }
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 35b96cc..b0acffa 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -18,10 +18,12 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
+import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSCAPE;
import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
@@ -36,6 +38,7 @@
import android.content.ContextWrapper;
import android.content.Intent;
import android.graphics.PointF;
+import android.graphics.RectF;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -90,6 +93,7 @@
private final SwipeSharedState mSwipeSharedState;
private final InputMonitorCompat mInputMonitorCompat;
private final SysUINavigationMode.Mode mMode;
+ private final RectF mSwipeTouchRegion;
private final int mDisplayRotation;
@@ -106,7 +110,7 @@
private int mActivePointerId = INVALID_POINTER_ID;
private final float mDragSlop;
- private final float mTouchSlop;
+ private final float mSquaredTouchSlop;
// Slop used to check when we start moving window.
private boolean mPassedDragSlop;
@@ -127,7 +131,8 @@
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
InputConsumerController inputConsumer,
Consumer<OtherActivityInputConsumer> onCompleteCallback,
- SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat) {
+ SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
+ RectF swipeTouchRegion) {
super(base);
mMainThreadHandler = new Handler(Looper.getMainLooper());
@@ -135,6 +140,7 @@
mRecentsModel = recentsModel;
mHomeIntent = homeIntent;
mMode = SysUINavigationMode.getMode(base);
+ mSwipeTouchRegion = swipeTouchRegion;
mMotionPauseDetector = new MotionPauseDetector(base);
mMotionPauseMinDisplacement = base.getResources().getDimension(
@@ -152,7 +158,8 @@
mDisplayRotation = getSystemService(WindowManager.class).getDefaultDisplay().getRotation();
mDragSlop = QuickStepContract.getQuickStepDragSlopPx();
- mTouchSlop = QuickStepContract.getQuickStepTouchSlopPx();
+ float slop = QuickStepContract.getQuickStepTouchSlopPx();
+ mSquaredTouchSlop = slop * slop;
mPassedTouchSlop = mPassedDragSlop = continuingPreviousGesture;
}
@@ -204,6 +211,19 @@
RaceConditionTracker.onEvent(DOWN_EVT, EXIT);
break;
}
+ case ACTION_POINTER_DOWN: {
+ if (!mPassedTouchSlop) {
+ // Cancel interaction in case of multi-touch interaction
+ int ptrIdx = ev.getActionIndex();
+ if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) {
+ int action = ev.getAction();
+ ev.setAction(ACTION_CANCEL);
+ finishTouchTracking(ev);
+ ev.setAction(action);
+ }
+ }
+ break;
+ }
case ACTION_POINTER_UP: {
int ptrIdx = ev.getActionIndex();
int ptrId = ev.getPointerId(ptrIdx);
@@ -238,7 +258,7 @@
}
if (!mPassedTouchSlop) {
- if (Math.hypot(displacementX, mLastPos.y - mDownPos.y) >= mTouchSlop) {
+ if (squaredHypot(displacementX, mLastPos.y - mDownPos.y) >= mSquaredTouchSlop) {
mPassedTouchSlop = true;
if (mIsDeferredDownTarget) {
@@ -273,13 +293,8 @@
break;
}
case ACTION_CANCEL:
- // TODO: Should be different than ACTION_UP
case ACTION_UP: {
- RaceConditionTracker.onEvent(UP_EVT, ENTER);
- TraceHelper.endSection("TouchInt");
-
finishTouchTracking(ev);
- RaceConditionTracker.onEvent(UP_EVT, EXIT);
break;
}
}
@@ -342,6 +357,9 @@
* the animation can still be running.
*/
private void finishTouchTracking(MotionEvent ev) {
+ RaceConditionTracker.onEvent(UP_EVT, ENTER);
+ TraceHelper.endSection("TouchInt");
+
if (mPassedDragSlop && mInteractionHandler != null) {
if (ev.getActionMasked() == ACTION_CANCEL) {
mInteractionHandler.onGestureCancelled();
@@ -374,6 +392,7 @@
mVelocityTracker.recycle();
mVelocityTracker = null;
mMotionPauseDetector.clear();
+ RaceConditionTracker.onEvent(UP_EVT, EXIT);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
index a650113..c164a24 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -285,13 +285,20 @@
/**
* Compute scale and translation y such that the specified task view fills the screen.
*/
- public LauncherState.ScaleAndTranslation getOverviewFullscreenScaleAndTranslation(TaskView v) {
+ public ClipAnimationHelper updateForFullscreenOverview(TaskView v) {
TaskThumbnailView thumbnailView = v.getThumbnail();
RecentsView recentsView = v.getRecentsView();
fromTaskThumbnailView(thumbnailView, recentsView);
Rect taskSize = new Rect();
recentsView.getTaskSize(taskSize);
updateTargetRect(taskSize);
+ return this;
+ }
+
+ /**
+ * @return The source rect's scale and translation relative to the target rect.
+ */
+ public LauncherState.ScaleAndTranslation getScaleAndTranslation() {
float scale = mSourceRect.width() / mTargetRect.width();
float translationY = mSourceRect.centerY() - mSourceRect.top - mTargetRect.centerY();
return new LauncherState.ScaleAndTranslation(scale, 0, translationY);
@@ -332,35 +339,10 @@
mSourceStackBounds.offset(left, insets.top + fullDp.availableHeightPx - taskHeight);
}
- public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) {
- RectF currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
- canvas.translate(mSourceStackBounds.left - mHomeStackBounds.left,
- mSourceStackBounds.top - mHomeStackBounds.top);
- mTmpMatrix.setRectToRect(mTargetRect, currentRect, ScaleToFit.FILL);
-
- canvas.concat(mTmpMatrix);
- canvas.translate(mTargetRect.left, mTargetRect.top);
-
- float scale = mTargetRect.width() / mSourceRect.width();
- float insetProgress = (1 - progress);
- float windowCornerRadius = mUseRoundedCornersOnWindows
- ? mWindowCornerRadius : 0;
- ttv.drawOnCanvas(canvas,
- -mSourceWindowClipInsets.left * insetProgress,
- -mSourceWindowClipInsets.top * insetProgress,
- ttv.getMeasuredWidth() + mSourceWindowClipInsets.right * insetProgress,
- ttv.getMeasuredHeight() + mSourceWindowClipInsets.bottom * insetProgress,
- Utilities.mapRange(progress, windowCornerRadius * scale, ttv.getCornerRadius()));
- }
-
public RectF getTargetRect() {
return mTargetRect;
}
- public RectF getSourceRect() {
- return mSourceRect;
- }
-
public float getCurrentCornerRadius() {
return mCurrentCornerRadius;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewDrawable.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewDrawable.java
deleted file mode 100644
index bb41e5d..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewDrawable.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-import android.util.FloatProperty;
-import android.view.View;
-
-import com.android.launcher3.BaseActivity;
-import com.android.launcher3.Utilities;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskThumbnailView;
-import com.android.quickstep.views.TaskView;
-
-public class TaskViewDrawable extends Drawable {
-
- public static final FloatProperty<TaskViewDrawable> PROGRESS =
- new FloatProperty<TaskViewDrawable>("progress") {
- @Override
- public void setValue(TaskViewDrawable taskViewDrawable, float v) {
- taskViewDrawable.setProgress(v);
- }
-
- @Override
- public Float get(TaskViewDrawable taskViewDrawable) {
- return taskViewDrawable.mProgress;
- }
- };
-
- /**
- * The progress at which we play the atomic icon scale animation.
- */
- private static final float ICON_SCALE_THRESHOLD = 0.95f;
-
- private final RecentsView mParent;
- private final View mIconView;
- private final float[] mIconPos;
- private final TaskView mTaskView;
-
- private final TaskThumbnailView mThumbnailView;
-
- private final ClipAnimationHelper mClipAnimationHelper;
-
- private float mProgress = 1;
- private boolean mPassedIconScaleThreshold;
- private ValueAnimator mIconScaleAnimator;
- private float mIconScale;
-
- public TaskViewDrawable(TaskView tv, RecentsView parent) {
- mParent = parent;
- mTaskView = tv;
- mIconView = tv.getIconView();
- mIconPos = new float[2];
- mIconScale = mIconView.getScaleX();
- Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);
-
- mThumbnailView = tv.getThumbnail();
- mClipAnimationHelper = new ClipAnimationHelper(parent.getContext());
- mClipAnimationHelper.fromTaskThumbnailView(mThumbnailView, parent);
- mClipAnimationHelper.prepareAnimation(
- BaseActivity.fromContext(tv.getContext()).getDeviceProfile(), true /* isOpening */);
- }
-
- public void setProgress(float progress) {
- mProgress = progress;
- mParent.invalidate();
- boolean passedIconScaleThreshold = progress <= ICON_SCALE_THRESHOLD;
- if (mPassedIconScaleThreshold != passedIconScaleThreshold) {
- mPassedIconScaleThreshold = passedIconScaleThreshold;
- animateIconScale(mPassedIconScaleThreshold ? 0 : 1);
- }
- }
-
- private void animateIconScale(float toScale) {
- if (mIconScaleAnimator != null) {
- mIconScaleAnimator.cancel();
- }
- mIconScaleAnimator = ValueAnimator.ofFloat(mIconScale, toScale);
- mIconScaleAnimator.addUpdateListener(valueAnimator -> {
- mIconScale = (float) valueAnimator.getAnimatedValue();
- if (mProgress > ICON_SCALE_THRESHOLD) {
- // Speed up the icon scale to ensure it is 1 when progress is 1.
- float iconProgress = (mProgress - ICON_SCALE_THRESHOLD) / (1 - ICON_SCALE_THRESHOLD);
- if (iconProgress > mIconScale) {
- mIconScale = iconProgress;
- }
- }
- invalidateSelf();
- });
- mIconScaleAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mIconScaleAnimator = null;
- }
- });
- mIconScaleAnimator.setDuration(TaskView.SCALE_ICON_DURATION);
- mIconScaleAnimator.start();
- }
-
- @Override
- public void draw(Canvas canvas) {
- canvas.save();
- canvas.translate(mParent.getScrollX(), mParent.getScrollY());
- mClipAnimationHelper.drawForProgress(mThumbnailView, canvas, mProgress);
- canvas.restore();
-
- canvas.save();
- canvas.translate(mIconPos[0], mIconPos[1]);
- canvas.scale(mIconScale, mIconScale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
- mIconView.draw(canvas);
- canvas.restore();
- }
-
- public ClipAnimationHelper getClipAnimationHelper() {
- return mClipAnimationHelper;
- }
-
- @Override
- public void setAlpha(int i) { }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) { }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- public TaskView getTaskView() {
- return mTaskView;
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index bdac750..deedd21 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -30,6 +30,7 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
@@ -179,6 +180,21 @@
}
@Override
+ protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (mRecentsAnimationWrapper.targetSet != null && tv.isRunningTask()) {
+ mTransformParams.setProgress(1 - progress)
+ .setSyncTransactionApplier(mSyncTransactionApplier)
+ .setForLiveTile(true);
+ mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
+ mTransformParams);
+ } else {
+ redrawLiveTile(true);
+ }
+ }
+ }
+
+ @Override
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
boolean shouldRemoveTask, long duration) {
PendingAnimation anim = super.createTaskDismissAnimation(taskView, animateTaskView,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index bded5ba..661468a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -18,7 +18,10 @@
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
+import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
@@ -30,7 +33,6 @@
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-import static com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -77,6 +79,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils.ViewProgressProperty;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -99,7 +102,6 @@
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.ClipAnimationHelper;
-import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -142,6 +144,19 @@
}
};
+ public static final FloatProperty<RecentsView> FULLSCREEN_PROGRESS =
+ new FloatProperty<RecentsView>("fullscreenProgress") {
+ @Override
+ public void setValue(RecentsView recentsView, float v) {
+ recentsView.setFullscreenProgress(v);
+ }
+
+ @Override
+ public Float get(RecentsView recentsView) {
+ return recentsView.mFullscreenProgress;
+ }
+ };
+
protected RecentsAnimationWrapper mRecentsAnimationWrapper;
protected ClipAnimationHelper mClipAnimationHelper;
protected SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
@@ -165,6 +180,7 @@
private final ClearAllButton mClearAllButton;
private final Rect mClearAllButtonDeadZoneRect = new Rect();
private final Rect mTaskViewDeadZoneRect = new Rect();
+ protected final ClipAnimationHelper mTempClipAnimationHelper;
private final ScrollState mScrollState = new ScrollState();
// Keeps track of the previously known visible tasks for purposes of loading/unloading task data
@@ -267,7 +283,7 @@
private boolean mHandleTaskStackChanges;
private boolean mSwipeDownShouldLaunchApp;
private boolean mTouchDownToStartHome;
- private final int mTouchSlop;
+ private final float mSquaredTouchSlop;
private int mDownX;
private int mDownY;
@@ -276,6 +292,8 @@
@ViewDebug.ExportedProperty(category = "launcher")
private float mContentAlpha = 1;
+ @ViewDebug.ExportedProperty(category = "launcher")
+ private float mFullscreenProgress = 0;
// Keeps track of task id whose visual state should not be reset
private int mIgnoreResetTaskId = -1;
@@ -310,6 +328,7 @@
mActivity = (T) BaseActivity.fromContext(context);
mModel = RecentsModel.INSTANCE.get(context);
mIdp = InvariantDeviceProfile.INSTANCE.get(context);
+ mTempClipAnimationHelper = new ClipAnimationHelper(context);
mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
.inflate(R.layout.overview_clear_all_button, this, false);
@@ -322,7 +341,7 @@
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mTaskTopMargin = getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mSquaredTouchSlop = squaredTouchSlop(context);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
mEmptyIcon.setCallback(this);
@@ -479,7 +498,8 @@
case MotionEvent.ACTION_MOVE:
// Passing the touch slop will not allow dismiss to home
if (mTouchDownToStartHome &&
- (isHandlingTouch() || Math.hypot(mDownX - x, mDownY - y) > mTouchSlop)) {
+ (isHandlingTouch() ||
+ squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop)) {
mTouchDownToStartHome = false;
}
break;
@@ -598,6 +618,14 @@
loadVisibleTaskData();
}
+ public void setFullscreenProgress(float fullscreenProgress) {
+ mFullscreenProgress = fullscreenProgress;
+ int taskCount = getTaskViewCount();
+ for (int i = 0; i < taskCount; i++) {
+ getTaskViewAt(i).setFullscreenProgress(mFullscreenProgress);
+ }
+ }
+
private void updateTaskStackListenerState() {
boolean handleTaskStackChanges = mOverviewStateEnabled && isAttachedToWindow()
&& getWindowVisibility() == VISIBLE;
@@ -1286,15 +1314,6 @@
setVisibility(alpha > 0 ? VISIBLE : GONE);
}
- private float[] getAdjacentScaleAndTranslation(TaskView currTask,
- float currTaskToScale, float currTaskToTranslationY) {
- float displacement = currTask.getWidth() * (currTaskToScale - currTask.getCurveScale());
- sTempFloatArray[0] = currTaskToScale;
- sTempFloatArray[1] = mIsRtl ? -displacement : displacement;
- sTempFloatArray[2] = currTaskToTranslationY;
- return sTempFloatArray;
- }
-
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
@@ -1423,27 +1442,15 @@
int centerTaskIndex = getCurrentPage();
boolean launchingCenterTask = taskIndex == centerTaskIndex;
- float toScale = clipAnimationHelper.getSourceRect().width()
- / clipAnimationHelper.getTargetRect().width();
- float toTranslationY = clipAnimationHelper.getSourceRect().centerY()
- - clipAnimationHelper.getTargetRect().centerY();
+ LauncherState.ScaleAndTranslation toScaleAndTranslation = clipAnimationHelper
+ .getScaleAndTranslation();
+ float toScale = toScaleAndTranslation.scale;
+ float toTranslationY = toScaleAndTranslation.translationY;
if (launchingCenterTask) {
- TaskView centerTask = getTaskViewAt(centerTaskIndex);
- if (taskIndex - 1 >= 0) {
- TaskView adjacentTask = getTaskViewAt(taskIndex - 1);
- float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask,
- toScale, toTranslationY);
- scaleAndTranslation[1] = -scaleAndTranslation[1];
- anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
- anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1));
- }
- if (taskIndex + 1 < getTaskViewCount()) {
- TaskView adjacentTask = getTaskViewAt(taskIndex + 1);
- float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask,
- toScale, toTranslationY);
- anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
- anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1));
- }
+ RecentsView recentsView = tv.getRecentsView();
+ anim.play(ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY, toScale));
+ anim.play(ObjectAnimator.ofFloat(recentsView, TRANSLATION_Y, toTranslationY));
+ anim.play(ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS, 1));
} else {
// We are launching an adjacent task, so parallax the center and other adjacent task.
float displacementX = tv.getWidth() * (toScale - tv.getCurveScale());
@@ -1461,16 +1468,6 @@
return anim;
}
- private Animator createAnimForChild(TaskView child, float[] toScaleAndTranslation) {
- AnimatorSet anim = new AnimatorSet();
- anim.play(ObjectAnimator.ofFloat(child, TaskView.ZOOM_SCALE, toScaleAndTranslation[0]));
- anim.play(new PropertyListBuilder()
- .translationX(toScaleAndTranslation[1])
- .translationY(toScaleAndTranslation[2])
- .build(child));
- return anim;
- }
-
public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {
if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
@@ -1481,60 +1478,38 @@
return new PendingAnimation(new AnimatorSet());
}
- tv.setVisibility(INVISIBLE);
int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
- TaskViewDrawable drawable = new TaskViewDrawable(tv, this);
- getOverlay().add(drawable);
-
final boolean[] passedOverviewThreshold = new boolean[] {false};
- ObjectAnimator drawableAnim =
- ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0);
- drawableAnim.setInterpolator(LINEAR);
- drawableAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- TransformParams mParams = new TransformParams();
+ ValueAnimator progressAnim = ValueAnimator.ofFloat(0, 1);
+ progressAnim.setInterpolator(LINEAR);
+ progressAnim.addUpdateListener(animator -> {
+ // Once we pass a certain threshold, update the sysui flags to match the target
+ // tasks' flags
+ mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW,
+ animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD
+ ? targetSysUiFlags
+ : 0);
- @Override
- public void onAnimationUpdate(ValueAnimator animator) {
- // Once we pass a certain threshold, update the sysui flags to match the target
- // tasks' flags
- mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW,
- animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD
- ? targetSysUiFlags
- : 0);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- if (mRecentsAnimationWrapper.targetSet != null
- && drawable.getTaskView().isRunningTask()) {
- mParams.setProgress(1 - animator.getAnimatedFraction())
- .setSyncTransactionApplier(mSyncTransactionApplier)
- .setForLiveTile(true);
- drawable.getClipAnimationHelper().applyTransform(
- mRecentsAnimationWrapper.targetSet, mParams);
- } else {
- redrawLiveTile(true);
- }
- }
+ onTaskLaunchAnimationUpdate(animator.getAnimatedFraction(), tv);
- // Passing the threshold from taskview to fullscreen app will vibrate
- final boolean passed = animator.getAnimatedFraction() >=
- SUCCESS_TRANSITION_PROGRESS;
- if (passed != passedOverviewThreshold[0]) {
- passedOverviewThreshold[0] = passed;
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- }
+ // Passing the threshold from taskview to fullscreen app will vibrate
+ final boolean passed = animator.getAnimatedFraction() >=
+ SUCCESS_TRANSITION_PROGRESS;
+ if (passed != passedOverviewThreshold[0]) {
+ passedOverviewThreshold[0] = passed;
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
});
- AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv,
- drawable.getClipAnimationHelper());
- anim.play(drawableAnim);
+ ClipAnimationHelper clipAnimationHelper = new ClipAnimationHelper(mActivity);
+ clipAnimationHelper.fromTaskThumbnailView(tv.getThumbnail(), this);
+ clipAnimationHelper.prepareAnimation(mActivity.getDeviceProfile(), true /* isOpening */);
+ AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv, clipAnimationHelper);
+ anim.play(progressAnim);
anim.setDuration(duration);
- Consumer<Boolean> onTaskLaunchFinish = (result) -> {
- onTaskLaunched(result);
- tv.setVisibility(VISIBLE);
- getOverlay().remove(drawable);
- };
+ Consumer<Boolean> onTaskLaunchFinish = this::onTaskLaunched;
mPendingAnimation = new PendingAnimation(anim);
mPendingAnimation.addEndListener((onEndListener) -> {
@@ -1560,6 +1535,9 @@
return mPendingAnimation;
}
+ protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
+ }
+
public abstract boolean shouldUseMultiWindowTaskSizeStrategy();
protected void onTaskLaunched(boolean success) {
@@ -1714,4 +1692,8 @@
true /* hideOriginal */, iconLocation, false /* isOpening */, mFloatingIconView);
return mFloatingIconView;
}
+
+ public ClipAnimationHelper getTempClipAnimationHelper() {
+ return mTempClipAnimationHelper;
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index a9184ec..df5831b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -75,8 +75,6 @@
}
};
- private final float mCornerRadius;
-
private final BaseActivity mActivity;
private final TaskOverlay mOverlay;
private final boolean mIsDarkTextTheme;
@@ -110,7 +108,6 @@
public TaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mCornerRadius = TaskCornerRadius.get(context);
mOverlay = TaskOverlayFactory.INSTANCE.get(context).createOverlay(this);
mPaint.setFilterBitmap(true);
mBackgroundPaint.setColor(Color.WHITE);
@@ -118,7 +115,7 @@
mDimmingPaintAfterClearing.setColor(Color.BLACK);
mActivity = BaseActivity.fromContext(context);
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
- mFullscreenParams = new TaskView.FullscreenDrawParams(mCornerRadius);
+ mFullscreenParams = new TaskView.FullscreenDrawParams(TaskCornerRadius.get(context));
}
public void bind(Task task) {
@@ -225,10 +222,6 @@
invalidate();
}
- public float getCornerRadius() {
- return mCornerRadius;
- }
-
public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
float cornerRadius) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index c67058d..053b738 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -103,19 +103,6 @@
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
- public static final Property<TaskView, Float> ZOOM_SCALE =
- new FloatProperty<TaskView>("zoomScale") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setZoomScale(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mZoomScale;
- }
- };
-
public static final FloatProperty<TaskView> FULLSCREEN_PROGRESS =
new FloatProperty<TaskView>("fullscreenProgress") {
@Override
@@ -165,7 +152,6 @@
private IconView mIconView;
private DigitalWellBeingToast mDigitalWellBeingToast;
private float mCurveScale;
- private float mZoomScale;
private float mFullscreenProgress;
private final FullscreenDrawParams mCurrentFullscreenParams;
private final float mCornerRadius;
@@ -459,7 +445,6 @@
private void resetViewTransforms() {
setCurveScale(1);
- setZoomScale(1);
setTranslationX(0f);
setTranslationY(0f);
setTranslationZ(0);
@@ -527,13 +512,8 @@
return mCurveScale;
}
- public void setZoomScale(float adjacentScale) {
- mZoomScale = adjacentScale;
- onScaleChanged();
- }
-
private void onScaleChanged() {
- float scale = mCurveScale * mZoomScale;
+ float scale = mCurveScale;
setScaleX(scale);
setScaleY(scale);
}
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index ecf1b0a..ba4ea8b 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -36,6 +36,7 @@
android:importantForAccessibility="no" />
<LinearLayout
+ android:id="@+id/task_footer_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
@@ -43,7 +44,7 @@
<FrameLayout
android:id="@+id/proactive_suggest_container"
android:layout_width="match_parent"
- android:layout_height="36dp"
+ android:layout_height="48dp"
android:gravity="center"
android:visibility="gone"
/>
diff --git a/quickstep/src/com/android/quickstep/TestInformationProvider.java b/quickstep/src/com/android/quickstep/TestInformationProvider.java
index b37ddda..d96f9af 100644
--- a/quickstep/src/com/android/quickstep/TestInformationProvider.java
+++ b/quickstep/src/com/android/quickstep/TestInformationProvider.java
@@ -111,6 +111,14 @@
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) distance);
break;
}
+
+ case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
+ TestProtocol.sDebugTracing = true;
+ break;
+
+ case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
+ TestProtocol.sDebugTracing = false;
+ break;
}
return response;
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 4b6b3ee..43d6311 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -44,17 +44,12 @@
import org.junit.Before;
import org.junit.Ignore;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.TestWatcher;
import org.junit.runner.RunWith;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class TaplTestsQuickstep extends AbstractQuickStepTest {
- @Rule
- public TestWatcher mFailureWatcher = new TaplTestsLauncher3.FailureWatcher(mDevice);
-
@Before
public void setUp() throws Exception {
super.setUp();
diff --git a/res/values-v29/styles.xml b/res/values-v29/styles.xml
index f623823..7590594 100644
--- a/res/values-v29/styles.xml
+++ b/res/values-v29/styles.xml
@@ -28,5 +28,7 @@
<item name="android:windowShowWallpaper">true</item>
<item name="folderTextColor">?attr/workspaceTextColor</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
+ <item name="android:enforceStatusBarContrast">false</item>
+ <item name="android:enforceNavigationBarContrast">false</item>
</style>
</resources>
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 7e72208..3455cb8 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -44,6 +44,12 @@
android:defaultValue="@bool/allow_rotation"
android:persistent="true" />
+ <SwitchPreference
+ android:key="pref_grid_options"
+ android:title="Enable grid options"
+ android:defaultValue="false"
+ android:persistent="true" />
+
<androidx.preference.PreferenceScreen
android:key="pref_developer_options"
android:persistent="false"
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index ccd9e25..bd6ac90 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -134,6 +134,10 @@
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
@Nullable String sourceContainer) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "startActivitySafely 1");
+ }
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
return false;
@@ -157,6 +161,10 @@
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "startActivitySafely 2");
+ }
startActivity(intent, optsBundle);
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
Process.myUserHandle(), sourceContainer);
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index bff7f42..2f801e0 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -51,7 +51,6 @@
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconCache.IconLoadRequest;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
-import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.views.ActivityContext;
@@ -561,7 +560,10 @@
}
}
if (itemInfo.contentDescription != null) {
- if (hasDot()) {
+ if (itemInfo.isDisabled()) {
+ setContentDescription(getContext().getString(R.string.disabled_app_label,
+ itemInfo.contentDescription));
+ } else if (hasDot()) {
int count = mDotInfo.getNotificationCount();
setContentDescription(getContext().getResources().getQuantityString(
R.plurals.dotted_app_label, count, itemInfo.contentDescription, count));
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index d098b8c..c1f898c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -210,9 +210,8 @@
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
hotseatBarSidePaddingEndPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
- // Add a bit of space between nav bar and hotseat in multi-window vertical bar layout.
- hotseatBarSidePaddingStartPx = isMultiWindowMode && isVerticalBarLayout()
- ? edgeMarginPx : 0;
+ // Add a bit of space between nav bar and hotseat in vertical bar layout.
+ hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? verticalDragHandleSizePx : 0;
hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout()
? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
: (res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 40eb912..a59189b 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1782,6 +1782,10 @@
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
@Nullable String sourceContainer) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "startActivitySafely outer");
+ }
boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
if (success && v instanceof BubbleTextView) {
// This is set to the view that launched the activity that navigated the user away
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 51079b0..eff58a7 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -18,7 +18,6 @@
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
-
import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -203,6 +202,10 @@
return UiFactory.getOverviewScaleAndTranslationForNormalState(launcher);
}
+ public float getOverviewFullscreenProgress() {
+ return 0;
+ }
+
public void onStateEnabled(Launcher launcher) {
dispatchWindowStateChanged(launcher);
}
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index b1a3fc9..49ae338 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -447,6 +447,10 @@
}
private void onStateTransitionStart(LauncherState state) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "onStateTransitionStart");
+ }
if (mState != state) {
mState.onStateDisabled(mLauncher);
}
@@ -572,6 +576,10 @@
private final AnimatorSet mAnim;
public StartAnimRunnable(AnimatorSet anim) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "StartAnimRunnable");
+ }
mAnim = anim;
}
diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java
index 8df3290..0c80d13 100644
--- a/src/com/android/launcher3/ResourceUtils.java
+++ b/src/com/android/launcher3/ResourceUtils.java
@@ -21,8 +21,10 @@
import android.util.TypedValue;
public class ResourceUtils {
- public static final String NAVBAR_VERTICAL_SIZE = "navigation_bar_frame_height";
- public static final String NAVBAR_HORIZONTAL_SIZE = "navigation_bar_width";
+ public static final String NAVBAR_PORTRAIT_BOTTOM_SIZE = "navigation_bar_frame_height";
+ public static final String NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE = "navigation_bar_width";
+ public static final String NAVBAR_LANDSCAPE_BOTTOM_SIZE
+ = "navigation_bar_frame_height_landscape";
public static int getNavbarSize(String resName, Resources res) {
return getDimenByName(resName, res, 48);
diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/TestProtocol.java
index eefecda..a0440e8 100644
--- a/src/com/android/launcher3/TestProtocol.java
+++ b/src/com/android/launcher3/TestProtocol.java
@@ -64,4 +64,9 @@
"all-apps-to-overview-swipe-height";
public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT =
"home-to-all-apps-swipe-height";
+ public static boolean sDebugTracing = false;
+ public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing";
+ public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing";
+ public static final String NO_DRAG_TAG = "b/133009122";
+ public static final String NO_START_TAG = "b/132900132";
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 732aa95..cc9bda7 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -50,6 +50,7 @@
import android.os.Message;
import android.os.PowerManager;
import android.os.TransactionTooLargeException;
+import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
@@ -60,6 +61,7 @@
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.animation.Interpolator;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -71,6 +73,7 @@
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.views.Transposable;
import com.android.launcher3.widget.PendingAddShortcutInfo;
@@ -105,9 +108,7 @@
private static final Matrix sMatrix = new Matrix();
private static final Matrix sInverseMatrix = new Matrix();
- public static final boolean ATLEAST_Q = Build.VERSION.CODENAME.length() == 1
- && Build.VERSION.CODENAME.charAt(0) >= 'Q'
- && Build.VERSION.CODENAME.charAt(0) <= 'Z';
+ public static final boolean ATLEAST_Q = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
public static final boolean ATLEAST_P =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
@@ -133,6 +134,11 @@
Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") ||
Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
+ public static boolean isDevelopersOptionsEnabled(Context context) {
+ return Settings.Global.getInt(context.getApplicationContext().getContentResolver(),
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
+ }
+
// An intent extra to indicate the horizontal scroll of the wallpaper.
public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET";
public static final String EXTRA_WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR";
@@ -160,6 +166,12 @@
return Log.isLoggable(propertyName, Log.VERBOSE);
}
+ public static boolean existsStyleWallpapers(Context context) {
+ ResolveInfo ri = context.getPackageManager().resolveActivity(
+ PackageManagerHelper.getStyleWallpapersIntent(context), 0);
+ return ri != null;
+ }
+
/**
* Given a coordinate relative to the descendant, find the coordinate in a parent view's
* coordinates.
@@ -715,6 +727,15 @@
return str.toString();
}
+ public static float squaredHypot(float x, float y) {
+ return x * x + y * y;
+ }
+
+ public static float squaredTouchSlop(Context context) {
+ float slop = ViewConfiguration.get(context).getScaledTouchSlop();
+ return slop * slop;
+ }
+
private static class FixedSizeEmptyDrawable extends ColorDrawable {
private final int mSize;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index a508ce5..d19f9cd 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -371,6 +371,10 @@
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "onDragStart 1");
+ }
if (ENFORCE_DRAG_EVENT_ORDER) {
enforceDragParity("onDragStart", 0, 0);
}
@@ -421,6 +425,10 @@
}
// Always enter the spring loaded mode
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "onDragStart 2");
+ }
mLauncher.getStateManager().goToState(SPRING_LOADED);
}
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index bad8282..7e20d11 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -58,9 +58,7 @@
}
public static boolean showFlagTogglerUi(Context context) {
- return Utilities.IS_DEBUG_DEVICE &&
- Settings.Global.getInt(context.getApplicationContext().getContentResolver(),
- Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
+ return Utilities.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
}
public static final boolean IS_DOGFOOD_BUILD = false;
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index f92e00a..bf692fe 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -472,6 +472,10 @@
}
private void handleMoveEvent(int x, int y) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "handleMoveEvent 1");
+ }
mDragObject.dragView.move(x, y);
// Drop on someone?
@@ -488,6 +492,10 @@
if (mIsInPreDrag && mOptions.preDragCondition != null
&& mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "handleMoveEvent 2");
+ }
callOnDragStart();
}
}
@@ -525,6 +533,10 @@
* Call this from a drag source view.
*/
public boolean onControllerTouchEvent(MotionEvent ev) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "onControllerTouchEvent");
+ }
if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
return false;
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 389e852..2ef6d70 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -593,6 +593,10 @@
protected void handleClose(boolean animate) {
mIsOpen = false;
+ if (!animate && mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
+ mCurrentAnimator.cancel();
+ }
+
if (isEditingName()) {
mFolderName.dispatchBackKey();
}
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 9373976..962f215 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -35,6 +35,8 @@
import android.view.View;
import android.view.animation.AnimationUtils;
+import androidx.core.graphics.ColorUtils;
+
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.Launcher;
@@ -152,7 +154,8 @@
final float yDistance = initialY - lp.y;
// Set up the Folder background.
- final int finalColor = Themes.getAttrColor(mContext, R.attr.folderFillColor);
+ final int finalColor = ColorUtils.setAlphaComponent(
+ Themes.getAttrColor(mContext, R.attr.folderFillColor), 255);
final int initialColor = setColorAlphaBound(
finalColor, mPreviewBackground.getBackgroundAlpha());
mFolderBackground.mutate();
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 8d9c520..0a9bc72 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -203,6 +203,10 @@
mBackground.getBounds(outBounds);
}
+ public float getBackgroundStrokeWidth() {
+ return mBackground.getStrokeWidth();
+ }
+
public Folder getFolder() {
return mFolder;
}
diff --git a/src/com/android/launcher3/logging/EventLogArray.java b/src/com/android/launcher3/logging/EventLogArray.java
index bfb3792..f20f365 100644
--- a/src/com/android/launcher3/logging/EventLogArray.java
+++ b/src/com/android/launcher3/logging/EventLogArray.java
@@ -18,6 +18,7 @@
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
@@ -76,8 +77,12 @@
nextIndex = (nextIndex + 1) % logs.length;
}
+ public void clear() {
+ Arrays.setAll(logs, (i) -> null);
+ }
+
public void dump(String prefix, PrintWriter writer) {
- writer.println(prefix + name + " event history:");
+ writer.println(prefix + "EventLog (" + name + ") history:");
SimpleDateFormat sdf = new SimpleDateFormat(" HH:mm:ss.SSSZ ", Locale.US);
Date date = new Date();
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 047f486..7b14fa2 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -16,6 +16,8 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.launcher3.notification.NotificationMainView.NOTIFICATION_ITEM_INFO;
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS;
@@ -37,7 +39,6 @@
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.ImageView;
@@ -51,6 +52,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
import com.android.launcher3.dot.DotInfo;
@@ -136,8 +138,8 @@
return true;
}
// Stop sending touch events to deep shortcut views if user moved beyond touch slop.
- return Math.hypot(mInterceptTouchDown.x - ev.getX(), mInterceptTouchDown.y - ev.getY())
- > ViewConfiguration.get(getContext()).getScaledTouchSlop();
+ return squaredHypot(mInterceptTouchDown.x - ev.getX(), mInterceptTouchDown.y - ev.getY())
+ > squaredTouchSlop(getContext());
}
@Override
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 6e7188f..18b6094 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -24,6 +24,10 @@
import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -32,6 +36,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.GridOptionsProvider;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SecureSettingsObserver;
@@ -47,7 +52,8 @@
* Settings activity for Launcher. Currently implements the following setting: Allow rotation
*/
public class SettingsActivity extends Activity
- implements OnPreferenceStartFragmentCallback, OnPreferenceStartScreenCallback {
+ implements OnPreferenceStartFragmentCallback, OnPreferenceStartScreenCallback,
+ SharedPreferences.OnSharedPreferenceChangeListener{
private static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
private static final String FLAGS_PREFERENCE_KEY = "flag_toggler";
@@ -61,6 +67,8 @@
private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;
public static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";
+ public static final String GRID_OPTIONS_PREFERENCE_KEY = "pref_grid_options";
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -79,6 +87,28 @@
.replace(android.R.id.content, f)
.commit();
}
+ Utilities.getPrefs(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);
+ }
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (GRID_OPTIONS_PREFERENCE_KEY.equals(key)) {
+
+ final ComponentName cn = new ComponentName(getApplicationContext(),
+ GridOptionsProvider.class);
+ Context c = getApplicationContext();
+ int oldValue = c.getPackageManager().getComponentEnabledSetting(cn);
+ int newValue;
+ if (Utilities.getPrefs(c).getBoolean(GRID_OPTIONS_PREFERENCE_KEY, false)) {
+ newValue = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ } else {
+ newValue = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+ }
+
+ if (oldValue != newValue) {
+ c.getPackageManager().setComponentEnabledSetting(cn, newValue,
+ PackageManager.DONT_KILL_APP);
+ }
+ }
}
private boolean startFragment(String fragment, Bundle args, String key) {
@@ -200,6 +230,10 @@
// Show if plugins are enabled or flag UI is enabled.
return FeatureFlags.showFlagTogglerUi(getContext()) ||
PluginManagerWrapper.hasPlugins(getContext());
+ case GRID_OPTIONS_PREFERENCE_KEY:
+ return Utilities.isDevelopersOptionsEnabled(getContext()) &&
+ Utilities.IS_DEBUG_DEVICE &&
+ Utilities.existsStyleWallpapers(getContext());
}
return true;
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 0650001..99b9f25 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -66,14 +66,26 @@
}
private static void onClick(View v, String sourceContainer) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "onClick 1");
+ }
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "onClick 2");
+ }
return;
}
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!launcher.getWorkspace().isFinishedSwitchingState()) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "onClick 3");
+ }
return;
}
@@ -85,6 +97,10 @@
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "onClick 4");
+ }
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer);
} else if (tag instanceof LauncherAppWidgetInfo) {
@@ -216,6 +232,10 @@
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
@Nullable String sourceContainer) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_START_TAG,
+ "startAppShortcutOrInfoActivity");
+ }
Intent intent;
if (item instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 7439ac1..7d3a941 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -172,6 +172,11 @@
}
}
+ public static Intent getStyleWallpapersIntent(Context context) {
+ return new Intent(Intent.ACTION_SET_WALLPAPER).setComponent(
+ new ComponentName(context.getString(R.string.wallpaper_picker_package),
+ "com.android.customization.picker.CustomizationPickerActivity"));
+ }
/**
* Starts the details activity for {@code info}
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 3c81bcf..4964182 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -213,6 +213,10 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "onTouchEvent " + ev);
+ }
int action = ev.getAction();
if (action == ACTION_UP || action == ACTION_CANCEL) {
if (mTouchCompleteListener != null) {
@@ -222,6 +226,10 @@
}
if (mActiveController != null) {
+ if (com.android.launcher3.TestProtocol.sDebugTracing) {
+ android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
+ "onTouchEvent 1");
+ }
return mActiveController.onControllerTouchEvent(ev);
} else {
// In case no child view handled the touch event, we may not get onIntercept anymore
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index cb7bba7..3d5877a 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -259,8 +259,6 @@
mFgSpringX.animateToFinalPosition(diffX);
mFgSpringY.animateToFinalPosition(diffY);
}
-
-
}
invalidate();
invalidateOutline();
@@ -368,10 +366,13 @@
drawable = v.getBackground();
}
} else {
+ boolean isFolderIcon = v instanceof FolderIcon;
+ int width = isFolderIcon ? v.getWidth() : lp.width;
+ int height = isFolderIcon ? v.getHeight() : lp.height;
if (supportsAdaptiveIcons) {
- drawable = Utilities.getFullDrawable(mLauncher, info, lp.width, lp.height,
- false, sTmpObjArray);
- if ((drawable instanceof AdaptiveIconDrawable)) {
+ drawable = Utilities.getFullDrawable(mLauncher, info, width, height, false,
+ sTmpObjArray);
+ if (drawable instanceof AdaptiveIconDrawable) {
mBadge = getBadge(mLauncher, info, sTmpObjArray[0]);
} else {
// The drawable we get back is not an adaptive icon, so we need to use the
@@ -383,8 +384,8 @@
// Similar to DragView, we simply use the BubbleTextView icon here.
drawable = btvIcon;
} else {
- drawable = Utilities.getFullDrawable(mLauncher, info, lp.width, lp.height,
- false, sTmpObjArray);
+ drawable = Utilities.getFullDrawable(mLauncher, info, width, height, false,
+ sTmpObjArray);
}
}
}
@@ -412,13 +413,6 @@
}
mForeground = foreground;
- if (mForeground instanceof ShiftedBitmapDrawable && v instanceof FolderIcon) {
- ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground;
- ((FolderIcon) v).getPreviewBounds(sTmpRect);
- sbd.setShiftX(sbd.getShiftX() - sTmpRect.left);
- sbd.setShiftY(sbd.getShiftY() - sTmpRect.top);
- }
-
final int originalHeight = lp.height;
final int originalWidth = lp.width;
@@ -434,14 +428,27 @@
if (mBadge != null) {
mBadge.setBounds(mStartRevealRect);
- if (!isOpening) {
+ if (!isOpening && !isFolderIcon) {
DRAWABLE_ALPHA.set(mBadge, 0);
}
-
}
- if (!isFolderIcon) {
- mStartRevealRect.inset(mBlurSizeOutline, mBlurSizeOutline);
+ if (isFolderIcon) {
+ ((FolderIcon) v).getPreviewBounds(sTmpRect);
+ float bgStroke = ((FolderIcon) v).getBackgroundStrokeWidth();
+ if (mForeground instanceof ShiftedBitmapDrawable) {
+ ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground;
+ sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke);
+ sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke);
+ }
+ if (mBadge instanceof ShiftedBitmapDrawable) {
+ ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mBadge;
+ sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke);
+ sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke);
+ }
+ } else {
+ Utilities.scaleRectAboutCenter(mStartRevealRect,
+ IconShape.getNormalizationScale());
}
float aspectRatio = mLauncher.getDeviceProfile().aspectRatio;
@@ -474,6 +481,7 @@
setClipToOutline(true);
} else {
setBackground(finalDrawable);
+ setClipToOutline(false);
}
if (!loadIconSignal.isCanceled()) {
@@ -664,7 +672,7 @@
}
});
- if (mBadge != null) {
+ if (mBadge != null && !(mOriginalIcon instanceof FolderIcon)) {
ObjectAnimator badgeFade = ObjectAnimator.ofInt(mBadge, DRAWABLE_ALPHA, 255);
badgeFade.addUpdateListener(valueAnimator -> invalidate());
fade.play(badgeFade);
@@ -690,7 +698,6 @@
@Override
public void onAnimationEnd(Animator animation) {
folderIcon.setBackgroundVisible(true);
- folderIcon.animateBgShadowAndStroke();
if (folderIcon.hasDot()) {
folderIcon.animateDotScale(0, 1f);
}
@@ -745,5 +752,6 @@
mFgTransX = 0;
mFgSpringY.cancel();
mBadge = null;
+ sTmpObjArray[0] = null;
}
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 7062369..63f7427 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -152,9 +152,9 @@
RectF target = new RectF(x - halfSize, y - halfSize, x + halfSize, y + halfSize);
ArrayList<OptionItem> options = new ArrayList<>();
- int resString = existsStyleWallpapers(launcher) ?
+ int resString = Utilities.existsStyleWallpapers(launcher) ?
R.string.styles_wallpaper_button_text : R.string.wallpaper_button_text;
- int resDrawable = existsStyleWallpapers(launcher) ?
+ int resDrawable = Utilities.existsStyleWallpapers(launcher) ?
R.drawable.ic_palette : R.drawable.ic_wallpaper;
options.add(new OptionItem(resString, resDrawable,
ControlType.WALLPAPER_BUTTON, OptionsPopupView::startWallpaperPicker));
@@ -168,14 +168,6 @@
show(launcher, target, options);
}
- private static boolean existsStyleWallpapers(Launcher launcher) {
- Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
- intent.setComponent(new ComponentName(launcher.getString(R.string.wallpaper_picker_package),
- "com.android.customization.picker.CustomizationPickerActivity"));
- ResolveInfo ri = launcher.getPackageManager().resolveActivity(intent, 0);
- return ri != null;
- }
-
public static boolean onWidgetsClicked(View view) {
return openWidgets(Launcher.getLauncher(view.getContext()));
}
@@ -212,7 +204,7 @@
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra(EXTRA_WALLPAPER_OFFSET,
launcher.getWorkspace().getWallpaperOffsetForCenterPage());
- if (!existsStyleWallpapers(launcher)) {
+ if (!Utilities.existsStyleWallpapers(launcher)) {
intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "wallpaper_only");
} else {
intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "focus_wallpaper");
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index b6878bb..74cece8 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -64,8 +64,12 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestRule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
import org.junit.runners.model.Statement;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -89,23 +93,22 @@
public static final long DEFAULT_UI_TIMEOUT = 10000;
protected static final int LONG_WAIT_TIME_MS = 60000;
private static final String TAG = "AbstractLauncherUiTest";
+ private static int sScreenshotCount = 0;
protected MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
- protected final UiDevice mDevice;
+ protected final UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
protected final LauncherInstrumentation mLauncher;
protected Context mTargetContext;
protected String mTargetPackage;
protected AbstractLauncherUiTest() {
- final Instrumentation instrumentation = getInstrumentation();
- mDevice = UiDevice.getInstance(instrumentation);
try {
mDevice.setOrientationNatural();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
if (TestHelpers.isInLauncherProcess()) Utilities.enableRunningInTestHarnessForTests();
- mLauncher = new LauncherInstrumentation(instrumentation);
+ mLauncher = new LauncherInstrumentation(getInstrumentation());
}
@Rule
@@ -163,6 +166,36 @@
}
} : base;
+ @Rule
+ public TestWatcher mFailureWatcher = new TestWatcher() {
+ private void dumpViewHierarchy() {
+ final ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ try {
+ mDevice.dumpWindowHierarchy(stream);
+ stream.flush();
+ stream.close();
+ for (String line : stream.toString().split("\\r?\\n")) {
+ Log.e(TAG, line.trim());
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "error dumping XML to logcat", e);
+ }
+ }
+
+ @Override
+ protected void failed(Throwable e, Description description) {
+ if (mDevice == null) return;
+ final String pathname = getInstrumentation().getTargetContext().
+ getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png";
+ Log.e(TAG, "Failed test " + description.getMethodName() +
+ ", screenshot will be saved to " + pathname +
+ ", track trace is below, UI object dump is further below:\n" +
+ Log.getStackTraceString(e));
+ dumpViewHierarchy();
+ mDevice.takeScreenshot(new File(pathname));
+ }
+ };
+
@Before
public void setUp() throws Exception {
mTargetContext = InstrumentationRegistry.getTargetContext();
@@ -210,7 +243,7 @@
*/
protected UiObject2 scrollAndFind(UiObject2 container, BySelector condition) {
final int margin = ResourceUtils.getNavbarSize(
- ResourceUtils.NAVBAR_VERTICAL_SIZE, mLauncher.getResources()) + 1;
+ ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE, mLauncher.getResources()) + 1;
container.setGestureMargins(0, 0, 0, margin);
int i = 0;
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 7578dff..d4cfe3a 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -24,11 +24,8 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import android.util.Log;
-
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.UiDevice;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
@@ -45,62 +42,14 @@
import com.android.launcher3.widget.WidgetsRecyclerView;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
import org.junit.runner.RunWith;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-
@LargeTest
@RunWith(AndroidJUnit4.class)
public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
- private static final String TAG = "TaplTestsAosp";
private static final String APP_NAME = "LauncherTestApp";
- private static int sScreenshotCount = 0;
-
- public static class FailureWatcher extends TestWatcher {
- private UiDevice mDevice;
-
- public FailureWatcher(UiDevice device) {
- this.mDevice = device;
- }
-
- private void dumpViewHierarchy() {
- final ByteArrayOutputStream stream = new ByteArrayOutputStream();
- try {
- mDevice.dumpWindowHierarchy(stream);
- stream.flush();
- stream.close();
- for (String line : stream.toString().split("\\r?\\n")) {
- Log.e(TAG, line.trim());
- }
- } catch (IOException e) {
- Log.e(TAG, "error dumping XML to logcat", e);
- }
- }
-
- @Override
- protected void failed(Throwable e, Description description) {
- if (mDevice == null) return;
- final String pathname = getInstrumentation().getTargetContext().
- getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png";
- Log.e(TAG, "Failed test " + description.getMethodName() +
- ", screenshot will be saved to " + pathname +
- ", track trace is below, UI object dump is further below:\n" +
- Log.getStackTraceString(e));
- dumpViewHierarchy();
- mDevice.takeScreenshot(new File(pathname));
- }
- }
-
- @Rule
- public TestWatcher mFailureWatcher = new FailureWatcher(mDevice);
-
@Before
public void setUp() throws Exception {
super.setUp();
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index b66fa8a..a57d7ba 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -17,26 +17,25 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.graphics.Color;
+import android.view.View;
+
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
-import android.view.View;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.R;
-import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace.ItemOperator;
+import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.testcomponent.AppWidgetNoConfig;
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
@@ -49,7 +48,6 @@
import com.android.launcher3.widget.WidgetCell;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -181,7 +179,9 @@
// Accept confirmation:
BlockingBroadcastReceiver resultReceiver = new BlockingBroadcastReceiver(mCallbackAction);
- mDevice.wait(Until.findObject(By.text("Add automatically")), DEFAULT_UI_TIMEOUT).click();
+ mDevice.wait(Until.findObject(
+ By.text(mLauncher.isAvd() ? "ADD AUTOMATICALLY" : "Add automatically")),
+ DEFAULT_UI_TIMEOUT).click();
Intent result = resultReceiver.blockingGetIntent();
assertNotNull(result);
mAppWidgetId = result.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index a296975..70405fe 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
+import android.graphics.Point;
import android.graphics.Rect;
import androidx.annotation.NonNull;
@@ -48,12 +49,34 @@
return LauncherInstrumentation.ContainerType.ALL_APPS;
}
- private boolean hasClickableIcon(UiObject2 allAppsContainer, BySelector appIconSelector) {
- final UiObject2 icon = allAppsContainer.findObject(appIconSelector);
- if (icon == null) return false;
- if (mLauncher.getNavigationModel() == ZERO_BUTTON) return true;
- final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame");
- return icon.getVisibleBounds().bottom < navBar.getVisibleBounds().top;
+ private boolean hasClickableIcon(
+ UiObject2 allAppsContainer, UiObject2 appListRecycler, BySelector appIconSelector) {
+ final UiObject2 icon = appListRecycler.findObject(appIconSelector);
+ if (icon == null) {
+ LauncherInstrumentation.log("hasClickableIcon: icon not visible");
+ return false;
+ }
+ final Rect iconBounds = icon.getVisibleBounds();
+ LauncherInstrumentation.log("hasClickableIcon: icon bounds: " + iconBounds);
+ if (mLauncher.getNavigationModel() != ZERO_BUTTON) {
+ final UiObject2 navBar = mLauncher.waitForSystemUiObject("navigation_bar_frame");
+ if (iconBounds.bottom >= navBar.getVisibleBounds().top) {
+ LauncherInstrumentation.log("hasClickableIcon: icon intersects with nav bar");
+ return false;
+ }
+ }
+ if (iconCenterInSearchBox(allAppsContainer, icon)) {
+ LauncherInstrumentation.log("hasClickableIcon: icon center is under search box");
+ return false;
+ }
+ LauncherInstrumentation.log("hasClickableIcon: icon is clickable");
+ return true;
+ }
+
+ private boolean iconCenterInSearchBox(UiObject2 allAppsContainer, UiObject2 icon) {
+ final Point iconCenter = icon.getVisibleCenter();
+ return getSearchBox(allAppsContainer).getVisibleBounds().contains(
+ iconCenter.x, iconCenter.y);
}
/**
@@ -66,17 +89,22 @@
@NonNull
public AppIcon getAppIcon(String appName) {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to get app icon on all apps")) {
+ "want to get app icon " + appName + " on all apps")) {
final UiObject2 allAppsContainer = verifyActiveContainer();
- allAppsContainer.setGestureMargins(0, 0, 0,
- ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_VERTICAL_SIZE,
+ final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer,
+ "apps_list_view");
+ allAppsContainer.setGestureMargins(
+ 0,
+ getSearchBox(allAppsContainer).getVisibleBounds().bottom + 1,
+ 0,
+ ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE,
mLauncher.getResources()) + 1);
final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher);
- if (!hasClickableIcon(allAppsContainer, appIconSelector)) {
+ if (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector)) {
scrollBackToBeginning();
int attempts = 0;
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled")) {
- while (!hasClickableIcon(allAppsContainer, appIconSelector) &&
+ while (!hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector) &&
allAppsContainer.scroll(Direction.DOWN, 0.8f)) {
mLauncher.assertTrue(
"Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS,
@@ -89,7 +117,7 @@
final UiObject2 appIcon = mLauncher.getObjectInContainer(allAppsContainer,
appIconSelector);
- ensureIconVisible(appIcon, allAppsContainer);
+ ensureIconVisible(appIcon, allAppsContainer, appListRecycler);
return new AppIcon(mLauncher, appIcon);
}
}
@@ -97,10 +125,9 @@
private void scrollBackToBeginning() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to scroll back in all apps")) {
+ LauncherInstrumentation.log("Scrolling to the beginning");
final UiObject2 allAppsContainer = verifyActiveContainer();
- final UiObject2 searchBox =
- mLauncher.waitForObjectInContainer(allAppsContainer,
- "search_container_all_apps");
+ final UiObject2 searchBox = getSearchBox(allAppsContainer);
int attempts = 0;
final Rect margins = new Rect(0, searchBox.getVisibleBounds().bottom + 1, 0, 5);
@@ -128,19 +155,26 @@
getInt(TestProtocol.SCROLL_Y_FIELD, -1);
}
- private void ensureIconVisible(UiObject2 appIcon, UiObject2 allAppsContainer) {
+ private void ensureIconVisible(
+ UiObject2 appIcon, UiObject2 allAppsContainer, UiObject2 appListRecycler) {
final int appHeight = appIcon.getVisibleBounds().height();
if (appHeight < MIN_INTERACT_SIZE) {
// Try to figure out how much percentage of the container needs to be scrolled in order
// to reveal the app icon to have the MIN_INTERACT_SIZE
final float pct = Math.max(((float) (MIN_INTERACT_SIZE - appHeight)) / mHeight, 0.2f);
- mLauncher.scroll(allAppsContainer, Direction.DOWN, pct, null, 10);
+ mLauncher.scroll(appListRecycler, Direction.DOWN, pct, null, 10);
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"scrolled an icon in all apps to make it visible - and then")) {
mLauncher.waitForIdle();
verifyActiveContainer();
}
}
+ mLauncher.assertTrue("Couldn't scroll app icon to not intersect with the search box",
+ !iconCenterInSearchBox(allAppsContainer, appIcon));
+ }
+
+ private UiObject2 getSearchBox(UiObject2 allAppsContainer) {
+ return mLauncher.waitForObjectInContainer(allAppsContainer, "search_container_all_apps");
}
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
index c3b671b..a472d31 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
@@ -53,9 +53,9 @@
TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT).
getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
- final int endY = start.y + swipeHeight + mLauncher.getTouchSlop();
+ final int endY = start.y + swipeHeight;
LauncherInstrumentation.log("AllAppsFromOverview.switchBackToOverview before swipe");
- mLauncher.swipe(start.x, start.y, start.x, endY, OVERVIEW_STATE_ORDINAL);
+ mLauncher.swipeToState(start.x, start.y, start.x, endY, 60, OVERVIEW_STATE_ORDINAL);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("swiped down")) {
return new Overview(mLauncher);
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 8f5e7fe..55e14cc 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -86,9 +86,10 @@
final int swipeHeight = mLauncher.getTestInfo(getSwipeHeightRequestName()).
getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
- mLauncher.swipe(
+ mLauncher.swipeToState(
centerX, startY, centerX,
startY - swipeHeight - mLauncher.getTouchSlop(),
+ 60,
expectedState);
break;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index b3a369a..ace49e9 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -28,7 +28,7 @@
* Common overview pane for both Launcher and fallback recents
*/
public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
- private static final int FLING_SPEED = LauncherInstrumentation.needSlowGestures() ? 500 : 1500;
+ private static final int FLING_SPEED = LauncherInstrumentation.isAvd() ? 500 : 1500;
private static final int FLINGS_FOR_DISMISS_LIMIT = 40;
BaseOverview(LauncherInstrumentation launcher) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 1b372ec..3295ddb 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -24,6 +24,8 @@
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
+import com.android.launcher3.TestProtocol;
+
/**
* Ancestor for AppIcon and AppMenuItem.
*/
@@ -51,9 +53,11 @@
private Background launch(BySelector selector) {
LauncherInstrumentation.log("Launchable.launch before click " +
mObject.getVisibleCenter());
+ mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
mLauncher.assertTrue(
"Launching an app didn't open a new window: " + mObject.getText(),
mObject.clickAndWait(Until.newWindow(), LauncherInstrumentation.WAIT_TIME_MS));
+ mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
mLauncher.assertTrue(
"App didn't start: " + selector,
mLauncher.getDevice().wait(Until.hasObject(selector),
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index d3f1460..a4711f5 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -198,7 +198,7 @@
return NavigationModel.THREE_BUTTON;
}
- public static boolean needSlowGestures() {
+ public static boolean isAvd() {
return Build.MODEL.contains("Cuttlefish");
}
@@ -584,18 +584,15 @@
return mDevice;
}
- void swipe(int startX, int startY, int endX, int endY, int expectedState) {
- swipe(startX, startY, endX, endY, expectedState, 60);
- }
-
- void swipe(int startX, int startY, int endX, int endY, int expectedState, int steps) {
- changeStateViaGesture(startX, startY, endX, endY, expectedState,
- () -> mDevice.swipe(startX, startY, endX, endY, steps));
- }
-
void swipeToState(int startX, int startY, int endX, int endY, int steps, int expectedState) {
- changeStateViaGesture(startX, startY, endX, endY, expectedState,
- () -> linearGesture(startX, startY, endX, endY, steps));
+ final Bundle parcel = (Bundle) executeAndWaitForEvent(
+ () -> linearGesture(startX, startY, endX, endY, steps),
+ event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()),
+ "Swipe failed to receive an event for the swipe end: " + startX + ", " + startY
+ + ", " + endX + ", " + endY);
+ assertEquals("Swipe switched launcher to a wrong state;",
+ TestProtocol.stateOrdinalToString(expectedState),
+ TestProtocol.stateOrdinalToString(parcel.getInt(TestProtocol.STATE_FIELD)));
}
void scroll(UiObject2 container, Direction direction, float percent, Rect margins, int steps) {
@@ -652,18 +649,6 @@
sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end);
}
- private void changeStateViaGesture(int startX, int startY, int endX, int endY,
- int expectedState, Runnable gesture) {
- final Bundle parcel = (Bundle) executeAndWaitForEvent(
- gesture,
- event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()),
- "Swipe failed to receive an event for the swipe end: " + startX + ", " + startY
- + ", " + endX + ", " + endY);
- assertEquals("Swipe switched launcher to a wrong state;",
- TestProtocol.stateOrdinalToString(expectedState),
- TestProtocol.stateOrdinalToString(parcel.getInt(TestProtocol.STATE_FIELD)));
- }
-
void waitForIdle() {
mDevice.waitForIdle();
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index f7e0b6c..b780df4 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -41,7 +41,7 @@
LauncherInstrumentation.log("Widgets.flingForward enter");
final UiObject2 widgetsContainer = verifyActiveContainer();
widgetsContainer.setGestureMargins(0, 0, 0,
- ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_VERTICAL_SIZE,
+ ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_PORTRAIT_BOTTOM_SIZE,
mLauncher.getResources()) + 1);
widgetsContainer.fling(Direction.DOWN,
(int) (FLING_SPEED * mLauncher.getDisplayDensity()));
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 3cab1a1..10b253d 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -37,7 +37,7 @@
*/
public final class Workspace extends Home {
private static final float FLING_SPEED =
- LauncherInstrumentation.needSlowGestures() ? 1500.0F : 3500.0F;
+ LauncherInstrumentation.isAvd() ? 1500.0F : 3500.0F;
private static final int DRAG_DURACTION = 2000;
private final UiObject2 mHotseat;
@@ -148,6 +148,7 @@
static void dragIconToWorkspace(
LauncherInstrumentation launcher, Launchable launchable, Point dest,
String longPressIndicator) {
+ launcher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
LauncherInstrumentation.log("dragIconToWorkspace: begin");
final Point launchableCenter = launchable.getObject().getVisibleCenter();
final long downTime = SystemClock.uptimeMillis();
@@ -162,6 +163,7 @@
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest);
LauncherInstrumentation.log("dragIconToWorkspace: end");
launcher.waitUntilGone("drop_target_bar");
+ launcher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
}
/**