diff --git a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 900b94e186..917800f2a6 100644
--- a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -34,6 +34,8 @@ import android.view.MotionEvent;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -137,6 +139,9 @@ public class TouchInteractionService extends Service {
return sConnected;
}
+ public static final LooperExecutor BACKGROUND_EXECUTOR =
+ new LooperExecutor(UiThreadHelper.getBackgroundLooper());
+
private RecentsModel mRecentsModel;
private OverviewComponentObserver mOverviewComponentObserver;
private OverviewCommandHelper mOverviewCommandHelper;
@@ -180,4 +185,8 @@ public class TouchInteractionService extends Service {
}
return mMyBinder;
}
+
+ public static boolean isInputMonitorInitialized() {
+ return true;
+ }
}
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 332e0fa360..546548036e 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -23,6 +23,7 @@
package="com.android.launcher3" >
+
+ implements SwipeAnimationListener {
+
+ private static final String TAG = "BaseSwipeUpHandler";
+ protected static final Rect TEMP_RECT = new Rect();
+
+ // Start resisting when swiping past this factor of mTransitionDragLength.
+ private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
+ // This is how far down we can scale down, where 0f is full screen and 1f is recents.
+ private static final float DRAG_LENGTH_FACTOR_MAX_PULLBACK = 1.8f;
+ private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
+
+ // The distance needed to drag to reach the task size in recents.
+ protected int mTransitionDragLength;
+ // How much further we can drag past recents, as a factor of mTransitionDragLength.
+ protected float mDragLengthFactor = 1;
+
+ protected final Context mContext;
+ protected final OverviewComponentObserver mOverviewComponentObserver;
+ protected final ActivityControlHelper mActivityControlHelper;
+ protected final RecentsModel mRecentsModel;
+ protected final int mRunningTaskId;
+
+ protected final ClipAnimationHelper mClipAnimationHelper;
+ protected final TransformParams mTransformParams = new TransformParams();
+
+ private final Vibrator mVibrator;
+ protected final Mode mMode;
+
+ // Shift in the range of [0, 1].
+ // 0 => preview snapShot is completely visible, and hotseat is completely translated down
+ // 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
+ // visible.
+ protected final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
+
+ protected final ActivityInitListener mActivityInitListener;
+ protected final RecentsAnimationWrapper mRecentsAnimationWrapper;
+
+ protected T mActivity;
+ protected Q mRecentsView;
+ protected DeviceProfile mDp;
+ private final int mPageSpacing;
+
+ protected Runnable mGestureEndCallback;
+
+ protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
+ protected MultiStateCallback mStateCallback;
+
+ protected boolean mCanceled;
+ protected int mFinishingRecentsAnimationForNewTaskId = -1;
+
+ protected BaseSwipeUpHandler(Context context,
+ OverviewComponentObserver overviewComponentObserver,
+ RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
+ mContext = context;
+ mOverviewComponentObserver = overviewComponentObserver;
+ mActivityControlHelper = overviewComponentObserver.getActivityControlHelper();
+ mRecentsModel = recentsModel;
+ mActivityInitListener =
+ mActivityControlHelper.createActivityInitListener(this::onActivityInit);
+ mRunningTaskId = runningTaskId;
+ mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
+ this::createNewInputProxyHandler);
+ mMode = SysUINavigationMode.getMode(context);
+
+ mClipAnimationHelper = new ClipAnimationHelper(context);
+ mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
+ mVibrator = context.getSystemService(Vibrator.class);
+ initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
+ .getDeviceProfile(mContext));
+ }
+
+ protected void setStateOnUiThread(int stateFlag) {
+ if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
+ mStateCallback.setState(stateFlag);
+ } else {
+ postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
+ }
+ }
+
+ protected void performHapticFeedback() {
+ if (!mVibrator.hasVibrator()) {
+ return;
+ }
+ if (Settings.System.getInt(
+ mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0) {
+ return;
+ }
+
+ VibrationEffect effect = createPredefined(EFFECT_CLICK);
+ if (effect == null) {
+ return;
+ }
+ BACKGROUND_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
+ }
+
+ public Consumer getRecentsViewDispatcher(RotationMode rotationMode) {
+ return mRecentsView != null ? mRecentsView.getEventDispatcher(rotationMode) : null;
+ }
+
+ @UiThread
+ public void updateDisplacement(float displacement) {
+ // We are moving in the negative x/y direction
+ displacement = -displacement;
+ float shift;
+ if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
+ shift = mDragLengthFactor;
+ } else {
+ float translation = Math.max(displacement, 0);
+ shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
+ if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
+ float pullbackProgress = Utilities.getProgress(shift,
+ DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
+ pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
+ shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
+ * (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
+ }
+ }
+
+ mCurrentShift.updateValue(shift);
+ }
+
+ public void setGestureEndCallback(Runnable gestureEndCallback) {
+ mGestureEndCallback = gestureEndCallback;
+ }
+
+ public abstract Intent getLaunchIntent();
+
+ protected void linkRecentsViewScroll() {
+ SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
+ mTransformParams.setSyncTransactionApplier(applier);
+ mRecentsAnimationWrapper.runOnInit(() ->
+ mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
+ });
+
+ mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
+ if (moveWindowWithRecentsScroll()) {
+ updateFinalShift();
+ }
+ });
+ mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
+ mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
+ }
+
+ protected void startNewTask(int successStateFlag, Consumer resultCallback) {
+ // Launch the task user scrolled to (mRecentsView.getNextPage()).
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ // We finish recents animation inside launchTask() when live tile is enabled.
+ mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
+ true /* freezeTaskList */);
+ } else {
+ int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
+ mFinishingRecentsAnimationForNewTaskId = taskId;
+ mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
+ if (!mCanceled) {
+ TaskView nextTask = mRecentsView.getTaskView(taskId);
+ if (nextTask != null) {
+ nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
+ success -> {
+ resultCallback.accept(success);
+ if (!success) {
+ mActivityControlHelper.onLaunchTaskFailed(mActivity);
+ nextTask.notifyTaskLaunchFailed(TAG);
+ } else {
+ mActivityControlHelper.onLaunchTaskSuccess(mActivity);
+ }
+ }, mMainThreadHandler);
+ }
+ setStateOnUiThread(successStateFlag);
+ }
+ mCanceled = false;
+ mFinishingRecentsAnimationForNewTaskId = -1;
+ });
+ }
+ TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
+ }
+
+ @Override
+ public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
+ DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
+ final Rect overviewStackBounds;
+ RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
+
+ if (targetSet.minimizedHomeBounds != null && runningTaskTarget != null) {
+ overviewStackBounds = mActivityControlHelper
+ .getOverviewWindowBounds(targetSet.minimizedHomeBounds, runningTaskTarget);
+ dp = dp.getMultiWindowProfile(mContext, new Point(
+ overviewStackBounds.width(), overviewStackBounds.height()));
+ } else {
+ // If we are not in multi-window mode, home insets should be same as system insets.
+ dp = dp.copy(mContext);
+ overviewStackBounds = getStackBounds(dp);
+ }
+ dp.updateInsets(targetSet.homeContentInsets);
+ dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
+ if (runningTaskTarget != null) {
+ mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
+ }
+
+ mClipAnimationHelper.prepareAnimation(dp, false /* isOpening */);
+ initTransitionEndpoints(dp);
+
+ mRecentsAnimationWrapper.setController(targetSet);
+ }
+
+ private Rect getStackBounds(DeviceProfile dp) {
+ if (mActivity != null) {
+ int loc[] = new int[2];
+ View rootView = mActivity.getRootView();
+ rootView.getLocationOnScreen(loc);
+ return new Rect(loc[0], loc[1], loc[0] + rootView.getWidth(),
+ loc[1] + rootView.getHeight());
+ } else {
+ return new Rect(0, 0, dp.widthPx, dp.heightPx);
+ }
+ }
+
+ protected void initTransitionEndpoints(DeviceProfile dp) {
+ mDp = dp;
+
+ mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
+ dp, mContext, TEMP_RECT);
+ if (!dp.isMultiWindowMode) {
+ // When updating the target rect, also update the home bounds since the location on
+ // screen of the launcher window may be stale (position is not updated until first
+ // traversal after the window is resized). We only do this for non-multiwindow because
+ // we otherwise use the minimized home bounds provided by the system.
+ mClipAnimationHelper.updateHomeBounds(getStackBounds(dp));
+ }
+ mClipAnimationHelper.updateTargetRect(TEMP_RECT);
+ if (mMode == Mode.NO_BUTTON) {
+ // We can drag all the way to the top of the screen.
+ mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
+ }
+ }
+
+ /**
+ * Return true if the window should be translated horizontally if the recents view scrolls
+ */
+ protected abstract boolean moveWindowWithRecentsScroll();
+
+ protected abstract boolean onActivityInit(final T activity, Boolean alreadyOnHome);
+
+ /**
+ * Called to create a input proxy for the running task
+ */
+ @UiThread
+ protected abstract InputConsumer createNewInputProxyHandler();
+
+ /**
+ * Called when the value of {@link #mCurrentShift} changes
+ */
+ @UiThread
+ public abstract void updateFinalShift();
+
+ /**
+ * Called when motion pause is detected
+ */
+ public abstract void onMotionPauseChanged(boolean isPaused);
+
+ @UiThread
+ public void onGestureStarted() { }
+
+ @UiThread
+ public abstract void onGestureCancelled();
+
+ @UiThread
+ public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
+
+ public abstract void onConsumerAboutToBeSwitched(SwipeSharedState sharedState);
+
+ public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { }
+
+ public void initWhenReady() {
+ // Preload the plan
+ mRecentsModel.getTasks(null);
+
+ mActivityInitListener.register();
+ }
+
+ /**
+ * Applies the transform on the recents animation without any additional null checks
+ */
+ protected void applyTransformUnchecked() {
+ float shift = mCurrentShift.value;
+ float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
+ float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
+ mClipAnimationHelper.getTargetRect().width());
+ mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
+ mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
+ mTransformParams);
+ }
+
+ private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
+ float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 + mPageSpacing;
+ float interpolation = Math.min(1, offsetX / distanceToReachEdge);
+ return TaskView.getCurveScaleForInterpolation(interpolation);
+ }
+
+ /**
+ * Creates an animation that transforms the current app window into the home app.
+ * @param startProgress The progress of {@link #mCurrentShift} to start the window from.
+ * @param homeAnimationFactory The home animation factory.
+ */
+ protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
+ HomeAnimationFactory homeAnimationFactory) {
+ final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet;
+ final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet,
+ mTransformParams.setProgress(startProgress), false /* launcherOnTop */));
+ final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
+
+ final View floatingView = homeAnimationFactory.getFloatingView();
+ final boolean isFloatingIconView = floatingView instanceof FloatingIconView;
+ RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext.getResources());
+ if (isFloatingIconView) {
+ FloatingIconView fiv = (FloatingIconView) floatingView;
+ anim.addAnimatorListener(fiv);
+ fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
+ }
+
+ AnimatorPlaybackController homeAnim = homeAnimationFactory.createActivityAnimationToHome();
+
+ // End on a "round-enough" radius so that the shape reveal doesn't have to do too much
+ // rounding at the end of the animation.
+ float startRadius = mClipAnimationHelper.getCurrentCornerRadius();
+ float endRadius = startRect.width() / 6f;
+ // We want the window alpha to be 0 once this threshold is met, so that the
+ // FolderIconView can be seen morphing into the icon shape.
+ final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f;
+ anim.addOnUpdateListener(new RectFSpringAnim.OnUpdateListener() {
+ @Override
+ public void onUpdate(RectF currentRect, float progress) {
+ homeAnim.setPlayFraction(progress);
+
+ float alphaProgress = ACCEL_1_5.getInterpolation(progress);
+ float windowAlpha = Utilities.boundToRange(Utilities.mapToRange(alphaProgress, 0,
+ windowAlphaThreshold, 1.5f, 0f, Interpolators.LINEAR), 0, 1);
+ mTransformParams.setProgress(progress)
+ .setCurrentRectAndTargetAlpha(currentRect, windowAlpha);
+ if (isFloatingIconView) {
+ mTransformParams.setCornerRadius(endRadius * progress + startRadius
+ * (1f - progress));
+ }
+ mClipAnimationHelper.applyTransform(targetSet, mTransformParams,
+ false /* launcherOnTop */);
+
+ if (isFloatingIconView) {
+ ((FloatingIconView) floatingView).update(currentRect, 1f, progress,
+ windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false);
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ if (isFloatingIconView) {
+ ((FloatingIconView) floatingView).fastFinish();
+ }
+ }
+ });
+ anim.addAnimatorListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ homeAnim.dispatchOnStart();
+ }
+
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ homeAnim.getAnimationPlayer().end();
+ }
+ });
+ return anim;
+ }
+
+ public interface Factory {
+
+ BaseSwipeUpHandler newHandler(RunningTaskInfo runningTask,
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask);
+ }
+
+ protected interface RunningWindowAnim {
+ void end();
+
+ void cancel();
+
+ static RunningWindowAnim wrap(Animator animator) {
+ return new RunningWindowAnim() {
+ @Override
+ public void end() {
+ animator.end();
+ }
+
+ @Override
+ public void cancel() {
+ animator.cancel();
+ }
+ };
+ }
+
+ static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) {
+ return new RunningWindowAnim() {
+ @Override
+ public void end() {
+ rectFSpringAnim.end();
+ }
+
+ @Override
+ public void cancel() {
+ rectFSpringAnim.cancel();
+ }
+ };
+ }
+ }
+}
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 b2a71a4882..295585e002 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -151,16 +151,10 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@NonNull
@Override
public RectF getWindowTargetRect() {
- final int halfIconSize = dp.iconSizePx / 2;
- final float targetCenterX = dp.availableWidthPx / 2f;
- final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx;
-
if (canUseWorkspaceView) {
return iconLocation;
} else {
- // Fallback to animate to center of screen.
- return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize,
- targetCenterX + halfIconSize, targetCenterY + halfIconSize);
+ return HomeAnimationFactory.getDefaultWindowTargetRect(dp);
}
}
@@ -194,9 +188,6 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@Override
public AnimationFactory prepareRecentsUI(Launcher activity, boolean activityVisible,
boolean animateActivity, Consumer callback) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "prepareRecentsUI");
- }
final LauncherState startState = activity.getStateManager().getState();
LauncherState resetState = startState;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
new file mode 100644
index 0000000000..b507044e0a
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -0,0 +1,83 @@
+package com.android.quickstep;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.testing.TestInformationHandler;
+import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.uioverrides.states.OverviewState;
+import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
+import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.views.RecentsView;
+
+import java.util.concurrent.ExecutionException;
+
+public class QuickstepTestInformationHandler extends TestInformationHandler {
+
+ public QuickstepTestInformationHandler(Context context) {
+ }
+
+ @Override
+ public Bundle call(String method) {
+ final Bundle response = new Bundle();
+ switch (method) {
+ case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
+ final float swipeHeight =
+ OverviewState.getDefaultSwipeHeight(mDeviceProfile);
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
+ return response;
+ }
+
+ case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
+ final float swipeHeight =
+ LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile);
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
+ return response;
+ }
+
+ case TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED: {
+ response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ TouchInteractionService.isInputMonitorInitialized());
+ return response;
+ }
+
+ case TestProtocol.REQUEST_HOTSEAT_TOP: {
+ if (mLauncher == null) return null;
+
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ PortraitStatesTouchController.getHotseatTop(mLauncher));
+ return response;
+ }
+
+ case TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN: {
+ try {
+ final int leftMargin = new MainThreadExecutor().submit(() ->
+ mLauncher.getOverviewPanel().getLeftGestureMargin()).get();
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, leftMargin);
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return response;
+ }
+
+ case TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN: {
+ try {
+ final int rightMargin = new MainThreadExecutor().submit(() ->
+ mLauncher.getOverviewPanel().getRightGestureMargin()).
+ get();
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, rightMargin);
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return response;
+ }
+ }
+
+ return super.call(method);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index fc29a5663b..60e7b12ec4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -28,8 +28,10 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
+import android.content.Intent;
import android.content.res.Configuration;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.view.View;
@@ -42,7 +44,9 @@ import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.ObjectWrapper;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
@@ -54,6 +58,9 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
*/
public final class RecentsActivity extends BaseRecentsActivity {
+ public static final String EXTRA_THUMBNAIL = "thumbnailData";
+ public static final String EXTRA_TASK_ID = "taskID";
+
private Handler mUiHandler = new Handler(Looper.getMainLooper());
private RecentsRootView mRecentsRootView;
private FallbackRecentsView mFallbackRecentsView;
@@ -78,6 +85,22 @@ public final class RecentsActivity extends BaseRecentsActivity {
}
}
+ @Override
+ protected void onNewIntent(Intent intent) {
+ if (intent.getExtras() != null) {
+ int taskID = intent.getIntExtra(EXTRA_TASK_ID, 0);
+ IBinder thumbnail = intent.getExtras().getBinder(EXTRA_THUMBNAIL);
+ if (taskID != 0 && thumbnail instanceof ObjectWrapper) {
+ ThumbnailData thumbnailData = ((ObjectWrapper) thumbnail).get();
+ mFallbackRecentsView.showCurrentTask(taskID);
+ mFallbackRecentsView.updateThumbnail(taskID, thumbnailData);
+ }
+ }
+ intent.removeExtra(EXTRA_TASK_ID);
+ intent.removeExtra(EXTRA_THUMBNAIL);
+ super.onNewIntent(intent);
+ }
+
@Override
protected void onHandleConfigChanged() {
super.onHandleConfigChanged();
@@ -178,6 +201,12 @@ public final class RecentsActivity extends BaseRecentsActivity {
mFallbackRecentsView.resetTaskVisuals();
}
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mFallbackRecentsView.reset();
+ }
+
public void onTaskLaunched() {
mFallbackRecentsView.resetTaskVisuals();
}
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 bf9d531061..debed898ef 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -43,7 +43,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.RectF;
@@ -77,6 +76,7 @@ import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.logging.EventLogArray;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
+import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
@@ -95,12 +95,12 @@ import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+import com.android.systemui.shared.system.RecentsAnimationListener;
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
import java.io.FileDescriptor;
@@ -124,10 +124,6 @@ class ArgList extends LinkedList {
public String nextArg() {
return pollFirst().toLowerCase();
}
-
- public String nextArgExact() {
- return pollFirst();
- }
}
/**
@@ -231,12 +227,17 @@ public class TouchInteractionService extends Service implements
};
private static boolean sConnected = false;
+ private static boolean sInputMonitorInitialized = false;
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
public static boolean isConnected() {
return sConnected;
}
+ public static boolean isInputMonitorInitialized() {
+ return sInputMonitorInitialized;
+ }
+
public static SwipeSharedState getSwipeSharedState() {
return sSwipeSharedState;
}
@@ -244,6 +245,11 @@ public class TouchInteractionService extends Service implements
private final InputConsumer mResetGestureInputConsumer =
new ResetGestureInputConsumer(sSwipeSharedState);
+ private final BaseSwipeUpHandler.Factory mWindowTreansformFactory =
+ this::createWindowTransformSwipeHandler;
+ private final BaseSwipeUpHandler.Factory mFallbackNoButtonFactory =
+ this::createFallbackNoButtonSwipeHandler;
+
private ActivityManagerWrapper mAM;
private RecentsModel mRecentsModel;
private ISystemUiProxy mISystemUiProxy;
@@ -330,6 +336,7 @@ public class TouchInteractionService extends Service implements
mInputMonitorCompat.dispose();
mInputMonitorCompat = null;
}
+ sInputMonitorInitialized = false;
}
private void initInputMonitor() {
@@ -347,6 +354,7 @@ public class TouchInteractionService extends Service implements
Log.e(TAG, "Unable to create input monitor", e);
}
initTouchBounds();
+ sInputMonitorInitialized = true;
}
private int getNavbarSize(String resName) {
@@ -508,9 +516,6 @@ public class TouchInteractionService extends Service implements
}
private void onInputEvent(InputEvent ev) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onInputEvent " + ev);
- }
if (!(ev instanceof MotionEvent)) {
Log.e(TAG, "Unknown event " + ev);
return;
@@ -628,10 +633,6 @@ public class TouchInteractionService extends Service implements
} else if (mGestureBlockingActivity != null && runningTaskInfo != null
&& mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) {
return mResetGestureInputConsumer;
- } else if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
- return new FallbackNoButtonInputConsumer(this, activityControl,
- mInputMonitorCompat, sSwipeSharedState, mSwipeTouchRegion,
- mOverviewComponentObserver, disableHorizontalSwipe(event), runningTaskInfo);
} else {
return createOtherActivityInputConsumer(event, runningTaskInfo);
}
@@ -644,17 +645,25 @@ public class TouchInteractionService extends Service implements
&& exclusionRegion.contains((int) event.getX(), (int) event.getY());
}
- private OtherActivityInputConsumer createOtherActivityInputConsumer(MotionEvent event,
+ private InputConsumer createOtherActivityInputConsumer(MotionEvent event,
RunningTaskInfo runningTaskInfo) {
- final ActivityControlHelper activityControl =
- mOverviewComponentObserver.getActivityControlHelper();
- boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
- return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
- mOverviewComponentObserver.getOverviewIntent(), activityControl,
- shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive,
+ final boolean shouldDefer;
+ final BaseSwipeUpHandler.Factory factory;
+
+ if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
+ shouldDefer = !sSwipeSharedState.recentsAnimationFinishInterrupted;
+ factory = mFallbackNoButtonFactory;
+ } else {
+ shouldDefer = mOverviewComponentObserver.getActivityControlHelper()
+ .deferStartingActivity(mActiveNavBarRegion, event);
+ factory = mWindowTreansformFactory;
+ }
+
+ return new OtherActivityInputConsumer(this, runningTaskInfo,
+ shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
- disableHorizontalSwipe(event));
+ disableHorizontalSwipe(event), factory);
}
private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
@@ -697,6 +706,16 @@ public class TouchInteractionService extends Service implements
if (!mIsUserUnlocked) {
return;
}
+ if (!mMode.hasGestures && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
+ // Prevent the overview from being started before the real home on first boot.
+ return;
+ }
+
+ if (RestoreDbTask.isPending(this)) {
+ // Preloading while a restore is pending may cause launcher to start the restore
+ // too early.
+ return;
+ }
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
@@ -714,11 +733,7 @@ public class TouchInteractionService extends Service implements
}
// Pass null animation handler to indicate this start is preload.
- BackgroundExecutor.get().submit(
- () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
- mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(),
- null /* assistDataReceiver */, null /* animationHandler */,
- null /* resultCallback */, null /* resultCallbackHandler */));
+ startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null);
}
@Override
@@ -796,4 +811,21 @@ public class TouchInteractionService extends Service implements
break;
}
}
+
+ private BaseSwipeUpHandler createWindowTransformSwipeHandler(RunningTaskInfo runningTask,
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
+ return new WindowTransformSwipeHandler(runningTask, this, touchTimeMs,
+ mOverviewComponentObserver, continuingLastGesture, mInputConsumer, mRecentsModel);
+ }
+
+ private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(RunningTaskInfo runningTask,
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
+ return new FallbackNoButtonInputConsumer(this, mOverviewComponentObserver, runningTask,
+ mRecentsModel, mInputConsumer, isLikelyToStartNewTask, continuingLastGesture);
+ }
+
+ public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
+ BACKGROUND_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
+ .startRecentsActivity(intent, null, listener, null, null));
+ }
}
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 ac7ba3fc3d..df37759cc4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -18,8 +18,6 @@ package com.android.quickstep;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
-import static com.android.launcher3.Utilities.postAsyncCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
@@ -28,11 +26,9 @@ import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
-import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
@@ -43,65 +39,46 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_O
import android.animation.Animator;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Canvas;
-import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
import android.os.SystemClock;
-import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowInsets;
-import android.view.WindowManager;
import android.view.animation.Interpolator;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.logging.UserEventDispatcher;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.views.FloatingIconView;
-import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.inputconsumers.InputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
-import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.ClipAnimationHelper.TargetAlphaProvider;
import com.android.quickstep.util.RectFSpringAnim;
-import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
-import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import com.android.quickstep.views.LiveTileOverlay;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -109,19 +86,17 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
-import java.util.function.BiFunction;
-import java.util.function.Consumer;
+import androidx.annotation.NonNull;
+import androidx.annotation.UiThread;
@TargetApi(Build.VERSION_CODES.O)
public class WindowTransformSwipeHandler
- implements SwipeAnimationListener, OnApplyWindowInsetsListener {
+ extends BaseSwipeUpHandler
+ implements OnApplyWindowInsetsListener {
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
- private static final Rect TEMP_RECT = new Rect();
-
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
private static int getFlagForIndex(int index, String name) {
@@ -220,64 +195,30 @@ public class WindowTransformSwipeHandler
private static final long SHELF_ANIM_DURATION = 240;
public static final long RECENTS_ATTACH_DURATION = 300;
- // Start resisting when swiping past this factor of mTransitionDragLength.
- private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
- // This is how far down we can scale down, where 0f is full screen and 1f is recents.
- private static final float DRAG_LENGTH_FACTOR_MAX_PULLBACK = 1.8f;
- private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
-
/**
* Used as the page index for logging when we return to the last task at the end of the gesture.
*/
private static final int LOG_NO_OP_PAGE_INDEX = -1;
- private final ClipAnimationHelper mClipAnimationHelper;
- private final ClipAnimationHelper.TransformParams mTransformParams;
-
- private Runnable mGestureEndCallback;
private GestureEndTarget mGestureEndTarget;
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
private boolean mIsShelfPeeking;
- private DeviceProfile mDp;
- // The distance needed to drag to reach the task size in recents.
- private int mTransitionDragLength;
- // How much further we can drag past recents, as a factor of mTransitionDragLength.
- private float mDragLengthFactor = 1;
- // Shift in the range of [0, 1].
- // 0 => preview snapShot is completely visible, and hotseat is completely translated down
- // 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
- // visible.
- private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
private boolean mContinuingLastGesture;
// To avoid UI jump when gesture is started, we offset the animation by the threshold.
private float mShiftAtGestureStart = 0;
- private final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
-
- private final Context mContext;
- private final ActivityControlHelper mActivityControlHelper;
- private final ActivityInitListener mActivityInitListener;
-
- private final SysUINavigationMode.Mode mMode;
-
- private final int mRunningTaskId;
private ThumbnailData mTaskSnapshot;
- private MultiStateCallback mStateCallback;
// Used to control launcher components throughout the swipe gesture.
private AnimatorPlaybackController mLauncherTransitionController;
private boolean mHasLauncherTransitionControllerStarted;
- private T mActivity;
- private RecentsView mRecentsView;
private AnimationFactory mAnimationFactory = (t) -> { };
private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
- private boolean mCanceled;
private boolean mWasLauncherAlreadyVisible;
- private int mFinishingRecentsAnimationForNewTaskId = -1;
private boolean mPassedOverviewThreshold;
private boolean mGestureStarted;
@@ -286,31 +227,17 @@ public class WindowTransformSwipeHandler
private PointF mDownPos;
private boolean mIsLikelyToStartNewTask;
- private final RecentsAnimationWrapper mRecentsAnimationWrapper;
-
private final long mTouchTimeMs;
private long mLauncherFrameDrawnTime;
public WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
- long touchTimeMs, ActivityControlHelper controller, boolean continuingLastGesture,
- InputConsumerController inputConsumer) {
- mContext = context;
- mRunningTaskId = runningTaskInfo.id;
+ long touchTimeMs, OverviewComponentObserver overviewComponentObserver,
+ boolean continuingLastGesture,
+ InputConsumerController inputConsumer, RecentsModel recentsModel) {
+ super(context, overviewComponentObserver, recentsModel, inputConsumer, runningTaskInfo.id);
mTouchTimeMs = touchTimeMs;
- mActivityControlHelper = controller;
- mActivityInitListener = mActivityControlHelper
- .createActivityInitListener(this::onActivityInit);
mContinuingLastGesture = continuingLastGesture;
- mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
- this::createNewInputProxyHandler);
- mClipAnimationHelper = new ClipAnimationHelper(context);
- mTransformParams = new ClipAnimationHelper.TransformParams();
-
- mMode = SysUINavigationMode.getMode(context);
initStateCallbacks();
-
- DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
- initTransitionEndpoints(dp);
}
private void initStateCallbacks() {
@@ -373,44 +300,8 @@ public class WindowTransformSwipeHandler
}
}
- private void setStateOnUiThread(int stateFlag) {
- if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
- mStateCallback.setState(stateFlag);
- } else {
- postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag));
- }
- }
-
- private void initTransitionEndpoints(DeviceProfile dp) {
- mDp = dp;
-
- Rect tempRect = new Rect();
- mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
- dp, mContext, tempRect);
- mClipAnimationHelper.updateTargetRect(tempRect);
- if (mMode == Mode.NO_BUTTON) {
- // We can drag all the way to the top of the screen.
- mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
- }
- }
-
- private long getFadeInDuration() {
- if (mCurrentShift.getCurrentAnimation() != null) {
- ObjectAnimator anim = mCurrentShift.getCurrentAnimation();
- long theirDuration = anim.getDuration() - anim.getCurrentPlayTime();
-
- // TODO: Find a better heuristic
- return Math.min(MAX_SWIPE_DURATION, Math.max(theirDuration, MIN_SWIPE_DURATION));
- } else {
- return MAX_SWIPE_DURATION;
- }
- }
-
- public void initWhenReady() {
- mActivityInitListener.register();
- }
-
- private boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
+ @Override
+ protected boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
if (mActivity == activity) {
return true;
}
@@ -431,19 +322,7 @@ public class WindowTransformSwipeHandler
}
mRecentsView = activity.getOverviewPanel();
- SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, applier -> {
- mTransformParams.setSyncTransactionApplier(applier);
- mRecentsAnimationWrapper.runOnInit(() ->
- mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier));
- });
-
- mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
- if (mGestureEndTarget != HOME) {
- updateFinalShift();
- }
- });
- mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
- mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
+ linkRecentsViewScroll();
mRecentsView.setLiveTileOverlay(mLiveTileOverlay);
mActivity.getRootView().getOverlay().add(mLiveTileOverlay);
@@ -458,33 +337,23 @@ public class WindowTransformSwipeHandler
return true;
}
+ @Override
+ protected boolean moveWindowWithRecentsScroll() {
+ return mGestureEndTarget != HOME;
+ }
+
private void onLauncherStart(final T activity) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart");
- }
if (mActivity != activity) {
return;
}
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 1");
- }
if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
return;
}
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 2");
- }
// If we've already ended the gesture and are going home, don't prepare recents UI,
// as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL.
if (mGestureEndTarget != HOME) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 3");
- }
Runnable initAnimFactory = () -> {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 4");
- }
mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity,
mWasLauncherAlreadyVisible, true,
this::onAnimatorPlaybackControllerCreated);
@@ -494,14 +363,8 @@ public class WindowTransformSwipeHandler
// Launcher is visible, but might be about to stop. Thus, if we prepare recents
// now, it might get overridden by moveToRestState() in onStop(). To avoid this,
// wait until the next gesture (and possibly launcher) starts.
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 5");
- }
mStateCallback.addCallback(STATE_GESTURE_STARTED, initAnimFactory);
} else {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "onLauncherStart 6");
- }
initAnimFactory.run();
}
}
@@ -577,30 +440,7 @@ public class WindowTransformSwipeHandler
return TaskView.getCurveScaleForInterpolation(interpolation);
}
- public Consumer getRecentsViewDispatcher(RotationMode rotationMode) {
- return mRecentsView != null ? mRecentsView.getEventDispatcher(rotationMode) : null;
- }
-
- @UiThread
- public void updateDisplacement(float displacement) {
- // We are moving in the negative x/y direction
- displacement = -displacement;
- if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
- mCurrentShift.updateValue(mDragLengthFactor);
- } else {
- float translation = Math.max(displacement, 0);
- float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
- if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
- float pullbackProgress = Utilities.getProgress(shift,
- DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
- pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
- shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
- * (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
- }
- mCurrentShift.updateValue(shift);
- }
- }
-
+ @Override
public void onMotionPauseChanged(boolean isPaused) {
setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
}
@@ -651,6 +491,7 @@ public class WindowTransformSwipeHandler
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
}
+ @Override
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) {
mIsLikelyToStartNewTask = isLikelyToStartNewTask;
@@ -666,9 +507,8 @@ public class WindowTransformSwipeHandler
if (mIsShelfPeeking != wasShelfPeeking) {
maybeUpdateRecentsAttachedState();
}
- if (mRecentsView != null && shelfState.shouldPreformHaptic) {
- mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ if (shelfState.shouldPreformHaptic) {
+ performHapticFeedback();
}
}
@@ -697,19 +537,18 @@ public class WindowTransformSwipeHandler
updateLauncherTransitionProgress();
}
- @UiThread
- private void updateFinalShift() {
- float shift = mCurrentShift.value;
+ @Override
+ public Intent getLaunchIntent() {
+ return mOverviewComponentObserver.getOverviewIntent();
+ }
+
+ @Override
+ public void updateFinalShift() {
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
- float offsetX = mRecentsView == null ? 0 : mRecentsView.getScrollOffset();
- float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
- mClipAnimationHelper.getTargetRect().width());
- mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
- mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
- mTransformParams);
- updateSysUiFlags(shift);
+ applyTransformUnchecked();
+ updateSysUiFlags(mCurrentShift.value);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -722,9 +561,8 @@ public class WindowTransformSwipeHandler
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
if (passed != mPassedOverviewThreshold) {
mPassedOverviewThreshold = passed;
- if (mRecentsView != null && mMode != Mode.NO_BUTTON) {
- mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ if (mMode != Mode.NO_BUTTON) {
+ performHapticFeedback();
}
}
@@ -767,39 +605,7 @@ public class WindowTransformSwipeHandler
@Override
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
- DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
- final Rect overviewStackBounds;
- RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
-
- if (targetSet.minimizedHomeBounds != null && runningTaskTarget != null) {
- overviewStackBounds = mActivityControlHelper
- .getOverviewWindowBounds(targetSet.minimizedHomeBounds, runningTaskTarget);
- dp = dp.getMultiWindowProfile(mContext, new Point(
- targetSet.minimizedHomeBounds.width(), targetSet.minimizedHomeBounds.height()));
- dp.updateInsets(targetSet.homeContentInsets);
- } else {
- if (mActivity != null) {
- int loc[] = new int[2];
- View rootView = mActivity.getRootView();
- rootView.getLocationOnScreen(loc);
- overviewStackBounds = new Rect(loc[0], loc[1], loc[0] + rootView.getWidth(),
- loc[1] + rootView.getHeight());
- } else {
- overviewStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx);
- }
- // If we are not in multi-window mode, home insets should be same as system insets.
- dp = dp.copy(mContext);
- dp.updateInsets(targetSet.homeContentInsets);
- }
- dp.updateIsSeascape(mContext.getSystemService(WindowManager.class));
-
- if (runningTaskTarget != null) {
- mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
- }
- mClipAnimationHelper.prepareAnimation(dp, false /* isOpening */);
- initTransitionEndpoints(dp);
-
- mRecentsAnimationWrapper.setController(targetSet);
+ super.onRecentsAnimationStart(targetSet);
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimationCallback", targetSet.apps.length);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
@@ -814,7 +620,7 @@ public class WindowTransformSwipeHandler
TOUCH_INTERACTION_LOG.addLog("cancelRecentsAnimation");
}
- @UiThread
+ @Override
public void onGestureStarted() {
notifyGestureStartedAsync();
mShiftAtGestureStart = mCurrentShift.value;
@@ -838,7 +644,7 @@ public class WindowTransformSwipeHandler
/**
* Called as a result on ACTION_CANCEL to return the UI to the start state.
*/
- @UiThread
+ @Override
public void onGestureCancelled() {
updateDisplacement(0);
setStateOnUiThread(STATE_GESTURE_COMPLETED);
@@ -851,7 +657,7 @@ public class WindowTransformSwipeHandler
* @param velocity The x and y components of the velocity when the gesture ends.
* @param downPos The x and y value of where the gesture started.
*/
- @UiThread
+ @Override
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
@@ -869,9 +675,9 @@ public class WindowTransformSwipeHandler
handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
}
- @UiThread
- private InputConsumer createNewInputProxyHandler() {
- endRunningWindowAnim();
+ @Override
+ protected InputConsumer createNewInputProxyHandler() {
+ endRunningWindowAnim(true /* cancel */);
endLauncherTransitionController();
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
// Hide the task view, if not already hidden
@@ -883,9 +689,13 @@ public class WindowTransformSwipeHandler
? InputConsumer.NO_OP : new OverviewInputConsumer(activity, null, true);
}
- private void endRunningWindowAnim() {
+ private void endRunningWindowAnim(boolean cancel) {
if (mRunningWindowAnim != null) {
- mRunningWindowAnim.end();
+ if (cancel) {
+ mRunningWindowAnim.cancel();
+ } else {
+ mRunningWindowAnim.end();
+ }
}
}
@@ -976,7 +786,7 @@ public class WindowTransformSwipeHandler
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
if (endTarget == RECENTS && mMode != Mode.NO_BUTTON) {
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
- startShift, endShift, endShift, velocityPxPerMs.y,
+ startShift, endShift, endShift, endVelocity / 1000,
mTransitionDragLength);
endShift = overshoot.end;
interpolator = overshoot.interpolator;
@@ -1152,57 +962,15 @@ public class WindowTransformSwipeHandler
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
* @param homeAnimationFactory The home animation factory.
*/
- private RectFSpringAnim createWindowAnimationToHome(float startProgress,
+ @Override
+ protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
HomeAnimationFactory homeAnimationFactory) {
- final RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet;
- final RectF startRect = new RectF(mClipAnimationHelper.applyTransform(targetSet,
- mTransformParams.setProgress(startProgress), false /* launcherOnTop */));
- final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
-
- final View floatingView = homeAnimationFactory.getFloatingView();
- final boolean isFloatingIconView = floatingView instanceof FloatingIconView;
- RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mActivity.getResources());
- if (isFloatingIconView) {
- FloatingIconView fiv = (FloatingIconView) floatingView;
- anim.addAnimatorListener(fiv);
- fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
- }
-
- AnimatorPlaybackController homeAnim = homeAnimationFactory.createActivityAnimationToHome();
-
- // End on a "round-enough" radius so that the shape reveal doesn't have to do too much
- // rounding at the end of the animation.
- float startRadius = mClipAnimationHelper.getCurrentCornerRadius();
- float endRadius = startRect.width() / 6f;
- // We want the window alpha to be 0 once this threshold is met, so that the
- // FolderIconView can be seen morphing into the icon shape.
- final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f;
- anim.addOnUpdateListener((currentRect, progress) -> {
- homeAnim.setPlayFraction(progress);
-
- float alphaProgress = ACCEL_1_5.getInterpolation(progress);
- float windowAlpha = Utilities.boundToRange(Utilities.mapToRange(alphaProgress, 0,
- windowAlphaThreshold, 1.5f, 0f, Interpolators.LINEAR), 0, 1);
- mTransformParams.setProgress(progress)
- .setCurrentRectAndTargetAlpha(currentRect, windowAlpha);
- if (isFloatingIconView) {
- mTransformParams.setCornerRadius(endRadius * progress + startRadius
- * (1f - progress));
- }
- mClipAnimationHelper.applyTransform(targetSet, mTransformParams,
- false /* launcherOnTop */);
-
- if (isFloatingIconView) {
- ((FloatingIconView) floatingView).update(currentRect, 1f, progress,
- windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false);
- }
-
- updateSysUiFlags(Math.max(progress, mCurrentShift.value));
- });
+ RectFSpringAnim anim =
+ super.createWindowAnimationToHome(startProgress, homeAnimationFactory);
+ anim.addOnUpdateListener((r, p) -> updateSysUiFlags(Math.max(p, mCurrentShift.value)));
anim.addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
- homeAnim.dispatchOnStart();
if (mActivity != null) {
mActivity.getRootView().getOverlay().remove(mLiveTileOverlay);
}
@@ -1210,7 +978,6 @@ public class WindowTransformSwipeHandler
@Override
public void onAnimationSuccess(Animator animator) {
- homeAnim.getAnimationPlayer().end();
if (mRecentsView != null) {
mRecentsView.post(mRecentsView::resetTaskVisuals);
}
@@ -1222,11 +989,18 @@ public class WindowTransformSwipeHandler
return anim;
}
- /**
- * @return The GestureEndTarget if the gesture has ended, else null.
- */
- public @Nullable GestureEndTarget getGestureEndTarget() {
- return mGestureEndTarget;
+ @Override
+ public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
+ if (mGestureEndTarget != null) {
+ sharedState.canGestureBeContinued = mGestureEndTarget.canBeContinued;
+ sharedState.goingToLauncher = mGestureEndTarget.isLauncher;
+ }
+
+ if (sharedState.canGestureBeContinued) {
+ cancelCurrentAnimation(sharedState);
+ } else {
+ reset();
+ }
}
@UiThread
@@ -1239,43 +1013,18 @@ public class WindowTransformSwipeHandler
@UiThread
private void startNewTask() {
- // Launch the task user scrolled to (mRecentsView.getNextPage()).
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- // We finish recents animation inside launchTask() when live tile is enabled.
- mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false /* animate */,
- true /* freezeTaskList */);
- } else {
- int taskId = mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).getTask().key.id;
- mFinishingRecentsAnimationForNewTaskId = taskId;
- mRecentsAnimationWrapper.finish(true /* toRecents */, () -> {
- if (!mCanceled) {
- TaskView nextTask = mRecentsView.getTaskView(taskId);
- if (nextTask != null) {
- nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
- success -> {
- if (!success) {
- // We couldn't launch the task, so take user to overview so they can
- // decide what to do instead of staying in this broken state.
- endLauncherTransitionController();
- mActivityControlHelper.onLaunchTaskFailed(mActivity);
- nextTask.notifyTaskLaunchFailed(TAG);
- updateSysUiFlags(1 /* windowProgress == overview */);
- } else {
- mActivityControlHelper.onLaunchTaskSuccess(mActivity);
- }
- }, mMainThreadHandler);
- doLogGesture(NEW_TASK);
- }
- reset();
- }
- mCanceled = false;
- mFinishingRecentsAnimationForNewTaskId = -1;
- });
- }
- TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
+ startNewTask(STATE_HANDLER_INVALIDATED, success -> {
+ if (!success) {
+ // We couldn't launch the task, so take user to overview so they can
+ // decide what to do instead of staying in this broken state.
+ endLauncherTransitionController();
+ updateSysUiFlags(1 /* windowProgress == overview */);
+ }
+ doLogGesture(NEW_TASK);
+ });
}
- public void reset() {
+ private void reset() {
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
@@ -1283,7 +1032,7 @@ public class WindowTransformSwipeHandler
* Cancels any running animation so that the active target can be overriden by a new swipe
* handle (in case of quick switch).
*/
- public void cancelCurrentAnimation(SwipeSharedState sharedState) {
+ private void cancelCurrentAnimation(SwipeSharedState sharedState) {
mCanceled = true;
mCurrentShift.cancelAnimation();
if (mLauncherTransitionController != null && mLauncherTransitionController
@@ -1306,7 +1055,7 @@ public class WindowTransformSwipeHandler
}
private void invalidateHandler() {
- endRunningWindowAnim();
+ endRunningWindowAnim(false /* cancel */);
if (mGestureEndCallback != null) {
mGestureEndCallback.run();
@@ -1446,17 +1195,12 @@ public class WindowTransformSwipeHandler
reset();
}
- public void setGestureEndCallback(Runnable gestureEndCallback) {
- mGestureEndCallback = gestureEndCallback;
- }
-
- private void setTargetAlphaProvider(
- BiFunction provider) {
+ private void setTargetAlphaProvider(TargetAlphaProvider provider) {
mClipAnimationHelper.setTaskAlphaCallback(provider);
updateFinalShift();
}
- public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, Float expectedAlpha) {
+ public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, float expectedAlpha) {
if (!isNotInRecents(app)) {
return 0;
}
@@ -1467,16 +1211,4 @@ public class WindowTransformSwipeHandler
return app.isNotInRecents
|| app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
}
-
- private interface RunningWindowAnim {
- void end();
-
- static RunningWindowAnim wrap(Animator animator) {
- return animator::end;
- }
-
- static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) {
- return rectFSpringAnim::end;
- }
- }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index c28761804b..2e9c0a3c4d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -17,6 +17,7 @@ package com.android.quickstep.fallback;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -31,6 +32,10 @@ import com.android.quickstep.RecentsActivity;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
+
+import java.util.ArrayList;
public class FallbackRecentsView extends RecentsView {
@@ -54,6 +59,8 @@ public class FallbackRecentsView extends RecentsView {
private float mZoomScale = 1f;
private float mZoomTranslationY = 0f;
+ private RunningTaskInfo mRunningTaskInfo;
+
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -87,6 +94,12 @@ public class FallbackRecentsView extends RecentsView {
super.draw(canvas);
}
+ @Override
+ public void reset() {
+ super.reset();
+ resetViewUI();
+ }
+
@Override
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect);
@@ -114,6 +127,12 @@ public class FallbackRecentsView extends RecentsView {
}
}
+ @Override
+ public void resetTaskVisuals() {
+ super.resetTaskVisuals();
+ setFullscreenProgress(mFullscreenProgress);
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -139,4 +158,41 @@ public class FallbackRecentsView extends RecentsView {
TRANSLATION_Y.set(this, Utilities.mapRange(mZoomInProgress, 0, mZoomTranslationY));
FULLSCREEN_PROGRESS.set(this, mZoomInProgress);
}
+
+ public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
+ mRunningTaskInfo = runningTaskInfo;
+ onGestureAnimationStart(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
+ }
+
+ @Override
+ public void setCurrentTask(int runningTaskId) {
+ super.setCurrentTask(runningTaskId);
+ if (mRunningTaskInfo != null && mRunningTaskInfo.taskId != runningTaskId) {
+ mRunningTaskInfo = null;
+ }
+ }
+
+ @Override
+ protected void applyLoadPlan(ArrayList tasks) {
+ // When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
+ // as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
+ // track the index of the next task appropriately, as it we are switching on any other app.
+ if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
+ // Check if the task list has running task
+ boolean found = false;
+ for (Task t : tasks) {
+ if (t.key.id == mRunningTaskId) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ArrayList newList = new ArrayList<>(tasks.size() + 1);
+ newList.addAll(tasks);
+ newList.add(Task.from(new TaskKey(mRunningTaskInfo), mRunningTaskInfo, false));
+ tasks = newList;
+ }
+ }
+ super.applyLoadPlan(tasks);
+ }
}
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 db2af59aca..3d763ab52c 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
@@ -23,6 +23,7 @@ import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
+import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
import android.content.ComponentName;
import android.content.Context;
@@ -44,8 +45,6 @@ import com.android.quickstep.SwipeSharedState;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -209,9 +208,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
mInputMonitorCompat.pilferPointers();
- BackgroundExecutor.get().submit(
- () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
- intent, null, newListenerSet, null, null));
+ startRecentsActivityAsync(intent, newListenerSet);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index d05ca2a161..631c34c22d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -15,344 +15,441 @@
*/
package com.android.quickstep.inputconsumers;
-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.quickstep.WindowTransformSwipeHandler.MAX_SWIPE_DURATION;
+import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
+import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
+import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
-import static com.android.quickstep.WindowTransformSwipeHandler.MIN_SWIPE_DURATION;
-import static com.android.quickstep.inputconsumers.OtherActivityInputConsumer.QUICKSTEP_TOUCH_SLOP_RATIO;
-import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.HOME;
+import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.LAST_TASK;
+import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.NEW_TASK;
+import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS;
+import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
+import android.animation.AnimatorSet;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.graphics.RectF;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.ViewConfiguration;
-import android.view.WindowManager;
+import android.os.Bundle;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
-import com.android.quickstep.ActivityControlHelper;
+import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
+import com.android.quickstep.AnimatedFloat;
+import com.android.quickstep.BaseSwipeUpHandler;
+import com.android.quickstep.MultiStateCallback;
import com.android.quickstep.OverviewComponentObserver;
+import com.android.quickstep.RecentsActivity;
+import com.android.quickstep.RecentsModel;
import com.android.quickstep.SwipeSharedState;
-import com.android.quickstep.util.ClipAnimationHelper;
-import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
-import com.android.quickstep.util.NavBarPosition;
-import com.android.quickstep.util.RecentsAnimationListenerSet;
+import com.android.quickstep.fallback.FallbackRecentsView;
+import com.android.quickstep.util.ObjectWrapper;
+import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SwipeAnimationTargetSet;
-import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
+import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.BackgroundExecutor;
-import com.android.systemui.shared.system.InputMonitorCompat;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.ActivityOptionsCompat;
+import com.android.systemui.shared.system.InputConsumerController;
-public class FallbackNoButtonInputConsumer implements InputConsumer, SwipeAnimationListener {
+public class FallbackNoButtonInputConsumer extends
+ BaseSwipeUpHandler {
- private static final int STATE_NOT_FINISHED = 0;
- private static final int STATE_FINISHED_TO_HOME = 1;
- private static final int STATE_FINISHED_TO_APP = 2;
+ private static final String[] STATE_NAMES = DEBUG_STATES ? new String[5] : null;
- private static final float PROGRESS_TO_END_GESTURE = -2;
+ private static int getFlagForIndex(int index, String name) {
+ if (DEBUG_STATES) {
+ STATE_NAMES[index] = name;
+ }
+ return 1 << index;
+ }
- private final ActivityControlHelper mActivityControlHelper;
- private final InputMonitorCompat mInputMonitor;
- private final Context mContext;
- private final NavBarPosition mNavBarPosition;
- private final SwipeSharedState mSwipeSharedState;
- private final OverviewComponentObserver mOverviewComponentObserver;
- private final int mRunningTaskId;
+ private static final int STATE_RECENTS_PRESENT =
+ getFlagForIndex(0, "STATE_RECENTS_PRESENT");
+ private static final int STATE_HANDLER_INVALIDATED =
+ getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
- private final ClipAnimationHelper mClipAnimationHelper;
- private final TransformParams mTransformParams = new TransformParams();
- private final float mTransitionDragLength;
- private final DeviceProfile mDP;
+ private static final int STATE_GESTURE_CANCELLED =
+ getFlagForIndex(2, "STATE_GESTURE_CANCELLED");
+ private static final int STATE_GESTURE_COMPLETED =
+ getFlagForIndex(3, "STATE_GESTURE_COMPLETED");
+ private static final int STATE_APP_CONTROLLER_RECEIVED =
+ getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
- private final RectF mSwipeTouchRegion;
- private final boolean mDisableHorizontalSwipe;
+ public enum GestureEndTarget {
+ HOME(3, 100, 1),
+ RECENTS(1, 300, 0),
+ LAST_TASK(0, 150, 1),
+ NEW_TASK(0, 150, 1);
- private final PointF mDownPos = new PointF();
- private final PointF mLastPos = new PointF();
+ private final float mEndProgress;
+ private final long mDurationMultiplier;
+ private final float mLauncherAlpha;
- private int mActivePointerId = -1;
- // Slop used to determine when we say that the gesture has started.
- private boolean mPassedPilferInputSlop;
+ GestureEndTarget(float endProgress, long durationMultiplier, float launcherAlpha) {
+ mEndProgress = endProgress;
+ mDurationMultiplier = durationMultiplier;
+ mLauncherAlpha = launcherAlpha;
+ }
+ }
- private VelocityTracker mVelocityTracker;
+ private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
- // Distance after which we start dragging the window.
- private final float mTouchSlop;
+ private boolean mIsMotionPaused = false;
+ private GestureEndTarget mEndTarget;
- // Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
- private float mStartDisplacement;
- private SwipeAnimationTargetSet mSwipeAnimationTargetSet;
- private float mProgress;
+ private final boolean mInQuickSwitchMode;
+ private final boolean mContinuingLastGesture;
+ private final boolean mRunningOverHome;
+ private final boolean mSwipeUpOverHome;
- private int mState = STATE_NOT_FINISHED;
+ private final RunningTaskInfo mRunningTaskInfo;
+
+ private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
+ private RunningWindowAnim mFinishAnimation;
public FallbackNoButtonInputConsumer(Context context,
- ActivityControlHelper activityControlHelper, InputMonitorCompat inputMonitor,
- SwipeSharedState swipeSharedState, RectF swipeTouchRegion,
OverviewComponentObserver overviewComponentObserver,
- boolean disableHorizontalSwipe, RunningTaskInfo runningTaskInfo) {
- mContext = context;
- mActivityControlHelper = activityControlHelper;
- mInputMonitor = inputMonitor;
- mOverviewComponentObserver = overviewComponentObserver;
- mRunningTaskId = runningTaskInfo.id;
+ RunningTaskInfo runningTaskInfo, RecentsModel recentsModel,
+ InputConsumerController inputConsumer,
+ boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
+ super(context, overviewComponentObserver, recentsModel, inputConsumer, runningTaskInfo.id);
+ mLauncherAlpha.value = 1;
- mSwipeSharedState = swipeSharedState;
- mSwipeTouchRegion = swipeTouchRegion;
- mDisableHorizontalSwipe = disableHorizontalSwipe;
+ mRunningTaskInfo = runningTaskInfo;
+ mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
+ mContinuingLastGesture = continuingLastGesture;
+ mRunningOverHome = ActivityManagerWrapper.isHomeTask(runningTaskInfo);
+ mSwipeUpOverHome = mRunningOverHome && !mInQuickSwitchMode;
- mNavBarPosition = new NavBarPosition(context);
- mVelocityTracker = VelocityTracker.obtain();
-
- mTouchSlop = QUICKSTEP_TOUCH_SLOP_RATIO
- * ViewConfiguration.get(context).getScaledTouchSlop();
-
- mClipAnimationHelper = new ClipAnimationHelper(context);
-
- mDP = InvariantDeviceProfile.INSTANCE.get(context).getDeviceProfile(context).copy(context);
- Rect tempRect = new Rect();
- mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
- mDP, context, tempRect);
- mClipAnimationHelper.updateTargetRect(tempRect);
- }
-
- @Override
- public int getType() {
- return TYPE_FALLBACK_NO_BUTTON;
- }
-
- @Override
- public void onMotionEvent(MotionEvent ev) {
- if (mVelocityTracker == null) {
- return;
- }
-
- mVelocityTracker.addMovement(ev);
- if (ev.getActionMasked() == ACTION_POINTER_UP) {
- mVelocityTracker.clear();
- }
-
- switch (ev.getActionMasked()) {
- case ACTION_DOWN: {
- mActivePointerId = ev.getPointerId(0);
- mDownPos.set(ev.getX(), ev.getY());
- mLastPos.set(mDownPos);
- break;
- }
- case ACTION_POINTER_DOWN: {
- if (!mPassedPilferInputSlop) {
- // Cancel interaction in case of multi-touch interaction
- int ptrIdx = ev.getActionIndex();
- if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) {
- forceCancelGesture(ev);
- }
- }
- break;
- }
- case ACTION_POINTER_UP: {
- int ptrIdx = ev.getActionIndex();
- int ptrId = ev.getPointerId(ptrIdx);
- if (ptrId == mActivePointerId) {
- final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
- mDownPos.set(
- ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
- ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
- mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
- mActivePointerId = ev.getPointerId(newPointerIdx);
- }
- break;
- }
- case ACTION_MOVE: {
- int pointerIndex = ev.findPointerIndex(mActivePointerId);
- if (pointerIndex == INVALID_POINTER_ID) {
- break;
- }
- mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
- float displacement = getDisplacement(ev);
-
- if (!mPassedPilferInputSlop) {
- if (mDisableHorizontalSwipe && Math.abs(mLastPos.x - mDownPos.x)
- > Math.abs(mLastPos.y - mDownPos.y)) {
- // Horizontal gesture is not allowed in this region
- forceCancelGesture(ev);
- break;
- }
-
- if (Math.abs(displacement) >= mTouchSlop) {
- mPassedPilferInputSlop = true;
-
- // Deferred gesture, start the animation and gesture tracking once
- // we pass the actual touch slop
- startTouchTrackingForWindowAnimation(displacement);
- }
- } else {
- updateDisplacement(displacement - mStartDisplacement);
- }
- break;
- }
- case ACTION_CANCEL:
- case ACTION_UP: {
- finishTouchTracking(ev);
- break;
- }
- }
- }
-
- private void startTouchTrackingForWindowAnimation(float displacement) {
- mStartDisplacement = Math.min(displacement, -mTouchSlop);
-
- RecentsAnimationListenerSet listenerSet =
- mSwipeSharedState.newRecentsAnimationListenerSet();
- listenerSet.addListener(this);
- Intent homeIntent = mOverviewComponentObserver.getHomeIntent();
- BackgroundExecutor.get().submit(
- () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
- homeIntent, null, listenerSet, null, null));
-
- ActivityManagerWrapper.getInstance().closeSystemWindows(
- CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- mInputMonitor.pilferPointers();
- }
-
- private void updateDisplacement(float displacement) {
- mProgress = displacement / mTransitionDragLength;
- mTransformParams.setProgress(mProgress);
-
- if (mSwipeAnimationTargetSet != null) {
- mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
- }
- }
-
- private void forceCancelGesture(MotionEvent ev) {
- int action = ev.getAction();
- ev.setAction(ACTION_CANCEL);
- finishTouchTracking(ev);
- ev.setAction(action);
- }
-
- /**
- * Called when the gesture has ended. Does not correlate to the completion of the interaction as
- * the animation can still be running.
- */
- private void finishTouchTracking(MotionEvent ev) {
- if (ev.getAction() == ACTION_CANCEL) {
- mState = STATE_FINISHED_TO_APP;
+ if (mSwipeUpOverHome) {
+ mClipAnimationHelper.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
+ } else {
+ mClipAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
+ }
+
+ initStateCallbacks();
+ }
+
+ private void initStateCallbacks() {
+ mStateCallback = new MultiStateCallback(STATE_NAMES);
+
+ mStateCallback.addCallback(STATE_HANDLER_INVALIDATED,
+ this::onHandlerInvalidated);
+ mStateCallback.addCallback(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
+ this::onHandlerInvalidatedWithRecents);
+
+ mStateCallback.addCallback(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
+ this::finishAnimationTargetSetAnimationComplete);
+
+ if (mInQuickSwitchMode) {
+ mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
+ | STATE_RECENTS_PRESENT,
+ this::finishAnimationTargetSet);
+ } else {
+ mStateCallback.addCallback(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
+ this::finishAnimationTargetSet);
+ }
+ }
+
+ private void onLauncherAlphaChanged() {
+ if (mRecentsAnimationWrapper.targetSet != null && mEndTarget == null) {
+ applyTransformUnchecked();
+ }
+ }
+
+ @Override
+ protected boolean onActivityInit(final RecentsActivity activity, Boolean alreadyOnHome) {
+ mActivity = activity;
+ mRecentsView = activity.getOverviewPanel();
+ linkRecentsViewScroll();
+ mRecentsView.setDisallowScrollToClearAll(true);
+ mRecentsView.getClearAllButton().setVisibilityAlpha(0);
+
+ mRecentsView.setZoomProgress(1);
+
+ if (!mContinuingLastGesture) {
+ if (mRunningOverHome) {
+ mRecentsView.onGestureAnimationStart(mRunningTaskInfo);
+ } else {
+ mRecentsView.onGestureAnimationStart(mRunningTaskId);
+ }
+ }
+ setStateOnUiThread(STATE_RECENTS_PRESENT);
+ return true;
+ }
+
+ @Override
+ protected boolean moveWindowWithRecentsScroll() {
+ return mInQuickSwitchMode;
+ }
+
+ @Override
+ public void initWhenReady() {
+ if (mInQuickSwitchMode) {
+ // Only init if we are in quickswitch mode
+ super.initWhenReady();
+ }
+ }
+
+ @Override
+ public void updateDisplacement(float displacement) {
+ if (!mInQuickSwitchMode) {
+ super.updateDisplacement(displacement);
+ }
+ }
+
+ @Override
+ protected InputConsumer createNewInputProxyHandler() {
+ // Just consume all input on the active task
+ return InputConsumer.NO_OP;
+ }
+
+ @Override
+ public void onMotionPauseChanged(boolean isPaused) {
+ if (!mInQuickSwitchMode) {
+ mIsMotionPaused = isPaused;
+ mLauncherAlpha.animateToValue(mLauncherAlpha.value, isPaused ? 0 : 1)
+ .setDuration(150).start();
+ performHapticFeedback();
+ }
+ }
+
+ @Override
+ public Intent getLaunchIntent() {
+ if (mInQuickSwitchMode || mSwipeUpOverHome) {
+ return mOverviewComponentObserver.getOverviewIntent();
+ } else {
+ return mOverviewComponentObserver.getHomeIntent();
+ }
+ }
+
+ @Override
+ public void updateFinalShift() {
+ mTransformParams.setProgress(mCurrentShift.value);
+ mRecentsAnimationWrapper.setWindowThresholdCrossed(!mInQuickSwitchMode
+ && (mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD));
+ if (mRecentsAnimationWrapper.targetSet != null) {
+ applyTransformUnchecked();
+ }
+ }
+
+ @Override
+ public void onGestureCancelled() {
+ updateDisplacement(0);
+ mEndTarget = LAST_TASK;
+ setStateOnUiThread(STATE_GESTURE_CANCELLED);
+ }
+
+ @Override
+ public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
+ mEndVelocityPxPerMs.set(0, velocity.y / 1000);
+ if (mInQuickSwitchMode) {
+ // For now set it to non-null, it will be reset before starting the animation
+ mEndTarget = LAST_TASK;
} else {
- mVelocityTracker.computeCurrentVelocity(1000,
- ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity());
- float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
- float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
- float velocity = mNavBarPosition.isRightEdge() ? velocityX
- : mNavBarPosition.isLeftEdge() ? -velocityX
- : velocityY;
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
- boolean isFling = Math.abs(velocity) > flingThreshold;
+ boolean isFling = Math.abs(endVelocity) > flingThreshold;
- boolean goingHome;
- if (!isFling) {
- goingHome = -mProgress >= MIN_PROGRESS_FOR_OVERVIEW;
+ if (isFling) {
+ mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
+ } else if (mIsMotionPaused) {
+ mEndTarget = RECENTS;
} else {
- goingHome = velocity < 0;
+ mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
+ }
+ }
+ setStateOnUiThread(STATE_GESTURE_COMPLETED);
+ }
+
+ @Override
+ public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
+ if (mInQuickSwitchMode && mEndTarget != null) {
+ sharedState.canGestureBeContinued = true;
+ sharedState.goingToLauncher = false;
+
+ mCanceled = true;
+ mCurrentShift.cancelAnimation();
+ if (mFinishAnimation != null) {
+ mFinishAnimation.cancel();
}
- if (goingHome) {
- mState = STATE_FINISHED_TO_HOME;
- } else {
- mState = STATE_FINISHED_TO_APP;
+ if (mRecentsView != null) {
+ if (mFinishingRecentsAnimationForNewTaskId != -1) {
+ TaskView newRunningTaskView = mRecentsView.getTaskView(
+ mFinishingRecentsAnimationForNewTaskId);
+ int newRunningTaskId = newRunningTaskView != null
+ ? newRunningTaskView.getTask().key.id
+ : -1;
+ mRecentsView.setCurrentTask(newRunningTaskId);
+ sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
+ }
+ mRecentsView.setOnScrollChangeListener(null);
+ }
+ } else {
+ setStateOnUiThread(STATE_HANDLER_INVALIDATED);
+ }
+ }
+
+ private void onHandlerInvalidated() {
+ mActivityInitListener.unregister();
+ if (mGestureEndCallback != null) {
+ mGestureEndCallback.run();
+ }
+ if (mFinishAnimation != null) {
+ mFinishAnimation.end();
+ }
+ }
+
+ private void onHandlerInvalidatedWithRecents() {
+ mRecentsView.onGestureAnimationEnd();
+ mRecentsView.setDisallowScrollToClearAll(false);
+ mRecentsView.getClearAllButton().setVisibilityAlpha(1);
+ }
+
+ private void finishAnimationTargetSetAnimationComplete() {
+ switch (mEndTarget) {
+ case HOME: {
+ if (mSwipeUpOverHome) {
+ mRecentsAnimationWrapper.finish(false, null, false);
+ // Send a home intent to clear the task stack
+ mContext.startActivity(mOverviewComponentObserver.getHomeIntent());
+ } else {
+ mRecentsAnimationWrapper.finish(true, null, true);
+ }
+ break;
+ }
+ case LAST_TASK:
+ mRecentsAnimationWrapper.finish(false, null, false);
+ break;
+ case RECENTS: {
+ if (mSwipeUpOverHome) {
+ mRecentsAnimationWrapper.finish(true, null, true);
+ break;
+ }
+
+ ThumbnailData thumbnail =
+ mRecentsAnimationWrapper.targetSet.controller.screenshotTask(mRunningTaskId);
+ mRecentsAnimationWrapper.setCancelWithDeferredScreenshot(true);
+
+ ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
+ ActivityOptionsCompat.setFreezeRecentTasksList(options);
+
+ Bundle extras = new Bundle();
+ extras.putBinder(EXTRA_THUMBNAIL, new ObjectWrapper<>(thumbnail));
+ extras.putInt(EXTRA_TASK_ID, mRunningTaskId);
+
+ Intent intent = new Intent(mOverviewComponentObserver.getOverviewIntent())
+ .putExtras(extras);
+ mContext.startActivity(intent, options.toBundle());
+ mRecentsAnimationWrapper.targetSet.controller.cleanupScreenshot();
+ break;
+ }
+ case NEW_TASK: {
+ startNewTask(STATE_HANDLER_INVALIDATED, b -> {});
+ break;
}
}
- if (mSwipeAnimationTargetSet != null) {
- finishAnimationTargetSet();
- }
+ setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
private void finishAnimationTargetSet() {
- if (mState == STATE_FINISHED_TO_APP) {
- mSwipeAnimationTargetSet.finishController(false, null, false);
- } else {
- if (mProgress < PROGRESS_TO_END_GESTURE) {
- mSwipeAnimationTargetSet.finishController(true, null, true);
+ if (mInQuickSwitchMode) {
+ // Recalculate the end target, some views might have been initialized after
+ // gesture has ended.
+ if (mRecentsView == null || !mRecentsAnimationWrapper.hasTargets()) {
+ mEndTarget = LAST_TASK;
} else {
- long duration = (long) (Math.min(mProgress - PROGRESS_TO_END_GESTURE, 1)
- * MAX_SWIPE_DURATION / Math.abs(PROGRESS_TO_END_GESTURE));
- if (duration < 0) {
- duration = MIN_SWIPE_DURATION;
- }
-
- ValueAnimator anim = ValueAnimator.ofFloat(mProgress, PROGRESS_TO_END_GESTURE);
- anim.addUpdateListener(a -> {
- float p = (Float) anim.getAnimatedValue();
- mTransformParams.setProgress(p);
- mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
- });
- anim.setDuration(duration);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mSwipeAnimationTargetSet.finishController(true, null, true);
- }
- });
- anim.start();
+ final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
+ final int taskToLaunch = mRecentsView.getNextPage();
+ mEndTarget = (runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
+ ? NEW_TASK : LAST_TASK;
}
}
+
+ float endProgress = mEndTarget.mEndProgress;
+ long duration = (long) (mEndTarget.mDurationMultiplier *
+ Math.abs(endProgress - mCurrentShift.value));
+ if (mRecentsView != null) {
+ duration = Math.max(duration, mRecentsView.getScroller().getDuration());
+ }
+ if (mCurrentShift.value != endProgress || mInQuickSwitchMode) {
+ AnimationSuccessListener endListener = new AnimationSuccessListener() {
+
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ finishAnimationTargetSetAnimationComplete();
+ mFinishAnimation = null;
+ }
+ };
+
+ if (mEndTarget == HOME && !mRunningOverHome) {
+ RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration);
+ anim.addAnimatorListener(endListener);
+ anim.start(mEndVelocityPxPerMs);
+ mFinishAnimation = RunningWindowAnim.wrap(anim);
+ } else {
+
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(mLauncherAlpha.animateToValue(
+ mLauncherAlpha.value, mEndTarget.mLauncherAlpha));
+ anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
+
+ anim.setDuration(duration);
+ anim.addListener(endListener);
+ anim.start();
+ mFinishAnimation = RunningWindowAnim.wrap(anim);
+ }
+
+ } else {
+ finishAnimationTargetSetAnimationComplete();
+ }
}
@Override
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
- mSwipeAnimationTargetSet = targetSet;
- Rect overviewStackBounds = new Rect(0, 0, mDP.widthPx, mDP.heightPx);
- RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
+ super.onRecentsAnimationStart(targetSet);
+ mRecentsAnimationWrapper.enableInputConsumer();
- mDP.updateIsSeascape(mContext.getSystemService(WindowManager.class));
- if (runningTaskTarget != null) {
- mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
+ if (mRunningOverHome) {
+ mClipAnimationHelper.prepareAnimation(mDp, true);
}
- mClipAnimationHelper.prepareAnimation(mDP, false /* isOpening */);
+ applyTransformUnchecked();
- overviewStackBounds
- .inset(-overviewStackBounds.width() / 5, -overviewStackBounds.height() / 5);
- mClipAnimationHelper.updateTargetRect(overviewStackBounds);
- mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
-
- if (mState != STATE_NOT_FINISHED) {
- finishAnimationTargetSet();
- }
+ setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
}
@Override
- public void onRecentsAnimationCanceled() { }
-
- private float getDisplacement(MotionEvent ev) {
- if (mNavBarPosition.isRightEdge()) {
- return ev.getX() - mDownPos.x;
- } else if (mNavBarPosition.isLeftEdge()) {
- return mDownPos.x - ev.getX();
- } else {
- return ev.getY() - mDownPos.y;
- }
+ public void onRecentsAnimationCanceled() {
+ mRecentsAnimationWrapper.setController(null);
+ setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
- @Override
- public boolean allowInterceptByParent() {
- return !mPassedPilferInputSlop;
+ /**
+ * Creates an animation that transforms the current app window into the home app.
+ * @param startProgress The progress of {@link #mCurrentShift} to start the window from.
+ */
+ private RectFSpringAnim createWindowAnimationToHome(float startProgress, long duration) {
+ HomeAnimationFactory factory = new HomeAnimationFactory() {
+ @Override
+ public RectF getWindowTargetRect() {
+ return HomeAnimationFactory.getDefaultWindowTargetRect(mDp);
+ }
+
+ @Override
+ public AnimatorPlaybackController createActivityAnimationToHome() {
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(mLauncherAlpha.animateToValue(mLauncherAlpha.value, 1));
+ anim.setDuration(duration);
+ return AnimatorPlaybackController.wrap(anim, duration);
+ }
+ };
+ return createWindowAnimationToHome(startProgress, factory);
}
}
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 f5cf654b15..a1e5d47a53 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
@@ -33,7 +33,6 @@ public interface InputConsumer {
int TYPE_SCREEN_PINNED = 1 << 6;
int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
int TYPE_RESET_GESTURE = 1 << 8;
- int TYPE_FALLBACK_NO_BUTTON = 1 << 9;
String[] NAMES = new String[] {
"TYPE_NO_OP", // 0
@@ -45,7 +44,6 @@ public interface InputConsumer {
"TYPE_SCREEN_PINNED", // 6
"TYPE_OVERVIEW_WITHOUT_FOCUS", // 7
"TYPE_RESET_GESTURE", // 8
- "TYPE_FALLBACK_NO_BUTTON", // 9
};
InputConsumer NO_OP = () -> TYPE_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 4c137d3bf9..86766d99fb 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
@@ -28,13 +28,13 @@ import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
+import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.ContextWrapper;
-import android.content.Intent;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
@@ -48,21 +48,16 @@ import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
-import com.android.quickstep.ActivityControlHelper;
+import com.android.quickstep.BaseSwipeUpHandler;
import com.android.quickstep.OverviewCallbacks;
-import com.android.quickstep.RecentsModel;
import com.android.quickstep.SwipeSharedState;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.quickstep.WindowTransformSwipeHandler;
-import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget;
import com.android.quickstep.util.CachedEventDispatcher;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.BackgroundExecutor;
-import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import java.util.function.Consumer;
@@ -83,16 +78,14 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final RunningTaskInfo mRunningTask;
- private final RecentsModel mRecentsModel;
- private final Intent mHomeIntent;
- private final ActivityControlHelper mActivityControlHelper;
private final OverviewCallbacks mOverviewCallbacks;
- private final InputConsumerController mInputConsumer;
private final SwipeSharedState mSwipeSharedState;
private final InputMonitorCompat mInputMonitorCompat;
private final SysUINavigationMode.Mode mMode;
private final RectF mSwipeTouchRegion;
+ private final BaseSwipeUpHandler.Factory mHandlerFactory;
+
private final NavBarPosition mNavBarPosition;
private final Consumer mOnCompleteCallback;
@@ -100,7 +93,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final float mMotionPauseMinDisplacement;
private VelocityTracker mVelocityTracker;
- private WindowTransformSwipeHandler mInteractionHandler;
+ private BaseSwipeUpHandler mInteractionHandler;
private final boolean mIsDeferredDownTarget;
private final PointF mDownPos = new PointF();
@@ -114,7 +107,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final boolean mDisableHorizontalSwipe;
// Slop used to check when we start moving window.
- private boolean mPaddedWindowMoveSlop;
+ private boolean mPassedWindowMoveSlop;
// Slop used to determine when we say that the gesture has started.
private boolean mPassedPilferInputSlop;
@@ -128,20 +121,18 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
};
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
- RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl,
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
- InputConsumerController inputConsumer,
Consumer onCompleteCallback,
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
- RectF swipeTouchRegion, boolean disableHorizontalSwipe) {
+ RectF swipeTouchRegion, boolean disableHorizontalSwipe,
+ BaseSwipeUpHandler.Factory handlerFactory) {
super(base);
mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
- mRecentsModel = recentsModel;
- mHomeIntent = homeIntent;
mMode = SysUINavigationMode.getMode(base);
mSwipeTouchRegion = swipeTouchRegion;
+ mHandlerFactory = handlerFactory;
mMotionPauseDetector = new MotionPauseDetector(base);
mMotionPauseMinDisplacement = base.getResources().getDimension(
@@ -150,11 +141,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
mVelocityTracker = VelocityTracker.obtain();
mInputMonitorCompat = inputMonitorCompat;
- mActivityControlHelper = activityControl;
boolean continuingPreviousGesture = swipeSharedState.getActiveListener() != null;
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
mOverviewCallbacks = overviewCallbacks;
- mInputConsumer = inputConsumer;
mSwipeSharedState = swipeSharedState;
mNavBarPosition = new NavBarPosition(base);
@@ -163,7 +152,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
float slop = QUICKSTEP_TOUCH_SLOP_RATIO * mTouchSlop;
mSquaredTouchSlop = slop * slop;
- mPassedPilferInputSlop = mPaddedWindowMoveSlop = continuingPreviousGesture;
+ mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;
mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe;
}
@@ -186,7 +175,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
}
// Proxy events to recents view
- if (mPaddedWindowMoveSlop && mInteractionHandler != null
+ if (mPassedWindowMoveSlop && mInteractionHandler != null
&& !mRecentsViewDispatcher.hasConsumer()) {
mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
mNavBarPosition.getRotationMode()));
@@ -213,7 +202,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
// Start the window animation on down to give more time for launcher to draw if the
// user didn't start the gesture over the back button
if (!mIsDeferredDownTarget) {
- startTouchTrackingForWindowAnimation(ev.getEventTime());
+ startTouchTrackingForWindowAnimation(ev.getEventTime(), false);
}
RaceConditionTracker.onEvent(DOWN_EVT, EXIT);
@@ -251,17 +240,21 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
float displacement = getDisplacement(ev);
float displacementX = mLastPos.x - mDownPos.x;
- if (!mPaddedWindowMoveSlop) {
+ if (!mPassedWindowMoveSlop) {
if (!mIsDeferredDownTarget) {
// Normal gesture, ensure we pass the drag slop before we start tracking
// the gesture
if (Math.abs(displacement) > mTouchSlop) {
- mPaddedWindowMoveSlop = true;
+ mPassedWindowMoveSlop = true;
mStartDisplacement = Math.min(displacement, -mTouchSlop);
}
}
}
+ float horizontalDist = Math.abs(displacementX);
+ float upDist = -displacement;
+ boolean isLikelyToStartNewTask = horizontalDist > upDist;
+
if (!mPassedPilferInputSlop) {
float displacementY = mLastPos.y - mDownPos.y;
if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
@@ -277,10 +270,11 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
if (mIsDeferredDownTarget) {
// Deferred gesture, start the animation and gesture tracking once
// we pass the actual touch slop
- startTouchTrackingForWindowAnimation(ev.getEventTime());
+ startTouchTrackingForWindowAnimation(
+ ev.getEventTime(), isLikelyToStartNewTask);
}
- if (!mPaddedWindowMoveSlop) {
- mPaddedWindowMoveSlop = true;
+ if (!mPassedWindowMoveSlop) {
+ mPassedWindowMoveSlop = true;
mStartDisplacement = Math.min(displacement, -mTouchSlop);
}
@@ -289,15 +283,12 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
}
if (mInteractionHandler != null) {
- if (mPaddedWindowMoveSlop) {
+ if (mPassedWindowMoveSlop) {
// Move
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
}
if (mMode == Mode.NO_BUTTON) {
- float horizontalDist = Math.abs(displacementX);
- float upDist = -displacement;
- boolean isLikelyToStartNewTask = horizontalDist > upDist;
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|| isLikelyToStartNewTask);
mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
@@ -329,16 +320,14 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
mInteractionHandler.onGestureStarted();
}
- private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
+ private void startTouchTrackingForWindowAnimation(
+ long touchTimeMs, boolean isLikelyToStartNewTask) {
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation");
RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener();
- final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
- mRunningTask, this, touchTimeMs, mActivityControlHelper,
- listenerSet != null, mInputConsumer);
+ final BaseSwipeUpHandler handler = mHandlerFactory.newHandler(mRunningTask, touchTimeMs,
+ listenerSet != null, isLikelyToStartNewTask);
- // Preload the plan
- mRecentsModel.getTasks(null);
mInteractionHandler = handler;
handler.setGestureEndCallback(this::onInteractionGestureFinished);
mMotionPauseDetector.setOnMotionPauseListener(handler::onMotionPauseChanged);
@@ -352,9 +341,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
RecentsAnimationListenerSet newListenerSet =
mSwipeSharedState.newRecentsAnimationListenerSet();
newListenerSet.addListener(handler);
- BackgroundExecutor.get().submit(
- () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
- mHomeIntent, null, newListenerSet, null, null));
+ startRecentsActivityAsync(handler.getLaunchIntent(), newListenerSet);
}
}
@@ -366,7 +353,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
RaceConditionTracker.onEvent(UP_EVT, ENTER);
TraceHelper.endSection("TouchInt");
- if (mPaddedWindowMoveSlop && mInteractionHandler != null) {
+ if (mPassedWindowMoveSlop && mInteractionHandler != null) {
if (ev.getActionMasked() == ACTION_CANCEL) {
mInteractionHandler.onGestureCancelled();
} else {
@@ -409,14 +396,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
// The consumer is being switched while we are active. Set up the shared state to be
// used by the next animation
removeListener();
- GestureEndTarget endTarget = mInteractionHandler.getGestureEndTarget();
- mSwipeSharedState.canGestureBeContinued = endTarget != null && endTarget.canBeContinued;
- mSwipeSharedState.goingToLauncher = endTarget != null && endTarget.isLauncher;
- if (mSwipeSharedState.canGestureBeContinued) {
- mInteractionHandler.cancelCurrentAnimation(mSwipeSharedState);
- } else {
- mInteractionHandler.reset();
- }
+ mInteractionHandler.onConsumerAboutToBeSwitched(mSwipeSharedState);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index 12ea07eaff..581ab6d3ea 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -82,9 +82,6 @@ public class OverviewInputConsumer
@Override
public void onMotionEvent(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onMotionEvent " + ev);
- }
if (!mProxyTouch) {
return;
}
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 6dc672ecfa..90989feb4d 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
@@ -99,8 +99,8 @@ public class ClipAnimationHelper {
// Whether to boost the opening animation target layers, or the closing
private int mBoostModeTargetLayers = -1;
- private BiFunction mTaskAlphaCallback =
- (t, a1) -> a1;
+ private TargetAlphaProvider mTaskAlphaCallback = (t, a) -> a;
+ private TargetAlphaProvider mBaseAlphaCallback = (t, a) -> 1;
public ClipAnimationHelper(Context context) {
mWindowCornerRadius = getWindowCornerRadius(context.getResources());
@@ -119,8 +119,12 @@ public class ClipAnimationHelper {
}
public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
- mHomeStackBounds.set(homeStackBounds);
updateSourceStack(target);
+ updateHomeBounds(homeStackBounds);
+ }
+
+ public void updateHomeBounds(Rect homeStackBounds) {
+ mHomeStackBounds.set(homeStackBounds);
}
public void updateTargetRect(Rect targetRect) {
@@ -187,12 +191,12 @@ public class ClipAnimationHelper {
Rect crop = mTmpRect;
crop.set(app.sourceContainerBounds);
crop.offsetTo(0, 0);
- float alpha = 1f;
+ float alpha;
int layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
float cornerRadius = 0f;
float scale = Math.max(params.currentRect.width(), mTargetRect.width()) / crop.width();
if (app.mode == targetSet.targetMode) {
- alpha = mTaskAlphaCallback.apply(app, params.targetAlpha);
+ alpha = mTaskAlphaCallback.getAlpha(app, params.targetAlpha);
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL);
mTmpMatrix.postTranslate(app.position.x, app.position.y);
@@ -214,9 +218,12 @@ public class ClipAnimationHelper {
// home target.
alpha = 1 - (progress * params.targetAlpha);
}
- } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && launcherOnTop) {
- crop = null;
- layer = Integer.MAX_VALUE;
+ } else {
+ alpha = mBaseAlphaCallback.getAlpha(app, progress);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get() && launcherOnTop) {
+ crop = null;
+ layer = Integer.MAX_VALUE;
+ }
}
// Since radius is in Surface space, but we draw the rounded corners in screen space, we
@@ -247,11 +254,14 @@ public class ClipAnimationHelper {
}
}
- public void setTaskAlphaCallback(
- BiFunction callback) {
+ public void setTaskAlphaCallback(TargetAlphaProvider callback) {
mTaskAlphaCallback = callback;
}
+ public void setBaseAlphaCallback(TargetAlphaProvider callback) {
+ mBaseAlphaCallback = callback;
+ }
+
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) {
fromTaskThumbnailView(ttv, rv, null);
}
@@ -357,6 +367,10 @@ public class ClipAnimationHelper {
return mCurrentCornerRadius;
}
+ public interface TargetAlphaProvider {
+ float getAlpha(RemoteAnimationTargetCompat target, float expectedAlpha);
+ }
+
public static class TransformParams {
float progress;
public float offsetX;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ObjectWrapper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ObjectWrapper.java
new file mode 100644
index 0000000000..abfe3adbff
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ObjectWrapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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.os.Binder;
+import android.os.IBinder;
+
+/**
+ * Utility class to pass non-parcealable objects within same process using parcealable payload.
+ *
+ * It wraps the object in a binder as binders are singleton within a process
+ */
+public class ObjectWrapper extends Binder {
+
+ private final T mObject;
+
+ public ObjectWrapper(T object) {
+ mObject = object;
+ }
+
+ public T get() {
+ return mObject;
+ }
+
+ public static IBinder wrap(Object obj) {
+ return new ObjectWrapper<>(obj);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
index 77dc6f32e7..c6eafe6a64 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -225,7 +225,18 @@ public class RectFSpringAnim {
}
}
+ public void cancel() {
+ if (mAnimsStarted) {
+ for (OnUpdateListener onUpdateListener : mOnUpdateListeners) {
+ onUpdateListener.onCancel();
+ }
+ }
+ end();
+ }
+
public interface OnUpdateListener {
void onUpdate(RectF currentRect, float progress);
+
+ default void onCancel() { }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 07e96869ed..1705c9712a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -16,6 +16,8 @@
package com.android.quickstep.util;
import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.ViewGroup;
@@ -29,6 +31,7 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
+import com.android.launcher3.Workspace;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.SpringObjectAnimator;
@@ -79,9 +82,19 @@ public class StaggeredWorkspaceAnim {
.getDimensionPixelSize(R.dimen.swipe_up_max_workspace_trans_y);
DeviceProfile grid = launcher.getDeviceProfile();
- ShortcutAndWidgetContainer currentPage = ((CellLayout) launcher.getWorkspace()
- .getChildAt(launcher.getWorkspace().getCurrentPage()))
- .getShortcutsAndWidgets();
+ Workspace workspace = launcher.getWorkspace();
+ CellLayout cellLayout = (CellLayout) workspace.getChildAt(workspace.getCurrentPage());
+ ShortcutAndWidgetContainer currentPage = cellLayout.getShortcutsAndWidgets();
+
+ boolean workspaceClipChildren = workspace.getClipChildren();
+ boolean workspaceClipToPadding = workspace.getClipToPadding();
+ boolean cellLayoutClipChildren = cellLayout.getClipChildren();
+ boolean cellLayoutClipToPadding = cellLayout.getClipToPadding();
+
+ workspace.setClipChildren(false);
+ workspace.setClipToPadding(false);
+ cellLayout.setClipChildren(false);
+ cellLayout.setClipToPadding(false);
// Hotseat and QSB takes up two additional rows.
int totalRows = grid.inv.numRows + (grid.isVerticalBarLayout() ? 0 : 2);
@@ -111,6 +124,27 @@ public class StaggeredWorkspaceAnim {
addWorkspaceScrimAnimationForState(launcher, BACKGROUND_APP, 0);
addWorkspaceScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
+
+ AnimatorListener resetClipListener = new AnimatorListenerAdapter() {
+ int numAnimations = mAnimators.size();
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ numAnimations--;
+ if (numAnimations > 0) {
+ return;
+ }
+
+ workspace.setClipChildren(workspaceClipChildren);
+ workspace.setClipToPadding(workspaceClipToPadding);
+ cellLayout.setClipChildren(cellLayoutClipChildren);
+ cellLayout.setClipToPadding(cellLayoutClipToPadding);
+ }
+ };
+
+ for (Animator a : mAnimators) {
+ a.addListener(resetClipListener);
+ }
}
/**
@@ -134,10 +168,6 @@ public class StaggeredWorkspaceAnim {
* @param totalRows Total number of rows.
*/
private void addStaggeredAnimationForView(View v, int row, int totalRows) {
- if (v == mViewToIgnore) {
- return;
- }
-
// Invert the rows, because we stagger starting from the bottom of the screen.
int invertedRow = totalRows - row;
// Add 1 to the inverted row so that the bottom most row has a start delay.
@@ -149,6 +179,10 @@ public class StaggeredWorkspaceAnim {
springTransY.setStartDelay(startDelay);
mAnimators.add(springTransY);
+ if (v == mViewToIgnore) {
+ return;
+ }
+
v.setAlpha(0);
ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f);
alpha.setInterpolator(LINEAR);
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 6a9abd5455..b566837da6 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
@@ -37,6 +37,7 @@ import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch
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.TouchInteractionService.BACKGROUND_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -72,6 +73,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ListView;
@@ -108,7 +110,6 @@ import com.android.quickstep.util.ClipAnimationHelper;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.LauncherEventUtil;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
@@ -226,7 +227,7 @@ public abstract class RecentsView extends PagedView impl
return;
}
- BackgroundExecutor.get().submit(() -> {
+ BACKGROUND_EXECUTOR.execute(() -> {
TaskView taskView = getTaskView(taskId);
if (taskView == null) {
return;
@@ -269,7 +270,7 @@ public abstract class RecentsView extends PagedView impl
private int mTaskListChangeId = -1;
// Only valid until the launcher state changes to NORMAL
- private int mRunningTaskId = -1;
+ protected int mRunningTaskId = -1;
private boolean mRunningTaskTileHidden;
private Task mTmpRunningTask;
@@ -289,7 +290,7 @@ public abstract class RecentsView extends PagedView impl
@ViewDebug.ExportedProperty(category = "launcher")
private float mContentAlpha = 1;
@ViewDebug.ExportedProperty(category = "launcher")
- private float mFullscreenProgress = 0;
+ protected float mFullscreenProgress = 0;
// Keeps track of task id whose visual state should not be reset
private int mIgnoreResetTaskId = -1;
@@ -532,7 +533,7 @@ public abstract class RecentsView extends PagedView impl
return true;
}
- private void applyLoadPlan(ArrayList tasks) {
+ protected void applyLoadPlan(ArrayList tasks) {
if (mPendingAnimation != null) {
mPendingAnimation.addEndListener((onEndListener) -> applyLoadPlan(tasks));
return;
@@ -604,6 +605,7 @@ public abstract class RecentsView extends PagedView impl
TaskView taskView = (TaskView) getChildAt(i);
if (mIgnoreResetTaskId != taskView.getTask().key.id) {
taskView.resetVisualProperties();
+ taskView.setStableAlpha(mContentAlpha);
}
}
if (mRunningTaskTileHidden) {
@@ -854,12 +856,14 @@ public abstract class RecentsView extends PagedView impl
* is called. Also scrolls the view to this task.
*/
public void showCurrentTask(int runningTaskId) {
- if (getChildCount() == 0) {
+ if (getTaskView(runningTaskId) == null) {
+ boolean wasEmpty = getChildCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView = mTaskViewPool.getView();
- addView(taskView);
- addView(mClearAllButton);
-
+ addView(taskView, 0);
+ if (wasEmpty) {
+ addView(mClearAllButton);
+ }
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(),
@@ -1739,4 +1743,14 @@ public abstract class RecentsView extends PagedView impl
updateEnabledOverlays();
}
}
+
+ public int getLeftGestureMargin() {
+ final WindowInsets insets = getRootWindowInsets();
+ return Math.max(insets.getSystemGestureInsets().left, insets.getSystemWindowInsetLeft());
+ }
+
+ public int getRightGestureMargin() {
+ final WindowInsets insets = getRootWindowInsets();
+ return Math.max(insets.getSystemGestureInsets().right, insets.getSystemWindowInsetRight());
+ }
}
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 b26fdce92f..2211eb4dd7 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
@@ -192,9 +192,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
super(context, attrs, defStyleAttr);
mActivity = BaseDraggingActivity.fromContext(context);
setOnClickListener((view) -> {
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TASK_TAG, "TaskView onClick");
- }
if (getTask() == null) {
return;
}
@@ -291,9 +288,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
public void launchTask(boolean animate, boolean freezeTaskList, Consumer resultCallback,
Handler resultCallbackHandler) {
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TASK_TAG, "launchTask");
- }
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (isRunningTask()) {
getRecentsView().finishRecentsAnimation(false /* toRecents */,
@@ -308,9 +302,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
private void launchTaskInternal(boolean animate, boolean freezeTaskList,
Consumer resultCallback, Handler resultCallbackHandler) {
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TASK_TAG, "launchTaskInternal");
- }
if (mTask != null) {
final ActivityOptions opts;
if (animate) {
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 5394f495e9..01dcff202d 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -33,5 +33,5 @@
"Encore %1$s aujourd\'hui"
"Suggestions d\'applications"
"Toutes les applications"
- "Vos applications prévues"
+ "Applications prévues pour vous"
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 0467af4b2d..387d509587 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -27,7 +27,7 @@
"बंद करें"
"ऐप्लिकेशन इस्तेमाल की सेटिंग"
"सभी ऐप्लिकेशन बंद करें"
- "हाल ही में इस्तेमाल किए गए एेप्लिकेशन"
+ "हाल ही में इस्तेमाल किए गए ऐप्लिकेशन"
"%1$s, %2$s"
"<1 मिनट"
"आज %1$s और चलेगा"
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 1ca558a240..cccece749c 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -27,7 +27,7 @@
"बंद"
"अॅप वापर सेटिंग्ज"
"सर्व साफ करा"
- "अलीकडील अॅप्स"
+ "अलीकडील अॅप्स"
"%1$s, %2$s"
"१मिहून कमी"
"आज %1$sशिल्लक आहे"
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 6030cea938..109d751c48 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -51,7 +51,6 @@ import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.LayoutUtils;
-import com.android.systemui.shared.system.QuickStepContract;
/**
* Touch controller for handling various state transitions in portrait UI.
@@ -296,9 +295,13 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
* @return true if the event is over the hotseat
*/
static boolean isTouchOverHotseat(Launcher launcher, MotionEvent ev) {
+ return (ev.getY() >= getHotseatTop(launcher));
+ }
+
+ public static int getHotseatTop(Launcher launcher) {
DeviceProfile dp = launcher.getDeviceProfile();
int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
- return (ev.getY() >= (launcher.getDragLayer().getHeight() - hotseatHeight));
+ return launcher.getDragLayer().getHeight() - hotseatHeight;
}
private static class InterpolatorWrapper implements Interpolator {
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index cd2c9cb1bf..5c9c7d4cab 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -152,5 +152,15 @@ public interface ActivityControlHelper {
default void playAtomicAnimation(float velocity) {
// No-op
}
+
+ static RectF getDefaultWindowTargetRect(DeviceProfile dp) {
+ final int halfIconSize = dp.iconSizePx / 2;
+ final float targetCenterX = dp.availableWidthPx / 2f;
+ final float targetCenterY = dp.availableHeightPx - dp.hotseatBarSizePx;
+ // Fallback to animate to center of screen.
+ return new RectF(targetCenterX - halfIconSize, targetCenterY - halfIconSize,
+ targetCenterX + halfIconSize, targetCenterY + halfIconSize);
+ }
+
}
}
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
deleted file mode 100644
index 89513634fe..0000000000
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.android.quickstep;
-
-import android.content.Context;
-import android.os.Bundle;
-
-import com.android.launcher3.testing.TestInformationHandler;
-import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.uioverrides.states.OverviewState;
-import com.android.quickstep.util.LayoutUtils;
-
-public class QuickstepTestInformationHandler extends TestInformationHandler {
-
- public QuickstepTestInformationHandler(Context context) { }
-
- @Override
- public Bundle call(String method) {
- final Bundle response = new Bundle();
- switch (method) {
- case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
- final float swipeHeight =
- OverviewState.getDefaultSwipeHeight(mDeviceProfile);
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
- return response;
- }
-
- case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
- final float swipeHeight =
- LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile);
- response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
- return response;
- }
- }
-
- return super.call(method);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index f27ba85388..e41dba94cc 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -16,6 +16,8 @@
package com.android.quickstep;
+import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
+
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
@@ -25,10 +27,7 @@ import android.util.SparseBooleanArray;
import com.android.launcher3.MainThreadExecutor;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.KeyguardManagerCompat;
-import com.android.systemui.shared.system.RecentTaskInfoCompat;
-import com.android.systemui.shared.system.TaskDescriptionCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
import java.util.Collections;
@@ -43,7 +42,6 @@ public class RecentTasksList extends TaskStackChangeListener {
private final KeyguardManagerCompat mKeyguardManager;
private final MainThreadExecutor mMainThreadExecutor;
- private final BackgroundExecutor mBgThreadExecutor;
// The list change id, increments as the task list changes in the system
private int mChangeId;
@@ -56,7 +54,6 @@ public class RecentTasksList extends TaskStackChangeListener {
public RecentTasksList(Context context) {
mMainThreadExecutor = new MainThreadExecutor();
- mBgThreadExecutor = BackgroundExecutor.get();
mKeyguardManager = new KeyguardManagerCompat(context);
mChangeId = 1;
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
@@ -67,7 +64,7 @@ public class RecentTasksList extends TaskStackChangeListener {
*/
public void getTaskKeys(int numTasks, Consumer> callback) {
// Kick off task loading in the background
- mBgThreadExecutor.submit(() -> {
+ BACKGROUND_EXECUTOR.execute(() -> {
ArrayList tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
mMainThreadExecutor.execute(() -> callback.accept(tasks));
});
@@ -87,13 +84,14 @@ public class RecentTasksList extends TaskStackChangeListener {
: () -> callback.accept(copyOf(mTasks));
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
- // The list is up to date, callback with the same list
- mMainThreadExecutor.execute(resultCallback);
+ // The list is up to date, send the callback on the next frame,
+ // so that requestID can be returned first.
+ mMainThreadExecutor.getHandler().post(resultCallback);
return requestLoadId;
}
// Kick off task loading in the background
- mBgThreadExecutor.submit(() -> {
+ BACKGROUND_EXECUTOR.execute(() -> {
ArrayList tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);
mMainThreadExecutor.execute(() -> {
@@ -121,12 +119,7 @@ public class RecentTasksList extends TaskStackChangeListener {
@Override
public void onTaskRemoved(int taskId) {
- for (int i = mTasks.size() - 1; i >= 0; i--) {
- if (mTasks.get(i).key.id == taskId) {
- mTasks.remove(i);
- return;
- }
- }
+ mTasks = loadTasksInBackground(Integer.MAX_VALUE, false);
}
@Override
@@ -166,15 +159,11 @@ public class RecentTasksList extends TaskStackChangeListener {
int taskCount = rawTasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo rawTask = rawTasks.get(i);
- RecentTaskInfoCompat t = new RecentTaskInfoCompat(rawTask);
Task.TaskKey taskKey = new Task.TaskKey(rawTask);
Task task;
if (!loadKeysOnly) {
- ActivityManager.TaskDescription rawTd = t.getTaskDescription();
- TaskDescriptionCompat td = new TaskDescriptionCompat(rawTd);
- boolean isLocked = tmpLockedUsers.get(t.getUserId());
- task = new Task(taskKey, td.getPrimaryColor(), td.getBackgroundColor(),
- t.supportsSplitScreenMultiWindow(), isLocked, rawTd, t.getTopActivity());
+ boolean isLocked = tmpLockedUsers.get(taskKey.userId);
+ task = Task.from(taskKey, rawTask, isLocked);
} else {
task = new Task(taskKey);
}
diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
index d9fcf4d97a..d0956d1f6d 100644
--- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
+++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
@@ -88,7 +88,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
*/
@Test
public void testPredictionExistsInAllApps() {
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
mLauncher.pressHome().switchToAllApps();
// Dispatch an update
@@ -103,7 +103,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
*/
@Test
public void testPredictionsDeferredUntilHome() {
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
sendPredictionUpdate(mSampleApp1, mSampleApp2);
mLauncher.pressHome().switchToAllApps();
waitForLauncherCondition("Predictions were not updated in loading state",
@@ -120,7 +120,7 @@ public class AppPredictionsUITests extends AbstractQuickStepTest {
@Test
public void testPredictionsDisabled() {
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
sendPredictionUpdate();
mLauncher.pressHome().switchToAllApps();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 9e3bf2f56e..885fdbf423 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -17,7 +17,6 @@
package com.android.quickstep;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -208,7 +207,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@Test
@NavigationModeSwitch
-// @PortraitLandscape
+ @PortraitLandscape
public void testBackground() throws Exception {
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
final Background background = mLauncher.getBackground();
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index c0859d3b4d..50f92daf28 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -88,7 +88,7 @@
"Punts de notificació"
"Activats"
"Desactivats"
- "Cal que tingui accés a les notificacions"
+ "Cal accés a les notificacions"
"Per veure els punts de notificació, activa les notificacions de l\'aplicació %1$s"
"Canvia la configuració"
"Mostra els punts de notificació"
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 3054214b5e..211f735b49 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -30,10 +30,10 @@
"Layar utama"
"Tindakan khusus"
"Sentuh lama untuk memilih widget."
- "Tap dua kalip & tahan untuk mengambil widget atau menggunakan tindakan khusus."
+ "Ketuk dua kali & tahan untuk mengambil widget atau menggunakan tindakan khusus."
"%1$d × %2$d"
"lebar %1$d x tinggi %2$d"
- "Tap lama untuk menempatkan secara manual"
+ "Sentuh lama untuk menempatkan secara manual"
"Tambahkan otomatis"
"Telusuri aplikasi"
"Memuat aplikasi…"
@@ -41,8 +41,8 @@
"Telusuri aplikasi lainnya"
"Aplikasi"
"Notifikasi"
- "Tap lama untuk memilih pintasan."
- "Tap dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."
+ "Sentuh lama untuk memilih pintasan."
+ "Ketuk dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus."
"Tidak ada ruang lagi pada layar Utama ini."
"Tidak ada ruang tersisa di baki Favorit"
"Daftar aplikasi"
@@ -73,8 +73,8 @@
"Layar utama %1$d dari %2$d"
"Halaman layar utama baru"
"Folder dibuka, %1$d x %2$d"
- "Tap untuk menutup folder"
- "Tap untuk menyimpan ganti nama"
+ "Ketuk untuk menutup folder"
+ "Ketuk untuk menyimpan ganti nama"
"Folder ditutup"
"Folder diganti namanya menjadi %1$s"
"Folder: %1$s"
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 19c06976b0..49e38982cd 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -35,18 +35,18 @@
"%1$d रूंद बाय %2$d उंच"
"स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा"
"आपोआप जोडा"
- "अॅप्स शोधा"
- "अॅप्स लोड करत आहे…"
- "\"%1$s\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत"
- "अधिक अॅप्स शोधा"
+ "अॅप्स शोधा"
+ "अॅप्स लोड करत आहे…"
+ "\"%1$s\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत"
+ "अधिक अॅप्स शोधा"
"ॲप"
"सूचना"
"शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा."
"शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा."
"या मुख्य स्क्रीनवर आणखी जागा नाही."
"आवडीच्या ट्रे मध्ये आणखी जागा नाही"
- "अॅप्स सूची"
- "वैयक्तिक अॅप्स सूची"
+ "अॅप्स सूची"
+ "वैयक्तिक अॅप्स सूची"
"कामाच्या ठिकाणी वापरली जाणाऱ्या अॅप्सची सूची"
"होम"
"काढा"
@@ -136,7 +136,7 @@
"कामाची अॅप्स येथे मिळवा"
"प्रत्येक कार्य अॅपला एक बॅज असतो आणि तो तुमच्या संस्थेकडून सुरक्षित ठेवला जातो. अधिक सहज अॅक्सेससाठी अॅप्स तुमच्या होम स्क्रीनवर हलवा."
"तुमच्या संस्थेकडून व्यवस्थापित"
- "सूचना आणि अॅप्स बंद आहेत"
+ "सूचना आणि अॅप्स बंद आहेत"
"बंद करा"
"बंद केले"
"हे करता आले नाही: %1$s"
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 34e267da9b..23b00d0936 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -90,7 +90,7 @@
"Значки уведомлений"
"Включены"
"Отключены"
- "Нет доступа к уведомлениям"
+ "Нужен доступ к уведомлениям"
"Чтобы показывать значки уведомлений, включите уведомления в приложении \"%1$s\""
"Изменить настройки"
"Показывать значки уведомлений"
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index f69b172480..50553095d6 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -135,10 +135,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
@Nullable String sourceContainer) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(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;
@@ -162,10 +158,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(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 1619e3645f..22c69f59a5 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -319,9 +319,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_START_TAG, "BubbleTextView.onTouchEvent " + event);
- }
// Call the superclass onTouchEvent first, because sometimes it changes the state to
// isPressed() on an ACTION_UP
boolean result = super.onTouchEvent(event);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bc3aa7ef40..03fdc971dd 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -890,9 +890,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
protected void onStart() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_OVERVIEW_EVENT_TAG, "Launcher.onStart");
- }
RaceConditionTracker.onEvent(ON_START_EVT, ENTER);
super.onStart();
if (mLauncherCallbacks != null) {
@@ -1809,11 +1806,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
@Nullable String sourceContainer) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TAG,
- "startActivitySafely outer");
- }
-
if (!hasBeenResumed()) {
// Workaround an issue where the WM launch animation is clobbered when finishing the
// recents animation into launcher. Defer launching the activity until Launcher is
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 2c8c208456..d66e5813b9 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -403,10 +403,6 @@ public class LauncherStateManager {
}
private void onStateTransitionStart(LauncherState state) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "onStateTransitionStart");
- }
if (mState != state) {
mState.onStateDisabled(mLauncher);
}
@@ -429,11 +425,6 @@ public class LauncherStateManager {
// Only change the stable states after the transitions have finished
if (state != mCurrentStableState) {
mLastStableState = state.getHistoryForState(mCurrentStableState);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG,
- "mCurrentStableState = " + state.getClass().getSimpleName() + " @ " +
- android.util.Log.getStackTraceString(new Throwable()));
- }
mCurrentStableState = state;
}
@@ -580,10 +571,6 @@ public class LauncherStateManager {
private final AnimatorSet mAnim;
public StartAnimRunnable(AnimatorSet anim) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "StartAnimRunnable");
- }
mAnim = anim;
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index f8e4c9dfc7..bd52ffe4b2 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -47,6 +47,7 @@ import android.view.animation.Interpolator;
import android.widget.ScrollView;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.touch.OverScroll;
@@ -367,6 +368,7 @@ public abstract class PagedView extends ViewGrou
*/
protected void onPageEndTransition() {
mWasInOverscroll = false;
+ AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
}
protected int getUnboundedScrollX() {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 9f846bbc4d..8cd0822991 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -370,10 +370,6 @@ public class Workspace extends PagedView
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "onDragStart 1");
- }
if (ENFORCE_DRAG_EVENT_ORDER) {
enforceDragParity("onDragStart", 0, 0);
}
@@ -424,10 +420,6 @@ public class Workspace extends PagedView
}
// Always enter the spring loaded mode
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "onDragStart 2");
- }
mLauncher.getStateManager().goToState(SPRING_LOADED);
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index ea9b077c62..4a2109e588 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -50,6 +50,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusedItemDecorator;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.MultiValueAlpha;
@@ -297,7 +298,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
@Override
public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
- // This is filled in {@link AllAppsRecyclerView}
+ if (getApps().hasFilter()) {
+ targetParent.containerType = ContainerType.SEARCHRESULT;
+ } else {
+ targetParent.containerType = ContainerType.ALLAPPS;
+ }
}
@Override
@@ -626,9 +631,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_START_TAG, "AllAppsContainerView.dispatchTouchEvent " + ev);
- }
final boolean result = super.dispatchTouchEvent(ev);
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 4683893ea0..a64374bc37 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -168,10 +168,6 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
@Override
public void setStateWithAnimation(LauncherState toState,
AnimatorSetBuilder builder, AnimationConfig config) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG,
- "setStateWithAnimation " + toState.getClass().getSimpleName());
- }
float targetProgress = toState.getVerticalProgress(mLauncher);
if (Float.compare(mProgress, targetProgress) == 0) {
setAlphas(toState, config, builder);
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 2ad92e16f8..1369441fe1 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -301,11 +301,6 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
}
private void refreshRecyclerView() {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TAG,
- "refreshRecyclerView @ " + android.util.Log.getStackTraceString(
- new Throwable()));
- }
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index b169cb80be..8443231e8d 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -144,7 +144,8 @@ public class Interpolators {
public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
float upperBound) {
if (upperBound <= lowerBound) {
- throw new IllegalArgumentException("lowerBound must be less than upperBound");
+ throw new IllegalArgumentException(String.format(
+ "lowerBound (%f) must be less than upperBound (%f)", lowerBound, upperBound));
}
return t -> {
if (t < lowerBound) {
diff --git a/src/com/android/launcher3/anim/SpringObjectAnimator.java b/src/com/android/launcher3/anim/SpringObjectAnimator.java
index 395fed259a..91a31069c1 100644
--- a/src/com/android/launcher3/anim/SpringObjectAnimator.java
+++ b/src/com/android/launcher3/anim/SpringObjectAnimator.java
@@ -96,7 +96,10 @@ public class SpringObjectAnimator extends ValueAnimator {
}
});
- mSpring.addUpdateListener((animation, value, velocity) -> mSpringEnded = false);
+ mSpring.addUpdateListener((animation, value, velocity) -> {
+ mSpringEnded = false;
+ mEnded = false;
+ });
mSpring.addEndListener((animation, canceled, value, velocity) -> {
mSpringEnded = true;
tryEnding();
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 43ae65175f..81c95cbdd4 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -53,9 +53,6 @@ public class AccessibilityManagerCompat {
}
public static void sendStateEventToTest(Context context, int stateOrdinal) {
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.e(TestProtocol.NO_ALLAPPS_EVENT_TAG, "sendStateEventToTest");
- }
final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
if (accessibilityManager == null) return;
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index c719c1c986..1b08723f63 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -137,9 +137,6 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen
@Override
public boolean shouldStartDrag(double distanceDragged) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_DRAG_TAG, "BIDL.shouldStartDrag");
- }
// Stay in pre-drag mode, if workspace is locked.
return !mLauncher.isWorkspaceLocked();
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 72a1abb833..d32dd2eb98 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -474,10 +474,6 @@ public class DragController implements DragDriver.EventListener, TouchController
}
private void handleMoveEvent(int x, int y) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "handleMoveEvent 1");
- }
mDragObject.dragView.move(x, y);
// Drop on someone?
@@ -492,22 +488,8 @@ public class DragController implements DragDriver.EventListener, TouchController
mLastTouch[0] = x;
mLastTouch[1] = y;
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_DRAG_TAG,
- "handleMoveEvent Conditions " +
- mIsInPreDrag + ", " +
- (mIsInPreDrag && mOptions.preDragCondition != null) + ", " +
- (mIsInPreDrag && mOptions.preDragCondition != null
- && mOptions.preDragCondition.shouldStartDrag(
- mDistanceSinceScroll)));
- }
-
if (mIsInPreDrag && mOptions.preDragCondition != null
&& mOptions.preDragCondition.shouldStartDrag(mDistanceSinceScroll)) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "handleMoveEvent 2");
- }
callOnDragStart();
}
}
@@ -545,10 +527,6 @@ public class DragController implements DragDriver.EventListener, TouchController
* Call this from a drag source view.
*/
public boolean onControllerTouchEvent(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "onControllerTouchEvent");
- }
if (mDragDriver == null || mOptions == null || mOptions.isAccessibleDrag) {
return false;
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 9719a1892f..25d9f7976a 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -449,11 +449,6 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
@Override
public boolean shouldStartDrag(double distanceDragged) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_DRAG_TAG,
- "createPreDragCondition().shouldStartDrag " + distanceDragged + ", "
- + mStartDragThreshold);
- }
return distanceDragged > mStartDragThreshold;
}
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index d2e196138c..bab454f070 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -74,6 +74,11 @@ public class TestInformationHandler implements ResourceBasedOverride {
break;
}
+ case TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED: {
+ response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, true);
+ break;
+ }
+
case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
TestProtocol.sDebugTracing = true;
break;
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 3774042c93..079ab6d8fe 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -66,17 +66,15 @@ public final class TestProtocol {
"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 final String REQUEST_HOTSEAT_TOP = "hotseat-top";
+ public static final String REQUEST_IS_LAUNCHER_INITIALIZED = "is-launcher-initialized";
public static final String REQUEST_FREEZE_APP_LIST = "freeze-app-list";
public static final String REQUEST_UNFREEZE_APP_LIST = "unfreeze-app-list";
public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags";
+ public static final String REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN = "overview-left-margin";
+ public static final String REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN = "overview-right-margin";
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_ALLAPPS_EVENT_TAG = "b/133867119";
- public static final String NO_DRAG_TAG = "b/133009122";
- public static final String NO_START_TAG = "b/132900132";
- public static final String NO_START_TASK_TAG = "b/133765434";
- public static final String NO_OVERVIEW_EVENT_TAG = "b/134532571";
- public static final String EVENTS_TO_OVERVIEW_MISSING_TAG = "b/133867119";
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 6f53140eab..ae69f3b32d 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -31,7 +31,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.os.SystemClock;
-import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
@@ -43,7 +42,6 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -118,9 +116,6 @@ public abstract class AbstractStateChangeTouchController
@Override
public final boolean onControllerInterceptTouchEvent(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onControllerInterceptTouchEvent 1 " + ev);
- }
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mNoIntercept = !canInterceptTouch(ev);
if (mNoIntercept) {
@@ -150,9 +145,6 @@ public abstract class AbstractStateChangeTouchController
return false;
}
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onControllerInterceptTouchEvent 2 ");
- }
onControllerTouchEvent(ev);
return mDetector.isDraggingOrSettling();
}
@@ -240,9 +232,6 @@ public abstract class AbstractStateChangeTouchController
@Override
public void onDragStart(boolean start) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onDragStart 1 " + start);
- }
mStartState = mLauncher.getStateManager().getState();
if (mStartState == ALL_APPS) {
mStartContainerType = LauncherLogProto.ContainerType.ALLAPPS;
@@ -252,9 +241,6 @@ public abstract class AbstractStateChangeTouchController
mStartContainerType = LauncherLogProto.ContainerType.TASKSWITCHER;
}
if (mCurrentAnimation == null) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onDragStart 2");
- }
mFromState = mStartState;
mToState = null;
cancelAnimationControllers();
@@ -376,9 +362,6 @@ public abstract class AbstractStateChangeTouchController
@Override
public void onDragEnd(float velocity, boolean fling) {
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.e(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onDragEnd");
- }
final int logAction = fling ? Touch.FLING : Touch.SWIPE;
boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
@@ -515,9 +498,6 @@ public abstract class AbstractStateChangeTouchController
}
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.e(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onSwipeInteractionCompleted 1");
- }
if (mAtomicComponentsController != null) {
mAtomicComponentsController.getAnimationPlayer().end();
mAtomicComponentsController = null;
@@ -531,18 +511,17 @@ public abstract class AbstractStateChangeTouchController
shouldGoToTargetState = !reachedTarget;
}
if (shouldGoToTargetState) {
- if (targetState != mStartState) {
- logReachedState(logAction, targetState);
- }
- mLauncher.getStateManager().goToState(targetState, false /* animated */);
-
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.e(
- TestProtocol.NO_ALLAPPS_EVENT_TAG, "onSwipeInteractionCompleted 2");
- }
+ goToTargetState(targetState, logAction);
}
}
+ protected void goToTargetState(LauncherState targetState, int logAction) {
+ if (targetState != mStartState) {
+ logReachedState(logAction, targetState);
+ }
+ mLauncher.getStateManager().goToState(targetState, false /* animated */);
+ }
+
private void logReachedState(int logAction, LauncherState targetState) {
// Transition complete. log the action
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
@@ -563,9 +542,6 @@ public abstract class AbstractStateChangeTouchController
}
private void cancelAnimationControllers() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "cancelAnimationControllers");
- }
mCurrentAnimation = null;
cancelAtomicComponentsController();
mDetector.finishedScrolling();
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 85f763d095..2895a89be3 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -68,28 +68,12 @@ public class ItemClickHandler {
}
private static void onClick(View v, String sourceContainer) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(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 (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TAG,
- "onClick 2");
- }
- return;
- }
+ if (v.getWindowToken() == null) return;
Launcher launcher = Launcher.getLauncher(v.getContext());
- if (!launcher.getWorkspace().isFinishedSwitchingState()) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TAG,
- "onClick 3");
- }
- return;
- }
+ if (!launcher.getWorkspace().isFinishedSwitchingState()) return;
Object tag = v.getTag();
if (tag instanceof WorkspaceItemInfo) {
@@ -99,10 +83,6 @@ public class ItemClickHandler {
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TAG,
- "onClick 4");
- }
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer);
} else if (tag instanceof LauncherAppWidgetInfo) {
@@ -234,10 +214,6 @@ public class ItemClickHandler {
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
@Nullable String sourceContainer) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_START_TAG,
- "startAppShortcutOrInfoActivity");
- }
Intent intent;
if (item instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
diff --git a/src/com/android/launcher3/touch/SwipeDetector.java b/src/com/android/launcher3/touch/SwipeDetector.java
index 3d454046a5..3777a41ad8 100644
--- a/src/com/android/launcher3/touch/SwipeDetector.java
+++ b/src/com/android/launcher3/touch/SwipeDetector.java
@@ -158,9 +158,6 @@ public class SwipeDetector {
// SETTLING -> (View settled) -> IDLE
private void setState(ScrollState newState) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "setState -- start: " + newState);
- }
if (DBG) {
Log.d(TAG, "setState:" + mState + "->" + newState);
}
@@ -168,9 +165,6 @@ public class SwipeDetector {
if (newState == ScrollState.DRAGGING) {
initializeDragging();
if (mState == ScrollState.IDLE) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "setState -- 1: " + newState);
- }
reportDragStart(false /* recatch */);
} else if (mState == ScrollState.SETTLING) {
reportDragStart(true /* recatch */);
@@ -181,11 +175,6 @@ public class SwipeDetector {
}
mState = newState;
- if (com.android.launcher3.testing.TestProtocol.sDebugTracing) {
- android.util.Log.e(TestProtocol.NO_ALLAPPS_EVENT_TAG,
- "setState: " + newState + " @ " + android.util.Log.getStackTraceString(
- new Throwable()));
- }
}
public boolean isDraggingOrSettling() {
@@ -324,15 +313,9 @@ public class SwipeDetector {
break;
}
mDisplacement = mDir.getDisplacement(ev, pointerIndex, mDownPos, mIsRtl);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onTouchEvent 1");
- }
// handle state and listener calls.
if (mState != ScrollState.DRAGGING && shouldScrollStart(ev, pointerIndex)) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_ALLAPPS_EVENT_TAG, "onTouchEvent 2");
- }
setState(ScrollState.DRAGGING);
}
if (mState == ScrollState.DRAGGING) {
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 1e70c7f812..594a24630b 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -152,9 +152,6 @@ public abstract class BaseDragLayer
}
private TouchController findControllerToHandleTouch(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "findControllerToHandleTouch " + ev);
- }
if (shouldDisableGestures(ev)) return null;
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
@@ -233,10 +230,6 @@ public abstract class BaseDragLayer
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(TestProtocol.NO_DRAG_TAG,
- "onTouchEvent " + ev);
- }
int action = ev.getAction();
if (action == ACTION_UP || action == ACTION_CANCEL) {
if (mTouchCompleteListener != null) {
@@ -246,10 +239,6 @@ public abstract class BaseDragLayer
}
if (mActiveController != null) {
- if (TestProtocol.sDebugTracing) {
- android.util.Log.d(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
@@ -259,9 +248,6 @@ public abstract class BaseDragLayer
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_START_TAG, "BaseDragLayer.dispatchTouchEvent " + ev);
- }
switch (ev.getAction()) {
case ACTION_DOWN: {
float x = ev.getX();
@@ -315,9 +301,6 @@ public abstract class BaseDragLayer
* Proxies the touch events to the gesture handlers
*/
public boolean proxyTouchEvent(MotionEvent ev) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "proxyTouchEvent " + ev);
- }
boolean handled;
if (mProxyTouchController != null) {
handled = mProxyTouchController.onControllerTouchEvent(ev);
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index ab4b576bf9..e09a9e8bfc 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -18,6 +18,7 @@ package com.android.launcher3.views;
import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA;
import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.Utilities.getFullDrawable;
+import static com.android.launcher3.Utilities.isRtl;
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
@@ -129,6 +130,7 @@ public class FloatingIconView extends View implements
private final Launcher mLauncher;
private final int mBlurSizeOutline;
+ private final boolean mIsRtl;
private boolean mIsVerticalBarLayout = false;
private boolean mIsAdaptiveIcon = false;
@@ -174,6 +176,7 @@ public class FloatingIconView extends View implements
mLauncher = Launcher.getLauncher(context);
mBlurSizeOutline = getResources().getDimensionPixelSize(
R.dimen.blur_size_medium_outline);
+ mIsRtl = Utilities.isRtl(getResources());
mListenerView = new ListenerView(context, attrs);
mFgSpringX = new SpringAnimation(this, mFgTransXProperty)
@@ -213,7 +216,10 @@ public class FloatingIconView extends View implements
setAlpha(alpha);
LayoutParams lp = (LayoutParams) getLayoutParams();
- float dX = rect.left - lp.leftMargin;
+ float dX = mIsRtl
+ ? rect.left
+ - (mLauncher.getDeviceProfile().widthPx - lp.getMarginStart() - lp.width)
+ : rect.left - lp.getMarginStart();
float dY = rect.top - lp.topMargin;
setTranslationX(dX);
setTranslationY(dY);
@@ -323,14 +329,18 @@ public class FloatingIconView extends View implements
mPositionOut.set(position);
lp.ignoreInsets = true;
// Position the floating view exactly on top of the original
- lp.leftMargin = Math.round(position.left);
lp.topMargin = Math.round(position.top);
-
+ if (mIsRtl) {
+ lp.setMarginStart(Math.round(mLauncher.getDeviceProfile().widthPx - position.right));
+ } else {
+ lp.setMarginStart(Math.round(position.left));
+ }
// Set the properties here already to make sure they are available when running the first
// animation frame.
- layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin
- + lp.height);
-
+ int left = mIsRtl
+ ? mLauncher.getDeviceProfile().widthPx - lp.getMarginStart() - lp.width
+ : lp.leftMargin;
+ layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height);
}
/**
@@ -514,8 +524,11 @@ public class FloatingIconView extends View implements
} else {
lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
}
- layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin
- + lp.height);
+
+ int left = mIsRtl
+ ? mLauncher.getDeviceProfile().widthPx - lp.getMarginStart() - lp.width
+ : lp.leftMargin;
+ layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height);
float scale = Math.max((float) lp.height / originalHeight,
(float) lp.width / originalWidth);
@@ -656,8 +669,7 @@ public class FloatingIconView extends View implements
canvas.restoreToCount(count);
}
- public void onListenerViewClosed() {
- // Fast finish here.
+ public void fastFinish() {
if (mEndRunnable != null) {
mEndRunnable.run();
mEndRunnable = null;
@@ -757,7 +769,7 @@ public class FloatingIconView extends View implements
view.setVisibility(INVISIBLE);
parent.addView(view);
dragLayer.addView(view.mListenerView);
- view.mListenerView.setListener(view::onListenerViewClosed);
+ view.mListenerView.setListener(view::fastFinish);
view.mEndRunnable = () -> {
view.mEndRunnable = null;
diff --git a/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java b/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
index fa23b8d5b9..6a6916eec3 100644
--- a/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
+++ b/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
@@ -32,13 +32,14 @@ import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Base64;
+import androidx.test.InstrumentationRegistry;
+
+import com.android.launcher3.tapl.TestHelpers;
+
import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
-import androidx.test.InstrumentationRegistry;
-
/**
* Content provider to receive commands from tests
*/
@@ -47,6 +48,7 @@ public class TestCommandReceiver extends ContentProvider {
public static final String ENABLE_TEST_LAUNCHER = "enable-test-launcher";
public static final String DISABLE_TEST_LAUNCHER = "disable-test-launcher";
public static final String KILL_PROCESS = "kill-process";
+ public static final String GET_SYSTEM_HEALTH_MESSAGE = "get-system-health-message";
@Override
public boolean onCreate() {
@@ -99,6 +101,12 @@ public class TestCommandReceiver extends ContentProvider {
killBackgroundProcesses(arg);
return null;
}
+
+ case GET_SYSTEM_HEALTH_MESSAGE: {
+ final Bundle response = new Bundle();
+ response.putString("result", TestHelpers.getSystemHealthMessage(getContext()));
+ return response;
+ }
}
return super.call(method, arg, extras);
}
@@ -122,7 +130,8 @@ public class TestCommandReceiver extends ContentProvider {
// Create an empty file so that we can pass its descriptor
try {
file.createNewFile();
- } catch (IOException e) { }
+ } catch (IOException e) {
+ }
}
return ParcelFileDescriptor.open(file, MODE_READ_WRITE);
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index e39fc76a0b..361f2fb533 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -51,6 +51,7 @@ import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
+import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.FailureWatcher;
@@ -98,7 +99,11 @@ public abstract class AbstractLauncherUiTest {
} catch (RemoteException e) {
throw new RuntimeException(e);
}
- if (TestHelpers.isInLauncherProcess()) Utilities.enableRunningInTestHarnessForTests();
+ if (TestHelpers.isInLauncherProcess()) {
+ Utilities.enableRunningInTestHarnessForTests();
+ mLauncher.setSystemHealthSupplier(() -> TestCommandReceiver.callCommand(
+ TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE).getString("result"));
+ }
}
protected final LauncherActivityRule mActivityMonitor = new LauncherActivityRule();
diff --git a/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java b/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java
index 58c74cef16..a76b4a4886 100644
--- a/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java
+++ b/tests/src/com/android/launcher3/ui/DefaultLayoutProviderTest.java
@@ -72,7 +72,7 @@ public class DefaultLayoutProviderTest extends AbstractLauncherUiTest {
writeLayout(new LauncherLayoutBuilder().atHotseat(0).putApp(SETTINGS_APP, SETTINGS_APP));
// Launch the home activity
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
waitForModelLoaded();
mLauncher.getWorkspace().getHotseatAppIcon(getSettingsApp().getLabel().toString());
@@ -88,7 +88,7 @@ public class DefaultLayoutProviderTest extends AbstractLauncherUiTest {
info.getComponent().getClassName(), 2, 2));
// Launch the home activity
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
waitForModelLoaded();
// Verify widget present
@@ -105,7 +105,7 @@ public class DefaultLayoutProviderTest extends AbstractLauncherUiTest {
.build());
// Launch the home activity
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
waitForModelLoaded();
mLauncher.getWorkspace().getHotseatFolder("Folder: Copy");
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index c93c20a616..d9edc35874 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -53,8 +53,8 @@ public class WorkTabTest extends AbstractLauncherUiTest {
@Test
public void workTabExists() {
- mActivityMonitor.startLauncher();
-
+ mDevice.pressHome();
+ waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null);
executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
/*
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index dc72bda9a3..3206a69bbf 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -98,7 +98,7 @@ public class AddConfigWidgetTest extends AbstractLauncherUiTest {
lockRotation(true);
clearHomescreen();
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
final Widgets widgets = mLauncher.getWorkspace().openAllWidgets();
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 4529a80d1d..276c6144a2 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -55,7 +55,7 @@ public class AddWidgetTest extends AbstractLauncherUiTest {
private void performTest() throws Throwable {
clearHomescreen();
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
final LauncherAppWidgetProviderInfo widgetInfo =
TestViewHelpers.findWidgetProvider(this, false /* hasConfigureScreen */);
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index d36126bb17..3a7df64e81 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -267,7 +267,7 @@ public class BindWidgetTest extends AbstractLauncherUiTest {
resetLoaderState();
// Launch the home activity
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
waitForModelLoaded();
}
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index 6122daec2c..a9a5090988 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -131,7 +131,7 @@ public class RequestPinItemTest extends AbstractLauncherUiTest {
lockRotation(true);
clearHomescreen();
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
// Open Pin item activity
BlockingBroadcastReceiver openMonitor = new BlockingBroadcastReceiver(
diff --git a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
index 2aba7a56de..204240324e 100644
--- a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
@@ -15,11 +15,6 @@
*/
package com.android.launcher3.util.rule;
-import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage;
-
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
-import static androidx.test.InstrumentationRegistry.getTargetContext;
-
import android.app.Activity;
import android.app.Application;
import android.app.Application.ActivityLifecycleCallbacks;
@@ -52,26 +47,15 @@ public class LauncherActivityRule implements TestRule {
}
public Callable itemExists(final ItemOperator op) {
- return new Callable() {
-
- @Override
- public Boolean call() throws Exception {
- Launcher launcher = getActivity();
- if (launcher == null) {
- return false;
- }
- return launcher.getWorkspace().getFirstMatch(op) != null;
+ return () -> {
+ Launcher launcher = getActivity();
+ if (launcher == null) {
+ return false;
}
+ return launcher.getWorkspace().getFirstMatch(op) != null;
};
}
- /**
- * Starts the launcher activity in the target package.
- */
- public void startLauncher() {
- getInstrumentation().startActivitySync(getHomeIntentInPackage(getTargetContext()));
- }
-
private class MyStatement extends Statement implements ActivityLifecycleCallbacks {
private final Statement mBase;
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 0ac5e9f887..9ff354a7eb 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -181,7 +181,6 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
* Flings backward (up) and waits the fling's end.
*/
public void flingBackward() {
- mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
try (LauncherInstrumentation.Closable c =
mLauncher.addContextLayer("want to fling backward in all apps")) {
final UiObject2 allAppsContainer = verifyActiveContainer();
@@ -190,7 +189,6 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
allAppsContainer, Direction.UP, 1, new Rect(0, mHeight / 2, 0, 0), 10);
verifyActiveContainer();
}
- mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
}
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index c9eaf276d7..060bf30202 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -59,7 +59,6 @@ public class Background extends LauncherInstrumentation.VisibleContainer {
}
protected void goToOverviewUnchecked(int expectedState) {
- mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
switch (mLauncher.getNavigationModel()) {
case ZERO_BUTTON: {
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
@@ -112,7 +111,6 @@ public class Background extends LauncherInstrumentation.VisibleContainer {
mLauncher.waitForSystemUiObject("recent_apps").click();
break;
}
- mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
}
protected String getSwipeHeightRequestName() {
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index ace49e9cea..04a0f12714 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -16,11 +16,15 @@
package com.android.launcher3.tapl;
+import android.graphics.Rect;
+
import androidx.annotation.NonNull;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiObject2;
+import com.android.launcher3.testing.TestProtocol;
+
import java.util.Collections;
import java.util.List;
@@ -28,7 +32,6 @@ import java.util.List;
* Common overview pane for both Launcher and fallback recents
*/
public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
- private static final int FLING_SPEED = LauncherInstrumentation.isAvd() ? 500 : 1500;
private static final int FLINGS_FOR_DISMISS_LIMIT = 40;
BaseOverview(LauncherInstrumentation launcher) {
@@ -49,9 +52,10 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
mLauncher.addContextLayer("want to fling forward in overview")) {
LauncherInstrumentation.log("Overview.flingForward before fling");
final UiObject2 overview = verifyActiveContainer();
- overview.setGestureMargins(mLauncher.getEdgeSensitivityWidth(), 0, 0, 0);
- overview.fling(Direction.LEFT, (int) (FLING_SPEED * mLauncher.getDisplayDensity()));
- mLauncher.waitForIdle();
+ final int leftMargin = mLauncher.getTestInfo(
+ TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN).
+ getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ mLauncher.scroll(overview, Direction.LEFT, 1, new Rect(leftMargin, 0, 0, 0), 20);
verifyActiveContainer();
}
}
@@ -86,9 +90,10 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
mLauncher.addContextLayer("want to fling backward in overview")) {
LauncherInstrumentation.log("Overview.flingBackward before fling");
final UiObject2 overview = verifyActiveContainer();
- overview.setGestureMargins(0, 0, mLauncher.getEdgeSensitivityWidth(), 0);
- overview.fling(Direction.RIGHT, (int) (FLING_SPEED * mLauncher.getDisplayDensity()));
- mLauncher.waitForIdle();
+ final int rightMargin = mLauncher.getTestInfo(
+ TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN).
+ getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ mLauncher.scroll(overview, Direction.RIGHT, 1, new Rect(0, 0, rightMargin, 0), 20);
verifyActiveContainer();
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 04b8019450..82af7b03ac 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -53,11 +53,9 @@ abstract class Launchable {
private Background launch(BySelector selector) {
LauncherInstrumentation.log("Launchable.launch before click " +
mObject.getVisibleCenter() + " in " + mObject.getVisibleBounds());
- mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
mLauncher.assertTrue(
"Launching an app didn't open a new window: " + mObject.getText(),
mObject.clickAndWait(Until.newWindow(), 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 11b0665d95..a5b0d25671 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -39,7 +39,6 @@ import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.DropBoxManager;
import android.os.Parcelable;
import android.os.SystemClock;
import android.text.TextUtils;
@@ -73,6 +72,7 @@ import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeoutException;
+import java.util.function.Supplier;
/**
* The main tapl object. The only object that can be explicitly constructed by the using code. It
@@ -133,6 +133,7 @@ public final class LauncherInstrumentation {
private int mExpectedRotation = Surface.ROTATION_0;
private final Uri mTestProviderUri;
private final Deque mDiagnosticContext = new LinkedList<>();
+ private Supplier mSystemHealthSupplier;
/**
* Constructs the root of TAPL hierarchy. You get all other objects from it.
@@ -207,7 +208,7 @@ public final class LauncherInstrumentation {
try {
// Workaround, use constructed context because both the instrumentation context and the
// app context are not constructed with resources that take overlays into account
- final Context ctx = baseContext.createPackageContext("android", 0);
+ final Context ctx = baseContext.createPackageContext(getLauncherPackageName(), 0);
for (int i = 0; i < 100; ++i) {
final int currentInteractionMode = getCurrentInteractionMode(ctx);
final NavigationModel model = getNavigationModel(currentInteractionMode);
@@ -265,11 +266,17 @@ public final class LauncherInstrumentation {
}
private String getAnomalyMessage() {
- final UiObject2 object = mDevice.findObject(By.res("android", "alertTitle"));
+ UiObject2 object = mDevice.findObject(By.res("android", "alertTitle"));
if (object != null) {
return "System alert popup is visible: " + object.getText();
}
+ object = mDevice.findObject(By.res("android", "message"));
+ if (object != null) {
+ return "Message popup by " + object.getApplicationPackage() + " is visible: "
+ + object.getText();
+ }
+
if (hasSystemUiObject("keyguard_status_view")) return "Phone is locked";
if (!mDevice.hasObject(By.textStartsWith(""))) return "Screen is empty";
@@ -285,79 +292,24 @@ public final class LauncherInstrumentation {
return "Background";
}
- private static String truncateCrash(String text, int maxLines) {
- String[] lines = text.split("\\r?\\n");
- StringBuilder ret = new StringBuilder();
- for (int i = 0; i < maxLines && i < lines.length; i++) {
- ret.append(lines[i]);
- ret.append('\n');
- }
- if (lines.length > maxLines) {
- ret.append("... ");
- ret.append(lines.length - maxLines);
- ret.append(" more lines truncated ...\n");
- }
- return ret.toString();
- }
-
- private String checkCrash(String label) {
- DropBoxManager dropbox = (DropBoxManager) getContext().getSystemService(
- Context.DROPBOX_SERVICE);
- Assert.assertNotNull("Unable access the DropBoxManager service", dropbox);
-
- long timestamp = 0;
- DropBoxManager.Entry entry;
- int crashCount = 0;
- StringBuilder errorDetails = new StringBuilder();
- while (null != (entry = dropbox.getNextEntry(label, timestamp))) {
- String dropboxSnippet;
- try {
- dropboxSnippet = entry.getText(4096);
- } finally {
- entry.close();
- }
-
- crashCount++;
- errorDetails.append(label);
- errorDetails.append(": ");
- errorDetails.append(truncateCrash(dropboxSnippet, 40));
- errorDetails.append(" ...\n");
-
- timestamp = entry.getTimeMillis();
- }
- Assert.assertEquals(errorDetails.toString(), 0, crashCount);
- return crashCount > 0 ? errorDetails.toString() : null;
+ public void setSystemHealthSupplier(Supplier supplier) {
+ this.mSystemHealthSupplier = supplier;
}
private String getSystemHealthMessage() {
+ final String testPackage = getContext().getPackageName();
try {
- StringBuilder errors = new StringBuilder();
-
- final String testPackage = getContext().getPackageName();
- try {
- mDevice.executeShellCommand("pm grant " + testPackage +
- " android.permission.READ_LOGS");
- mDevice.executeShellCommand("pm grant " + testPackage +
- " android.permission.PACKAGE_USAGE_STATS");
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- final String[] labels = {
- "system_server_crash",
- "system_server_native_crash",
- "system_server_anr",
- };
-
- for (String label : labels) {
- final String crash = checkCrash(label);
- if (crash != null) errors.append(crash);
- }
-
- return errors.length() != 0 ? errors.toString() : null;
- } catch (Exception e) {
- return null;
+ mDevice.executeShellCommand("pm grant " + testPackage +
+ " android.permission.READ_LOGS");
+ mDevice.executeShellCommand("pm grant " + testPackage +
+ " android.permission.PACKAGE_USAGE_STATS");
+ } catch (IOException e) {
+ e.printStackTrace();
}
+
+ return mSystemHealthSupplier != null
+ ? mSystemHealthSupplier.get()
+ : TestHelpers.getSystemHealthMessage(getContext());
}
private void fail(String message) {
@@ -444,6 +396,8 @@ public final class LauncherInstrumentation {
}
private UiObject2 verifyContainerType(ContainerType containerType) {
+ //waitForTouchInteractionService();
+
assertEquals("Unexpected display rotation",
mExpectedRotation, mDevice.getDisplayRotation());
@@ -514,6 +468,18 @@ public final class LauncherInstrumentation {
}
}
+ private void waitForTouchInteractionService() {
+ for (int i = 0; i < 100; ++i) {
+ if (getTestInfo(
+ TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED).
+ getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD)) {
+ return;
+ }
+ SystemClock.sleep(100);
+ }
+ fail("TouchInteractionService didn't connect");
+ }
+
Parcelable executeAndWaitForEvent(Runnable command,
UiAutomation.AccessibilityEventFilter eventFilter, String message) {
try {
@@ -816,10 +782,26 @@ public final class LauncherInstrumentation {
startX = endX = rect.centerX();
final int vertCenter = rect.centerY();
final float halfGestureHeight = rect.height() * percent / 2.0f;
- startY = (int) (vertCenter + halfGestureHeight);
+ startY = (int) (vertCenter + halfGestureHeight) - 1;
endY = (int) (vertCenter - halfGestureHeight);
}
break;
+ case LEFT: {
+ startY = endY = rect.centerY();
+ final int horizCenter = rect.centerX();
+ final float halfGestureWidth = rect.width() * percent / 2.0f;
+ startX = (int) (horizCenter - halfGestureWidth);
+ endX = (int) (horizCenter + halfGestureWidth);
+ }
+ break;
+ case RIGHT: {
+ startY = endY = rect.centerY();
+ final int horizCenter = rect.centerX();
+ final float halfGestureWidth = rect.width() * percent / 2.0f;
+ startX = (int) (horizCenter + halfGestureWidth) - 1;
+ endX = (int) (horizCenter - halfGestureWidth);
+ }
+ break;
default:
fail("Unsupported direction");
return;
@@ -936,7 +918,7 @@ public final class LauncherInstrumentation {
int getEdgeSensitivityWidth() {
try {
final Context context = mInstrumentation.getTargetContext().createPackageContext(
- "android", 0);
+ getLauncherPackageName(), 0);
return context.getResources().getDimensionPixelSize(
getSystemDimensionResId(context, "config_backGestureInset")) + 1;
} catch (PackageManager.NameNotFoundException e) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index 058831f180..da68da3ba6 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -19,9 +19,9 @@ package com.android.launcher3.tapl;
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import androidx.annotation.NonNull;
-import androidx.test.uiautomator.UiObject2;
import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
+import com.android.launcher3.testing.TestProtocol;
/**
* Overview pane.
@@ -51,11 +51,15 @@ public final class Overview extends BaseOverview {
// Swipe from an app icon to the top.
LauncherInstrumentation.log("Overview.switchToAllApps before swipe");
- final UiObject2 allApps = mLauncher.waitForLauncherObject("apps_view");
- mLauncher.swipeToState(mLauncher.getDevice().getDisplayWidth() / 2,
- allApps.getVisibleBounds().top,
+ mLauncher.swipeToState(
mLauncher.getDevice().getDisplayWidth() / 2,
- 0, 50, ALL_APPS_STATE_ORDINAL);
+ mLauncher.getTestInfo(
+ TestProtocol.REQUEST_HOTSEAT_TOP).
+ getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD),
+ mLauncher.getDevice().getDisplayWidth() / 2,
+ 0,
+ 50,
+ ALL_APPS_STATE_ORDINAL);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped all way up from overview")) {
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 641c413538..6e3332260b 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -64,14 +64,12 @@ public final class OverviewTask {
*/
public Background open() {
verifyActiveContainer();
- mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"clicking an overview task")) {
mLauncher.assertTrue("Launching task didn't open a new window: " +
mTask.getParent().getContentDescription(),
mTask.clickAndWait(Until.newWindow(), WAIT_TIME_MS));
}
- mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
return new Background(mLauncher);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
index 93554d2452..e19f91a20a 100644
--- a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
+++ b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
@@ -26,6 +26,9 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.os.DropBoxManager;
+
+import org.junit.Assert;
import java.util.List;
@@ -81,4 +84,69 @@ public class TestHelpers {
}
return "com.android.systemui";
}
+
+ private static String truncateCrash(String text, int maxLines) {
+ String[] lines = text.split("\\r?\\n");
+ StringBuilder ret = new StringBuilder();
+ for (int i = 0; i < maxLines && i < lines.length; i++) {
+ ret.append(lines[i]);
+ ret.append('\n');
+ }
+ if (lines.length > maxLines) {
+ ret.append("... ");
+ ret.append(lines.length - maxLines);
+ ret.append(" more lines truncated ...\n");
+ }
+ return ret.toString();
+ }
+
+ private static String checkCrash(Context context, String label) {
+ DropBoxManager dropbox = (DropBoxManager) context.getSystemService(Context.DROPBOX_SERVICE);
+ Assert.assertNotNull("Unable access the DropBoxManager service", dropbox);
+
+ long timestamp = 0;
+ DropBoxManager.Entry entry;
+ int crashCount = 0;
+ StringBuilder errorDetails = new StringBuilder();
+ while (null != (entry = dropbox.getNextEntry(label, timestamp))) {
+ String dropboxSnippet;
+ try {
+ dropboxSnippet = entry.getText(4096);
+ } finally {
+ entry.close();
+ }
+
+ crashCount++;
+ errorDetails.append(label);
+ errorDetails.append(": ");
+ errorDetails.append(truncateCrash(dropboxSnippet, 40));
+ errorDetails.append(" ...\n");
+
+ timestamp = entry.getTimeMillis();
+ }
+ Assert.assertEquals(errorDetails.toString(), 0, crashCount);
+ return crashCount > 0 ? errorDetails.toString() : null;
+ }
+
+ public static String getSystemHealthMessage(Context context) {
+ try {
+ StringBuilder errors = new StringBuilder();
+
+ final String[] labels = {
+ "system_server_crash",
+ "system_server_native_crash",
+ "system_server_anr",
+ };
+
+ for (String label : labels) {
+ final String crash = checkCrash(context, label);
+ if (crash != null) errors.append(crash);
+ }
+
+ return errors.length() != 0 ? errors.toString() : null;
+ } catch (Exception e) {
+ return "Failed to get system health diags, maybe build your test via .bp instead of "
+ + ".mk? " + android.util.Log.getStackTraceString(e);
+ }
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index b01b6f363c..07f8b64433 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -67,7 +67,6 @@ public final class Workspace extends Home {
"switchToAllApps: swipeHeight = " + swipeHeight + ", slop = "
+ mLauncher.getTouchSlop());
- mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
mLauncher.swipeToState(
start.x,
start.y,
@@ -75,7 +74,6 @@ public final class Workspace extends Home {
start.y - swipeHeight - mLauncher.getTouchSlop(),
60,
ALL_APPS_STATE_ORDINAL);
- mLauncher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped to all apps")) {
@@ -157,7 +155,6 @@ public final class Workspace extends Home {
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();
@@ -172,7 +169,6 @@ public final class Workspace extends Home {
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest);
LauncherInstrumentation.log("dragIconToWorkspace: end");
launcher.waitUntilGone("drop_target_bar");
- launcher.getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
}
/**