Merge "Possibly fix the widget restoration bug" into udc-dev
diff --git a/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
index b13e8dc..225b4cd 100644
--- a/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
+++ b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
@@ -157,6 +157,7 @@
android:layout_marginVertical="16dp"
android:text="@string/gesture_tutorial_action_button_label"
android:background="@drawable/gesture_tutorial_action_button_background"
+ android:backgroundTint="?androidprv:attr/materialColorPrimary"
android:stateListAnimator="@null"
app:layout_constraintTop_toBottomOf="@id/guideline"
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index 3bd0df0..64ad1f7 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -175,6 +175,7 @@
android:paddingEnd="26dp"
android:text="@string/gesture_tutorial_action_button_label"
android:background="@drawable/gesture_tutorial_action_button_background"
+ android:backgroundTint="?android:attr/colorAccent"
android:stateListAnimator="@null"
android:visibility="invisible"
diff --git a/quickstep/res/layout/gesture_tutorial_mock_task_view.xml b/quickstep/res/layout/gesture_tutorial_mock_task_view.xml
deleted file mode 100644
index 047fdb1..0000000
--- a/quickstep/res/layout/gesture_tutorial_mock_task_view.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2023 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@style/GestureTutorialActivity"
- android:id="@+id/overview_gesture_tutorial_shape"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="20dp"
- android:background="?attr/onSurfaceOverview" />
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_step_menu.xml b/quickstep/res/layout/gesture_tutorial_step_menu.xml
index 7a302f4..cf78b1b 100644
--- a/quickstep/res/layout/gesture_tutorial_step_menu.xml
+++ b/quickstep/res/layout/gesture_tutorial_step_menu.xml
@@ -156,6 +156,7 @@
android:layout_marginVertical="16dp"
android:text="@string/gesture_tutorial_action_button_label"
android:background="@drawable/gesture_tutorial_action_button_background"
+ android:backgroundTint="?androidprv:attr/materialColorPrimary"
android:stateListAnimator="@null"
app:layout_constraintTop_toBottomOf="@id/guideline"
diff --git a/quickstep/res/layout/swipe_up_gesture_tutorial_shape.xml b/quickstep/res/layout/swipe_up_gesture_tutorial_shape.xml
deleted file mode 100644
index d60e84f..0000000
--- a/quickstep/res/layout/swipe_up_gesture_tutorial_shape.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2023 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@style/GestureTutorialActivity"
- android:id="@+id/swipe_up_gesture_tutorial_shape"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?attr/surfaceHome" />
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 6915417..612682a 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -223,6 +223,8 @@
<style name="OverviewActionButton"
parent="@android:style/Widget.DeviceDefault.Button.Borderless">
+ <item name="android:paddingTop">4dp</item>
+ <item name="android:paddingBottom">4dp</item>
<item name="android:textColor">@color/overview_button</item>
<item name="android:drawableTint">@color/overview_button</item>
<item name="android:tint">?android:attr/textColorPrimary</item>
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index 7bd8898..3230c66 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -185,8 +185,8 @@
return false;
}
boolean traverseBackwards = (keyCode == KeyEvent.KEYCODE_TAB && event.isShiftPressed())
- || (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && !isRTL)
- || (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && isRTL);
+ || (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && isRTL)
+ || (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && !isRTL);
int taskCount = mControllerCallbacks.getTaskCount();
int toIndex = mCurrentFocusIndex == -1
// Focus the second-most recent app if possible
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index 163c36f..f5ba8f9 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -84,6 +84,8 @@
}
activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
+ activityOptions.options.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
options = Pair.create(options.first, activityOptions.options);
if (pendingIntent.isActivity()) {
logAppLaunch(itemInfo);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 928910d..3a6566a 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -147,6 +147,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
@@ -662,6 +663,14 @@
} else {
runningTasks = mGestureState.getRunningTask().getPlaceholderTasks();
}
+
+ // Safeguard against any null tasks being sent to recents view, happens when quickswitching
+ // very quickly w/ split tasks because TopTaskTracker provides stale information compared to
+ // actual running tasks in the recents animation.
+ // TODO(b/236226779), Proper fix (ag/22237143)
+ if (Arrays.stream(runningTasks).anyMatch(Objects::isNull)) {
+ return;
+ }
mRecentsView.onGestureAnimationStart(runningTasks, mDeviceState.getRotationTouchHelper());
}
@@ -915,7 +924,12 @@
if (DesktopTaskView.DESKTOP_MODE_SUPPORTED && targets.hasDesktopTasks()) {
mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets);
} else {
+ int untrimmedAppCount = mRemoteTargetHandles.length;
mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(targets);
+ if (mRemoteTargetHandles.length < untrimmedAppCount && mIsSwipeForSplit) {
+ updateIsGestureForSplit(mRemoteTargetHandles.length);
+ setupRecentsViewUi();
+ }
}
mRecentsAnimationController = controller;
mRecentsAnimationTargets = targets;
@@ -2260,6 +2274,7 @@
targetCompat.taskId == mGestureState.getLastStartedTaskId())
.findFirst();
if (!taskTargetOptional.isPresent()) {
+ ActiveGestureLog.INSTANCE.addLog("No appeared task matching started task id");
finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */);
return;
}
@@ -2267,6 +2282,7 @@
TaskView taskView = mRecentsView == null
? null : mRecentsView.getTaskViewByTaskId(taskTarget.taskId);
if (taskView == null || !taskView.getThumbnail().shouldShowSplashView()) {
+ ActiveGestureLog.INSTANCE.addLog("Invalid task view splash state");
finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */);
return;
}
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index d9c269a..84b90b9 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -29,12 +29,15 @@
import com.android.quickstep.views.DesktopTaskView;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* Glues together the necessary components to animate a remote target using a
* {@link TaskViewSimulator}
*/
public class RemoteTargetGluer {
+ private static final int DEFAULT_NUM_HANDLES = 2;
+
private RemoteTargetHandle[] mRemoteTargetHandles;
private SplitBounds mSplitBounds;
@@ -62,8 +65,9 @@
}
}
- int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds();
- init(context, sizingStrategy, splitIds.length == 2 ? 2 : 1, false /* forDesktop */);
+ // Assume 2 handles needed for split, scale down as needed later on when we actually
+ // get remote targets
+ init(context, sizingStrategy, DEFAULT_NUM_HANDLES, false /* forDesktop */);
}
private void init(Context context, BaseActivityInterface sizingStrategy, int numHandles,
@@ -108,6 +112,17 @@
* the left/top task, index 1 right/bottom.
*/
public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
+ // Resize the mRemoteTargetHandles array since we started assuming split screen, but
+ // targets.apps is the ultimate source of truth here
+ long appCount = Arrays.stream(targets.apps)
+ .filter(app -> app.mode == targets.targetMode)
+ .count();
+ if (appCount < mRemoteTargetHandles.length) {
+ RemoteTargetHandle[] newHandles = new RemoteTargetHandle[(int) appCount];
+ System.arraycopy(mRemoteTargetHandles, 0/*src*/, newHandles, 0/*dst*/, (int) appCount);
+ mRemoteTargetHandles = newHandles;
+ }
+
if (mRemoteTargetHandles.length == 1) {
// If we're not in split screen, the splitIds count doesn't really matter since we
// should always hit this case.
@@ -233,6 +248,14 @@
targets.targetMode);
}
+ /**
+ * The object returned by this is may be modified in
+ * {@link #assignTargetsForSplitScreen(RemoteAnimationTargets)}, specifically the length of the
+ * array may be shortened based on the number of RemoteAnimationTargets present.
+ * <p>
+ * This can be accessed at any time, however the count will be more accurate if accessed after
+ * calling one of the respective assignTargets*() methods
+ */
public RemoteTargetHandle[] getRemoteTargetHandles() {
return mRemoteTargetHandles;
}
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 1b4fdc4..25ac47a 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -82,7 +82,8 @@
mContext = context;
mDeviceState = deviceState;
mGestureState = gestureState;
- mIsSwipeForSplit = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds().length > 1;
+ updateIsGestureForSplit(TopTaskTracker.INSTANCE.get(context)
+ .getRunningSplitTaskIds().length);
mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getActivityInterface());
mRemoteTargetHandles = mTargetGluer.getRemoteTargetHandles();
@@ -280,6 +281,10 @@
return out;
}
+ protected void updateIsGestureForSplit(int targetCount) {
+ mIsSwipeForSplit = targetCount > 1;
+ }
+
private RectFSpringAnim getWindowAnimationToHomeInternal(
HomeAnimationFactory homeAnimationFactory, RectF targetRect,
TransformParams transformParams, TaskViewSimulator taskViewSimulator,
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 4c4b9b4..410ba21 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
@@ -174,16 +175,21 @@
if (nonAppTargets == null) {
nonAppTargets = new RemoteAnimationTarget[0];
}
- if (activityInterface.isInLiveTileMode()
+ if ((activityInterface.isInLiveTileMode()
+ || mLastGestureState.getEndTarget() == RECENTS)
&& activityInterface.getCreatedActivity() != null) {
RecentsView recentsView =
activityInterface.getCreatedActivity().getOverviewPanel();
if (recentsView != null) {
+ ActiveGestureLog.INSTANCE.addLog("Launching side task id="
+ + appearedTaskTarget.taskId);
recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId,
appearedTaskTargets,
new RemoteAnimationTarget[0] /* wallpaper */,
nonAppTargets /* nonApps */);
return;
+ } else {
+ ActiveGestureLog.INSTANCE.addLog("Unable to launch side task (no recents)");
}
} else if (nonAppTargets.length > 0) {
TaskViewUtils.createSplitAuxiliarySurfacesAnimator(nonAppTargets /* nonApps */,
diff --git a/quickstep/src/com/android/quickstep/interaction/AnimatedTaskView.java b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskView.java
index 44b3d62..742b0fc 100644
--- a/quickstep/src/com/android/quickstep/interaction/AnimatedTaskView.java
+++ b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskView.java
@@ -15,10 +15,6 @@
*/
package com.android.quickstep.interaction;
-import static com.android.launcher3.QuickstepTransitionManager.ANIMATION_NAV_FADE_OUT_DURATION;
-import static com.android.launcher3.QuickstepTransitionManager.NAV_FADE_OUT_INTERPOLATOR;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
import android.animation.Animator;
@@ -28,30 +24,19 @@
import android.animation.ValueAnimator;
import android.annotation.ColorInt;
import android.content.Context;
-import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Display;
-import android.view.RoundedCorner;
import android.view.View;
import android.view.ViewOutlineProvider;
-import android.view.animation.ScaleAnimation;
-import android.view.animation.TranslateAnimation;
-import android.widget.ViewAnimator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
-import com.android.quickstep.util.MultiValueUpdateListener;
import java.util.ArrayList;
-import java.util.Arrays;
/**
* Helper View for the gesture tutorial mock previous app task view.
@@ -61,8 +46,6 @@
*/
public class AnimatedTaskView extends ConstraintLayout {
- private static final long ANIMATE_TO_FULL_SCREEN_DURATION = 300;
-
private View mFullTaskView;
private View mTopTaskView;
private View mBottomTaskView;
@@ -72,17 +55,16 @@
private float mTaskViewAnimatedRadius;
public AnimatedTaskView(@NonNull Context context) {
- super(context);
+ this(context, null);
}
- public AnimatedTaskView(@NonNull Context context,
- @Nullable AttributeSet attrs) {
- super(context, attrs);
+ public AnimatedTaskView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
}
public AnimatedTaskView(
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
+ this(context, attrs, defStyleAttr, 0);
}
public AnimatedTaskView(
@@ -104,97 +86,6 @@
setToSingleRowLayout(false);
}
- void animateToFillScreen(@Nullable Runnable onAnimationEndCallback) {
- if (mTaskViewOutlineProvider == null) {
- // This is an illegal state.
- return;
- }
- // calculate start and end corner radius
- Outline startOutline = new Outline();
- mTaskViewOutlineProvider.getOutline(this, startOutline);
- Rect outlineStartRect = new Rect();
- startOutline.getRect(outlineStartRect);
- float outlineStartRadius = startOutline.getRadius();
-
- final Display display = mContext.getDisplay();;
- RoundedCorner corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
- float outlineEndRadius = corner.getRadius();
-
- // create animation
- AnimatorSet set = new AnimatorSet();
- ArrayList<Animator> animations = new ArrayList<>();
-
- // center view
- animations.add(ObjectAnimator.ofFloat(this, TRANSLATION_X, 0));
-
- // retrieve start animation matrix to scale off of
- Matrix matrix = getAnimationMatrix();
- if (matrix == null) {
- // This is an illegal state.
- return;
- }
-
- float[] matrixValues = new float[9];
- matrix.getValues(matrixValues);
- float[] newValues = matrixValues.clone();
-
- ValueAnimator transformAnimation = ValueAnimator.ofFloat(0, 1);
-
- MultiValueUpdateListener listener = new MultiValueUpdateListener() {
- Matrix currentMatrix = new Matrix();
-
- FloatProp mOutlineRadius = new FloatProp(outlineStartRadius, outlineEndRadius, 0,
- ANIMATE_TO_FULL_SCREEN_DURATION, LINEAR);
- FloatProp mTransX = new FloatProp(matrixValues[Matrix.MTRANS_X], 0f, 0,
- ANIMATE_TO_FULL_SCREEN_DURATION, LINEAR);
- FloatProp mTransY = new FloatProp(matrixValues[Matrix.MTRANS_Y], 0f, 0,
- ANIMATE_TO_FULL_SCREEN_DURATION, LINEAR);
- FloatProp mScaleX = new FloatProp(matrixValues[Matrix.MSCALE_X], 1f, 0,
- ANIMATE_TO_FULL_SCREEN_DURATION, LINEAR);
- FloatProp mScaleY = new FloatProp(matrixValues[Matrix.MSCALE_Y], 1f, 0,
- ANIMATE_TO_FULL_SCREEN_DURATION, LINEAR);
-
- @Override
- public void onUpdate(float percent, boolean initOnly) {
- // scale corner radius to match display radius
- mTaskViewAnimatedRadius = mOutlineRadius.value;
- mFullTaskView.invalidateOutline();
-
- // translate to center, ends at translation x:0, y:0
- newValues[Matrix.MTRANS_X] = mTransX.value;
- newValues[Matrix.MTRANS_Y] = mTransY.value;
-
- // scale to full size, ends at scale 1
- newValues[Matrix.MSCALE_X] = mScaleX.value;
- newValues[Matrix.MSCALE_Y] = mScaleY.value;
-
- // create and set new animation matrix
- currentMatrix.setValues(newValues);
- setAnimationMatrix(currentMatrix);
- }
- };
-
- transformAnimation.addUpdateListener(listener);
- animations.add(transformAnimation);
- set.playSequentially(animations);
- set.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- addAnimatedOutlineProvider(mFullTaskView, outlineStartRect, outlineStartRadius);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- if (onAnimationEndCallback != null) {
- onAnimationEndCallback.run();
- }
- }
- });
- set.start();
- }
-
AnimatorSet createAnimationToMultiRowLayout() {
if (mTaskViewOutlineProvider == null) {
// This is an illegal state.
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 17e57bf..54c441b 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -136,7 +136,7 @@
}
@Override
- protected int getSwipeActionColor() {
+ protected int getFakeLauncherColor() {
return mTutorialFragment.mRootView.mColorSurfaceContainer;
}
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index 0012d47..891f20e 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -104,11 +104,9 @@
@Override
protected int getMockAppTaskLayoutResId() {
- return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
- ? R.layout.swipe_up_gesture_tutorial_shape
- : mTutorialFragment.isLargeScreen()
- ? R.layout.gesture_tutorial_tablet_mock_webpage
- : R.layout.gesture_tutorial_mock_webpage;
+ return mTutorialFragment.isLargeScreen()
+ ? R.layout.gesture_tutorial_tablet_mock_webpage
+ : R.layout.gesture_tutorial_mock_webpage;
}
@Override
@@ -121,7 +119,12 @@
}
@Override
- protected int getSwipeActionColor() {
+ protected int getFakeTaskViewColor() {
+ return isGestureCompleted() ? getFakeLauncherColor() : getExitingAppColor();
+ }
+
+ @Override
+ protected int getFakeLauncherColor() {
return mTutorialFragment.mRootView.mColorSurfaceContainer;
}
@@ -148,7 +151,7 @@
case BACK_CANCELLED_FROM_LEFT:
case BACK_CANCELLED_FROM_RIGHT:
case BACK_NOT_STARTED_TOO_FAR_FROM_EDGE:
- resetTaskView();
+ resetTaskViews();
showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge);
break;
}
@@ -178,18 +181,18 @@
}
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
- resetTaskView();
+ resetTaskViews();
showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge);
break;
case OVERVIEW_GESTURE_COMPLETED:
- fadeOutFakeTaskView(true, true, () -> {
+ fadeOutFakeTaskView(true, () -> {
showFeedback(R.string.home_gesture_feedback_overview_detected);
showFakeTaskbar(/* animateFromHotseat= */ false);
});
break;
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
case HOME_OR_OVERVIEW_CANCELLED:
- fadeOutFakeTaskView(false, true, null);
+ fadeOutFakeTaskView(false, null);
showFeedback(R.string.home_gesture_feedback_wrong_swipe_direction);
break;
}
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 593e6d9..667fe4d 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -25,7 +25,9 @@
import android.graphics.PointF;
import android.os.Build;
import android.os.Handler;
-import android.view.View;
+
+import androidx.annotation.ColorInt;
+import androidx.core.graphics.ColorUtils;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -43,6 +45,8 @@
@TargetApi(Build.VERSION_CODES.R)
final class OverviewGestureTutorialController extends SwipeUpGestureTutorialController {
+ private static final float LAUNCHER_COLOR_BLENDING_RATIO = 0.4f;
+
OverviewGestureTutorialController(OverviewGestureTutorialFragment fragment,
TutorialType tutorialType) {
super(fragment, tutorialType);
@@ -112,11 +116,9 @@
@Override
protected int getMockAppTaskLayoutResId() {
- return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
- ? R.layout.gesture_tutorial_mock_task_view
- : mTutorialFragment.isLargeScreen()
- ? R.layout.gesture_tutorial_tablet_mock_conversation_list
- : R.layout.gesture_tutorial_mock_conversation_list;
+ return mTutorialFragment.isLargeScreen()
+ ? R.layout.gesture_tutorial_tablet_mock_conversation_list
+ : R.layout.gesture_tutorial_mock_conversation_list;
}
@Override
@@ -128,11 +130,31 @@
: R.raw.overview_gesture_tutorial_animation;
}
- @Override
- protected int getSwipeActionColor() {
+ @ColorInt
+ private int getFakeTaskViewStartColor() {
return mTutorialFragment.mRootView.mColorSurfaceOverview;
}
+ @ColorInt
+ private int getFakeTaskViewEndColor() {
+ return getMockPreviousAppTaskThumbnailColor();
+ }
+
+ @Override
+ protected int getFakeTaskViewColor() {
+ return isGestureCompleted()
+ ? getFakeTaskViewEndColor()
+ : getFakeTaskViewStartColor();
+ }
+
+ @Override
+ protected int getFakeLauncherColor() {
+ return ColorUtils.blendARGB(
+ mTutorialFragment.mRootView.mColorSurfaceContainer,
+ mTutorialFragment.mRootView.mColorOnSurfaceOverview,
+ LAUNCHER_COLOR_BLENDING_RATIO);
+ }
+
@Override
protected int getHotseatIconColor() {
return mTutorialFragment.mRootView.mColorOnSurfaceOverview;
@@ -159,7 +181,7 @@
case BACK_CANCELLED_FROM_LEFT:
case BACK_CANCELLED_FROM_RIGHT:
case BACK_NOT_STARTED_TOO_FAR_FROM_EDGE:
- resetTaskView();
+ resetTaskViews();
showFeedback(R.string.overview_gesture_feedback_swipe_too_far_from_edge);
break;
}
@@ -190,7 +212,7 @@
}
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
- resetTaskView();
+ resetTaskViews();
showFeedback(R.string.overview_gesture_feedback_swipe_too_far_from_edge);
break;
case OVERVIEW_GESTURE_COMPLETED:
@@ -204,7 +226,7 @@
break;
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
case HOME_OR_OVERVIEW_CANCELLED:
- fadeOutFakeTaskView(false, true, null);
+ fadeOutFakeTaskView(false, null);
showFeedback(R.string.overview_gesture_feedback_wrong_swipe_direction);
break;
}
@@ -229,15 +251,21 @@
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
- new Handler().postDelayed(() -> {
- mFakeTaskView.setVisibility(View.INVISIBLE);
- if (!mTutorialFragment.isLargeScreen()) {
- mFakePreviousTaskView.animateToFillScreen(
- () -> onSuccessAnimationComplete());
- } else {
- onSuccessAnimationComplete();
- }
- }, TASK_VIEW_FILL_SCREEN_ANIMATION_DELAY_MILLIS);
+ new Handler().postDelayed(
+ () -> fadeOutFakeTaskView(
+ /* toOverviewFirst= */ true,
+ /* animatePreviousTask= */ false,
+ /* resetViews= */ false,
+ /* updateListener= */ v -> mFakeTaskView.setBackgroundColor(
+ ColorUtils.blendARGB(
+ getFakeTaskViewStartColor(),
+ getFakeTaskViewEndColor(),
+ v.getAnimatedFraction())),
+ /* onEndRunnable= */ () -> {
+ showSuccessFeedback();
+ resetTaskViews();
+ }),
+ TASK_VIEW_FILL_SCREEN_ANIMATION_DELAY_MILLIS);
}
});
}
@@ -259,9 +287,4 @@
animset.start();
mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
}
-
- private void onSuccessAnimationComplete() {
- mFakeLauncherView.setBackgroundColor(getMockPreviousAppTaskThumbnailColor());
- showSuccessFeedback();
- }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 66c659a..0bbf373 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -78,7 +78,7 @@
private final AnimatorListenerAdapter mResetTaskView = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- resetTaskView();
+ resetTaskViews();
}
};
@@ -122,7 +122,7 @@
mRunningWindowAnim = null;
}
- void resetTaskView() {
+ void resetTaskViews() {
mFakeHotseatView.setVisibility(View.INVISIBLE);
mFakeIconView.setVisibility(View.INVISIBLE);
if (mTutorialFragment.getActivity() != null) {
@@ -141,10 +141,21 @@
mShowPreviousTasks = false;
mRunningWindowAnim = null;
}
+ void fadeOutFakeTaskView(boolean toOverviewFirst, @Nullable Runnable onEndRunnable) {
+ fadeOutFakeTaskView(
+ toOverviewFirst,
+ /* animatePreviousTask= */ true,
+ /* resetViews= */ true,
+ /* updateListener= */ null,
+ onEndRunnable);
+ }
/** Fades the task view, optionally after animating to a fake Overview. */
- void fadeOutFakeTaskView(boolean toOverviewFirst, boolean reset,
- @Nullable Runnable onEndRunnable) {
+ void fadeOutFakeTaskView(boolean toOverviewFirst,
+ boolean animatePreviousTask,
+ boolean resetViews,
+ @Nullable ValueAnimator.AnimatorUpdateListener updateListener,
+ @Nullable Runnable onEndRunnable) {
cancelRunningAnimation();
PendingAnimation anim = new PendingAnimation(300);
if (toOverviewFirst) {
@@ -155,20 +166,20 @@
public void onAnimationEnd(Animator animation, boolean isReverse) {
PendingAnimation fadeAnim =
new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
- if (reset) {
- fadeAnim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+ fadeAnim.setFloat(mTaskViewSwipeUpAnimation
+ .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+ if (resetViews) {
fadeAnim.addListener(mResetTaskView);
- } else {
- fadeAnim.setViewAlpha(mFakeTaskView, 0, ACCEL);
- fadeAnim.setViewAlpha(mFakePreviousTaskView, 0, ACCEL);
}
if (onEndRunnable != null) {
fadeAnim.addListener(AnimatorListeners.forSuccessCallback(onEndRunnable));
}
+ if (updateListener != null) {
+ fadeAnim.addOnFrameListener(updateListener);
+ }
AnimatorSet animset = fadeAnim.buildAnim();
- if (reset && mTutorialFragment.isLargeScreen()) {
+ if (animatePreviousTask && mTutorialFragment.isLargeScreen()) {
animset.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -190,13 +201,10 @@
}
});
} else {
- if (reset) {
- anim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+ anim.setFloat(mTaskViewSwipeUpAnimation
+ .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+ if (resetViews) {
anim.addListener(mResetTaskView);
- } else {
- anim.setViewAlpha(mFakeTaskView, 0, ACCEL);
- anim.setViewAlpha(mFakePreviousTaskView, 0, ACCEL);
}
if (onEndRunnable != null) {
anim.addListener(AnimatorListeners.forSuccessCallback(onEndRunnable));
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 36655d2..084f8c1 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -268,7 +268,12 @@
}
@ColorInt
- protected abstract int getSwipeActionColor();
+ protected int getFakeTaskViewColor() {
+ return Color.TRANSPARENT;
+ }
+
+ @ColorInt
+ protected abstract int getFakeLauncherColor();
@ColorInt
protected int getExitingAppColor() {
@@ -445,6 +450,7 @@
}
private void showSuccessPage() {
+ pauseAndHideLottieAnimation();
mCheckmarkAnimation.setVisibility(View.VISIBLE);
mCheckmarkAnimation.playAnimation();
mFeedbackTitleView.setTextAppearance(mContext, getSuccessTitleTextAppearance());
@@ -591,7 +597,7 @@
protected void resetViewsForBackGesture() {
mFakeTaskView.setVisibility(View.VISIBLE);
- mFakeTaskView.setBackgroundColor(getSwipeActionColor());
+ mFakeTaskView.setBackgroundColor(getFakeTaskViewColor());
mExitingAppView.setVisibility(View.VISIBLE);
// reset the exiting app's dimensions
@@ -690,11 +696,10 @@
mContext, getMockWallpaperResId()));
mTutorialFragment.updateFeedbackAnimation();
mFakeLauncherView.setBackgroundColor(ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
- ? getSwipeActionColor()
+ ? getFakeLauncherColor()
: mContext.getColor(R.color.gesture_tutorial_fake_wallpaper_color));
updateFakeViewLayout(mFakeHotseatView, getMockHotseatResId());
mHotseatIconView = mFakeHotseatView.findViewById(R.id.hotseat_icon_1);
- updateFakeViewLayout(mFakeTaskView, getMockAppTaskLayoutResId());
mFakeTaskView.animate().alpha(1).setListener(
AnimatorListeners.forSuccessCallback(() -> mFakeTaskView.animate().cancel()));
mFakePreviousTaskView.setFakeTaskViewFillColor(getMockPreviousAppTaskThumbnailColor());
@@ -703,12 +708,15 @@
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
mExitingAppView.setBackgroundColor(getExitingAppColor());
+ mFakeTaskView.setBackgroundColor(getFakeTaskViewColor());
updateHotseatChildViewColor(mFakeIconView);
updateHotseatChildViewColor(mFakeHotseatView.findViewById(R.id.hotseat_icon_2));
updateHotseatChildViewColor(mFakeHotseatView.findViewById(R.id.hotseat_icon_3));
updateHotseatChildViewColor(mFakeHotseatView.findViewById(R.id.hotseat_icon_4));
updateHotseatChildViewColor(mFakeHotseatView.findViewById(R.id.hotseat_icon_5));
updateHotseatChildViewColor(mFakeHotseatView.findViewById(R.id.hotseat_search_bar));
+ } else {
+ updateFakeViewLayout(mFakeTaskView, getMockAppTaskLayoutResId());
}
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 9f15e19..bfad643 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -143,6 +143,7 @@
return null;
}
+ @NonNull
abstract TutorialController createController(TutorialType type);
abstract Class<? extends TutorialController> getControllerClass();
@@ -374,9 +375,15 @@
void changeController(TutorialType tutorialType) {
if (getControllerClass().isInstance(mTutorialController)) {
mTutorialController.setTutorialType(tutorialType);
+ if (isGestureComplete()) {
+ mTutorialController.setGestureCompleted();
+ }
mTutorialController.fadeTaskViewAndRun(mTutorialController::transitToController);
} else {
mTutorialController = createController(tutorialType);
+ if (isGestureComplete()) {
+ mTutorialController.setGestureCompleted();
+ }
mTutorialController.transitToController();
}
mEdgeBackGestureHandler.registerBackGestureAttemptCallback(mTutorialController);
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
index 614dfe8..8e6415b 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
@@ -61,7 +61,8 @@
*/
companion object {
@IntDef(SPLIT_TASK_TASK, SPLIT_TASK_PENDINGINTENT, SPLIT_TASK_SHORTCUT,
- SPLIT_PENDINGINTENT_TASK, SPLIT_PENDINGINTENT_PENDINGINTENT, SPLIT_SHORTCUT_TASK)
+ SPLIT_PENDINGINTENT_TASK, SPLIT_PENDINGINTENT_PENDINGINTENT, SPLIT_SHORTCUT_TASK,
+ SPLIT_SINGLE_TASK_FULLSCREEN, SPLIT_SINGLE_INTENT_FULLSCREEN)
@Retention(AnnotationRetention.SOURCE)
annotation class SplitLaunchType
@@ -71,6 +72,10 @@
const val SPLIT_PENDINGINTENT_TASK = 3
const val SPLIT_SHORTCUT_TASK = 4
const val SPLIT_PENDINGINTENT_PENDINGINTENT = 5
+
+ // Non-split edge case of launching the initial selected task as a fullscreen task
+ const val SPLIT_SINGLE_TASK_FULLSCREEN = 6
+ const val SPLIT_SINGLE_INTENT_FULLSCREEN = 7
}
@@ -190,7 +195,7 @@
/**
* @return [SplitLaunchData] with the necessary fields populated as determined by
- * [SplitLaunchData.splitLaunchType]
+ * [SplitLaunchData.splitLaunchType]. This is to be used for launching splitscreen
*/
fun getSplitLaunchData() : SplitLaunchData {
// Convert all intents to shortcut infos to see if determine if we launch shortcut or intent
@@ -201,6 +206,24 @@
initialStagePosition = getOppositeStagePosition(initialStagePosition)
}
+ return generateSplitLaunchData(splitLaunchType)
+ }
+
+ /**
+ * @return [SplitLaunchData] with the necessary fields populated as determined by
+ * [SplitLaunchData.splitLaunchType]. This is to be used for launching an initially selected
+ * split task in fullscreen
+ */
+ fun getFullscreenLaunchData() : SplitLaunchData {
+ // Convert all intents to shortcut infos to see if determine if we launch shortcut or intent
+ convertIntentsToFinalTypes()
+ val splitLaunchType = if (initialTaskId != INVALID_TASK_ID) SPLIT_SINGLE_TASK_FULLSCREEN
+ else SPLIT_SINGLE_INTENT_FULLSCREEN
+
+ return generateSplitLaunchData(splitLaunchType)
+ }
+
+ private fun generateSplitLaunchData(@SplitLaunchType splitLaunchType: Int) : SplitLaunchData {
return SplitLaunchData(
splitLaunchType,
initialTaskId,
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index ee51af7..ec8be89 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -27,6 +27,8 @@
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_PENDINGINTENT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_TASK;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SHORTCUT_TASK;
+import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SINGLE_INTENT_FULLSCREEN;
+import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SINGLE_TASK_FULLSCREEN;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDINGINTENT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;
@@ -324,11 +326,8 @@
}
boolean hasSecondaryPendingIntent = mSecondPendingIntent != null;
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
- final RemoteSplitLaunchTransitionRunner animationRunner =
- new RemoteSplitLaunchTransitionRunner(taskId1, taskId2, callback);
- final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
- ActivityThread.currentActivityThread().getApplicationThread(),
- "LaunchSplitPair");
+ final RemoteTransition remoteTransition = getShellRemoteTransition(taskId1, taskId2,
+ callback);
if (intent1 == null && (intent2 == null && !hasSecondaryPendingIntent)) {
mSystemUiProxy.startTasks(taskId1, options1.toBundle(), taskId2,
null /* options2 */, stagePosition, splitRatio, remoteTransition,
@@ -351,11 +350,8 @@
shellInstanceId);
}
} else {
- final RemoteSplitLaunchAnimationRunner animationRunner =
- new RemoteSplitLaunchAnimationRunner(taskId1, taskId2, callback);
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- animationRunner, 300, 150,
- ActivityThread.currentActivityThread().getApplicationThread());
+ final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(taskId1, taskId2,
+ callback);
if (intent1 == null && (intent2 == null && !hasSecondaryPendingIntent)) {
mSystemUiProxy.startTasksWithLegacyTransition(taskId1, options1.toBundle(),
@@ -402,11 +398,8 @@
Bundle optionsBundle = options1.toBundle();
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
- final RemoteSplitLaunchTransitionRunner animationRunner =
- new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
- final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
- ActivityThread.currentActivityThread().getApplicationThread(),
- "LaunchSplitPair");
+ final RemoteTransition remoteTransition = getShellRemoteTransition(firstTaskId,
+ secondTaskId, callback);
switch (launchData.getSplitLaunchType()) {
case SPLIT_TASK_TASK ->
mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
@@ -440,11 +433,8 @@
remoteTransition, shellInstanceId);
}
} else {
- final RemoteSplitLaunchAnimationRunner animationRunner =
- new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- animationRunner, 300, 150,
- ActivityThread.currentActivityThread().getApplicationThread());
+ final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId, secondTaskId,
+ callback);
switch (launchData.getSplitLaunchType()) {
case SPLIT_TASK_TASK ->
mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
@@ -501,26 +491,90 @@
Bundle optionsBundle = options1.toBundle();
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
- final RemoteSplitLaunchTransitionRunner animationRunner =
- new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
- final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
- ActivityThread.currentActivityThread().getApplicationThread(),
- "LaunchSplitPair");
+ final RemoteTransition remoteTransition = getShellRemoteTransition(firstTaskId,
+ secondTaskId, callback);
mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
null /* options2 */, stagePosition, splitRatio,
remoteTransition, null /*shellInstanceId*/);
} else {
- final RemoteSplitLaunchAnimationRunner animationRunner =
- new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- animationRunner, 300, 150,
- ActivityThread.currentActivityThread().getApplicationThread());
+ final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
+ secondTaskId, callback);
mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
secondTaskId, null /* options2 */, stagePosition,
splitRatio, adapter, null /*shellInstanceId*/);
}
}
+ /**
+ * Launches the initially selected task/intent in fullscreen (note the same SystemUi APIs are
+ * used as {@link #launchSplitTasks(Consumer)} because they are overloaded to launch both
+ * split and fullscreen tasks)
+ */
+ public void launchInitialAppFullscreen(Consumer<Boolean> callback) {
+ if (!FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
+ launchSplitTasks(callback);
+ return;
+ }
+
+ final ActivityOptions options1 = ActivityOptions.makeBasic();
+ SplitSelectDataHolder.SplitLaunchData launchData =
+ mSplitSelectDataHolder.getFullscreenLaunchData();
+ int firstTaskId = launchData.getInitialTaskId();
+ int secondTaskId = launchData.getSecondTaskId();
+ PendingIntent firstPI = launchData.getInitialPendingIntent();
+ int firstUserId = launchData.getInitialUserId();
+ int initialStagePosition = launchData.getInitialStagePosition();
+ Bundle optionsBundle = options1.toBundle();
+
+ final RemoteSplitLaunchTransitionRunner animationRunner =
+ new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
+ final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
+ ActivityThread.currentActivityThread().getApplicationThread(),
+ "LaunchSplitPair");
+ Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
+ LogUtils.getShellShareableInstanceId();
+ if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
+ switch (launchData.getSplitLaunchType()) {
+ case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasks(firstTaskId,
+ optionsBundle, secondTaskId, null /* options2 */, initialStagePosition,
+ DEFAULT_SPLIT_RATIO, remoteTransition, instanceIds.first);
+ case SPLIT_SINGLE_INTENT_FULLSCREEN -> mSystemUiProxy.startIntentAndTask(firstPI,
+ firstUserId, optionsBundle, secondTaskId, null /*options2*/,
+ initialStagePosition, DEFAULT_SPLIT_RATIO, remoteTransition,
+ instanceIds.first);
+ }
+ } else {
+ final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
+ secondTaskId, callback);
+ switch (launchData.getSplitLaunchType()) {
+ case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasksWithLegacyTransition(
+ firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
+ initialStagePosition, DEFAULT_SPLIT_RATIO, adapter, instanceIds.first);
+ case SPLIT_SINGLE_INTENT_FULLSCREEN ->
+ mSystemUiProxy.startIntentAndTaskWithLegacyTransition(firstPI, firstUserId,
+ optionsBundle, secondTaskId, null /*options2*/,
+ initialStagePosition, DEFAULT_SPLIT_RATIO, adapter,
+ instanceIds.first);
+ }
+ }
+ }
+
+ private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId,
+ Consumer<Boolean> callback) {
+ final RemoteSplitLaunchTransitionRunner animationRunner =
+ new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
+ return new RemoteTransition(animationRunner,
+ ActivityThread.currentActivityThread().getApplicationThread(), "LaunchSplitPair");
+ }
+
+ private RemoteAnimationAdapter getLegacyRemoteAdapter(int firstTaskId, int secondTaskId,
+ Consumer<Boolean> callback) {
+ final RemoteSplitLaunchAnimationRunner animationRunner =
+ new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
+ return new RemoteAnimationAdapter(animationRunner, 300, 150,
+ ActivityThread.currentActivityThread().getApplicationThread());
+ }
+
private void launchIntentOrShortcut(Intent intent, UserHandle user, ActivityOptions options1,
int taskId, @StagePosition int stagePosition, float splitRatio,
RemoteTransition remoteTransition, @Nullable InstanceId shellInstanceId) {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index d8fe32d..f740d9c 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -3260,7 +3260,7 @@
true /* isStagedTask */);
pendingAnimation.addEndListener(animationSuccess ->
- mSplitSelectStateController.launchSplitTasks(launchSuccess ->
+ mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess ->
resetFromSplitSelectionState()));
pendingAnimation.buildAnim().start();
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 617afcb..c20494d 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -20,6 +20,8 @@
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
+import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
+import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -560,6 +562,7 @@
synchronized (mLock) {
// Everything loaded bind the data.
mModelLoaded = true;
+ testLogD(WORK_TAB_MISSING, "launcher model loaded");
}
}
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 2ce6c78..dd82ecf 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -273,6 +273,8 @@
// {@link #onAnimationEnd} before B reads new UI state from {@link #onAnimationStart}.
a.addListener(new AnimatorListenerAdapter() {
private CellLayout mCellLayout;
+
+ private boolean mFolderClipChildren;
private boolean mFolderClipToPadding;
private boolean mContentClipChildren;
private boolean mContentClipToPadding;
@@ -283,12 +285,14 @@
public void onAnimationStart(Animator animator) {
super.onAnimationStart(animator);
mCellLayout = mContent.getCurrentCellLayout();
+ mFolderClipChildren = mFolder.getClipChildren();
mFolderClipToPadding = mFolder.getClipToPadding();
mContentClipChildren = mContent.getClipChildren();
mContentClipToPadding = mContent.getClipToPadding();
mCellLayoutClipChildren = mCellLayout.getClipChildren();
mCellLayoutClipPadding = mCellLayout.getClipToPadding();
+ mFolder.setClipChildren(false);
mFolder.setClipToPadding(false);
mContent.setClipChildren(false);
mContent.setClipToPadding(false);
@@ -309,6 +313,7 @@
mFolder.mFooter.setTranslationX(0f);
mFolder.mFolderName.setAlpha(1f);
+ mFolder.setClipChildren(mFolderClipChildren);
mFolder.setClipToPadding(mFolderClipToPadding);
mContent.setClipChildren(mContentClipChildren);
mContent.setClipToPadding(mContentClipToPadding);
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index 70c9802..44d32d9 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -16,6 +16,7 @@
package com.android.launcher3.model;
import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
+import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
import android.util.Log;
@@ -72,7 +73,9 @@
@Override
public final void run() {
- if (!Objects.requireNonNull(mModel).isModelLoaded()) {
+ boolean isModelLoaded = Objects.requireNonNull(mModel).isModelLoaded();
+ testLogD(WORK_TAB_MISSING, "modelLoaded: " + isModelLoaded + " forTask: " + this);
+ if (!isModelLoaded) {
if (DEBUG_TASKS) {
Log.d(TAG, "Ignoring model task since loader is pending=" + this);
}
diff --git a/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java
index 2742882..580b4f1 100644
--- a/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/BaseLauncherAppWidgetHostView.java
@@ -105,6 +105,7 @@
mEnforcedRectangle);
setOutlineProvider(mCornerRadiusEnforcementOutline);
setClipToOutline(true);
+ invalidateOutline();
}
/** Returns the corner radius currently enforced, in pixels. */
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index 723ea17..8dd1de4 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -42,7 +42,6 @@
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.launcher3.R;
-import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.recyclerview.ViewHolderBinder;
import com.android.launcher3.util.LabelComparator;
import com.android.launcher3.util.PackageUserKey;
@@ -58,7 +57,6 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import java.util.Map;
import java.util.OptionalInt;
import java.util.function.IntSupplier;
import java.util.function.Predicate;
@@ -174,9 +172,6 @@
mAllEntries.clear();
mAllEntries.add(new WidgetListSpaceEntry());
tempEntries.stream().sorted(mRowComparator).forEach(mAllEntries::add);
- if (shouldClearVisibleEntries()) {
- mVisibleEntries.clear();
- }
updateVisibleEntries();
}
@@ -426,29 +421,6 @@
updateVisibleEntries();
}
- /**
- * Returns {@code true} if there is a change in {@link #mAllEntries} that results in an
- * invalidation of {@link #mVisibleEntries}. e.g. there is change in the device language.
- */
- private boolean shouldClearVisibleEntries() {
- Map<PackageUserKey, PackageItemInfo> packagesInfo =
- mAllEntries.stream()
- .filter(entry -> entry instanceof WidgetsListHeaderEntry)
- .map(entry -> entry.mPkgItem)
- .collect(Collectors.toMap(
- entry -> PackageUserKey.fromPackageItemInfo(entry),
- entry -> entry));
- for (WidgetsListBaseEntry visibleEntry: mVisibleEntries) {
- PackageUserKey key = PackageUserKey.fromPackageItemInfo(visibleEntry.mPkgItem);
- PackageItemInfo packageItemInfo = packagesInfo.get(key);
- if (packageItemInfo != null
- && !visibleEntry.mPkgItem.title.equals(packageItemInfo.title)) {
- return true;
- }
- }
- return false;
- }
-
/** Comparator for sorting WidgetListRowEntry based on package title. */
public static class WidgetListBaseRowEntryComparator implements
Comparator<WidgetsListBaseEntry> {
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 8def7e8..b7c3aca 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -16,6 +16,8 @@
package com.android.launcher3.testing.shared;
+import android.util.Log;
+
/**
* Protocol for custom accessibility events for communication with UI Automation tests.
*/
@@ -161,4 +163,12 @@
public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
public static final String REQUEST_IS_EMULATE_DISPLAY_RUNNING = "is-emulate-display-running";
public static final String REQUEST_EMULATE_PRINT_DEVICE = "emulate-print-device";
+
+ /** Logs {@link Log#d(String, String)} if {@link #sDebugTracing} is true. */
+ public static void testLogD(String tag, String message) {
+ if (!sDebugTracing) {
+ return;
+ }
+ Log.d(tag, message);
+ }
}