diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 4269f2d9061062e7cf0703c5ce34b8e8eade4171..4ceb1957ad74f9b1f2823099cd229963484af88e 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -39,6 +39,7 @@ import android.hardware.SensorManager; import android.hardware.devicestate.DeviceStateManager; import android.os.Bundle; import android.os.CancellationSignal; +import android.os.IBinder; import android.view.View; import android.view.WindowInsets; import android.window.SplashScreen; @@ -513,11 +514,26 @@ public abstract class BaseQuickstepLauncher extends Launcher } /** - * Adds a new launch cookie for the activity launch of the given {@param info} if supported. + * Adds a new launch cookie for the activity launch if supported. + * + * @param info the item info for the launch + * @param opts the options to set the launchCookie on. */ public void addLaunchCookie(ItemInfo info, ActivityOptions opts) { + IBinder launchCookie = getLaunchCookie(info); + if (launchCookie != null) { + opts.setLaunchCookie(launchCookie); + } + } + + /** + * Return a new launch cookie for the activity launch if supported. + * + * @param info the item info for the launch + */ + public IBinder getLaunchCookie(ItemInfo info) { if (info == null) { - return; + return null; } switch (info.container) { case LauncherSettings.Favorites.CONTAINER_DESKTOP: @@ -531,8 +547,7 @@ public abstract class BaseQuickstepLauncher extends Launcher break; } // Reset any existing launch cookies associated with the cookie - opts.setLaunchCookie(ObjectWrapper.wrap(NO_MATCHING_ID)); - return; + return ObjectWrapper.wrap(NO_MATCHING_ID); } switch (info.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: @@ -543,10 +558,9 @@ public abstract class BaseQuickstepLauncher extends Launcher break; default: // Reset any existing launch cookies associated with the cookie - opts.setLaunchCookie(ObjectWrapper.wrap(NO_MATCHING_ID)); - return; + return ObjectWrapper.wrap(NO_MATCHING_ID); } - opts.setLaunchCookie(ObjectWrapper.wrap(new Integer(info.id))); + return ObjectWrapper.wrap(new Integer(info.id)); } public void setHintUserWillBeActive() { diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 49b2cc5894116089ab71471916f35b3da7eeff5d..3b493bbd30540deb6e5ec5138d4459eb6884c696 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -44,6 +44,7 @@ import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; import static com.android.launcher3.statehandlers.DepthController.DEPTH; import static com.android.launcher3.util.DisplayController.getSingleFrameMs; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import static com.android.launcher3.views.FloatingIconView.getFloatingIconView; import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch; @@ -75,6 +76,8 @@ import android.os.IBinder; import android.os.Looper; import android.os.SystemProperties; import android.os.UserHandle; +import android.provider.Settings; +import android.util.Log; import android.util.Pair; import android.util.Size; import android.view.SurfaceControl; @@ -133,6 +136,7 @@ import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.wm.shell.startingsurface.IStartingWindowListener; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; @@ -609,9 +613,28 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener RecentsView overview = mLauncher.getOverviewPanel(); ObjectAnimator alpha = ObjectAnimator.ofFloat(overview, RecentsView.CONTENT_ALPHA, alphas); + Log.d(BAD_STATE, "QTM composeViewContentAnimator alphas=" + Arrays.toString(alphas)); + alpha.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + Log.d(BAD_STATE, "QTM composeViewContentAnimator onStart"); + } + + @Override + public void onAnimationCancel(Animator animation) { + float alpha = overview == null ? -1 : RecentsView.CONTENT_ALPHA.get(overview); + Log.d(BAD_STATE, "QTM composeViewContentAnimator onCancel, alpha=" + alpha); + } + + @Override + public void onAnimationEnd(Animator animation) { + Log.d(BAD_STATE, "QTM composeViewContentAnimator onEnd"); + } + }); alpha.setDuration(CONTENT_ALPHA_DURATION); alpha.setInterpolator(LINEAR); anim.play(alpha); + Log.d(BAD_STATE, "QTM composeViewContentAnimator setFreezeVisibility=true"); overview.setFreezeViewVisibility(true); ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(overview, SCALE_PROPERTY, scales); @@ -620,6 +643,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener anim.play(scaleAnim); return () -> { + Log.d(BAD_STATE, "QTM composeViewContentAnimator onEnd setFreezeVisibility=false"); overview.setFreezeViewVisibility(false); SCALE_PROPERTY.set(overview, 1f); mLauncher.getStateManager().reapplyState(); @@ -1274,8 +1298,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener } } - return mLauncher.getFirstMatchForAppClose(launchCookieItemId, - packageName, UserHandle.of(runningTaskTarget.taskInfo.userId)); + return mLauncher.getFirstMatchForAppClose(launchCookieItemId, packageName, + UserHandle.of(runningTaskTarget.taskInfo.userId), true /* supportsAllAppsState */); } private @NonNull RectF getDefaultWindowTargetRect() { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 5308a8f3e88492fa503685ec8486f0579355435d..c612a845a53840304c24112d2a714e9e9e045307 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.taskbar; +import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; @@ -90,11 +91,12 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ private static final String WINDOW_TITLE = "Taskbar"; - private final DeviceProfile mDeviceProfile; private final LayoutInflater mLayoutInflater; private final TaskbarDragLayer mDragLayer; private final TaskbarControllers mControllers; + private DeviceProfile mDeviceProfile; + private final WindowManager mWindowManager; private final @Nullable RoundedCorner mLeftCorner, mRightCorner; private final int mTaskbarHeightForIme; @@ -125,10 +127,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0); final Resources resources = getResources(); - float taskbarIconSize = resources.getDimension(R.dimen.taskbar_icon_size); - mDeviceProfile.updateIconSize(1, resources); - float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx; - mDeviceProfile.updateIconSize(iconScale, resources); + updateIconSize(resources); mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size); @@ -197,7 +196,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance(); wmWrapper.setProvidesInsetsTypes( mWindowLayoutParams, - new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT } + new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT, + ITYPE_BOTTOM_MANDATORY_GESTURES } ); // Adjust the frame by the rounded corners (ie. leaving just the bar as the inset) when // the IME is showing @@ -211,6 +211,19 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mWindowManager.addView(mDragLayer, mWindowLayoutParams); } + /** Updates the Device profile instance to the latest representation of the screen. */ + public void updateDeviceProfile(DeviceProfile dp) { + mDeviceProfile = dp; + updateIconSize(getResources()); + } + + private void updateIconSize(Resources resources) { + float taskbarIconSize = resources.getDimension(R.dimen.taskbar_icon_size); + mDeviceProfile.updateIconSize(1, resources); + float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx; + mDeviceProfile.updateIconSize(iconScale, resources); + } + public void onConfigurationChanged(@Config int configChanges) { mControllers.onConfigurationChanged(configChanges); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index b3a9f8db7c7b44effe561acac0b84583258f9477..21d7411a56f9850eb145859ce844e03e4dfcecc0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -145,7 +145,7 @@ public class TaskbarDragController extends DragController popupContainer = mControllers.taskbarPopupController.showForIcon(btv); if (popupContainer != null) { - dragOptions.preDragCondition = popupContainer.createPreDragCondition(); + dragOptions.preDragCondition = popupContainer.createPreDragCondition(false); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 7a50d0bf63105cb5a4c729ada97cf0ac9a1d0872..be5ab55353a4d08135041360c1660277fdee05c4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -207,51 +207,83 @@ import java.util.function.Supplier; private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) { AnimatorSet animatorSet = new AnimatorSet(); - if (hasAnyFlag(changedFlags, FLAG_RESUMED)) { - boolean isResumed = isResumed(); - ObjectAnimator anim = mIconAlignmentForResumedState - .animateToValue(isResumed && goingToUnstashedLauncherState() - ? 1 : 0) - .setDuration(duration); - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mIsAnimatingToLauncherViaResume = false; - } + // Add the state animation first to ensure FLAG_IN_STASHED_LAUNCHER_STATE is set and we can + // determine whether goingToUnstashedLauncherStateChanged. + boolean wasGoingToUnstashedLauncherState = goingToUnstashedLauncherState(); + if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) { + boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING); + playStateTransitionAnim(animatorSet, duration, committed); - @Override - public void onAnimationStart(Animator animation) { - mIsAnimatingToLauncherViaResume = isResumed; + if (committed && mLauncherState == LauncherState.QUICK_SWITCH) { + // We're about to be paused, set immediately to ensure seamless handoff. + updateStateForFlag(FLAG_RESUMED, false); + applyState(0 /* duration */); + } + } + boolean goingToUnstashedLauncherStateChanged = wasGoingToUnstashedLauncherState + != goingToUnstashedLauncherState(); - TaskbarStashController stashController = mControllers.taskbarStashController; - stashController.updateStateForFlag(FLAG_IN_APP, !isResumed); - stashController.applyState(duration); - } - }); - animatorSet.play(anim); + boolean launcherStateChangedDuringAnimToResumeAlignment = + mIconAlignmentForResumedState.isAnimating() && goingToUnstashedLauncherStateChanged; + if (hasAnyFlag(changedFlags, FLAG_RESUMED) + || launcherStateChangedDuringAnimToResumeAlignment) { + boolean isResumed = isResumed(); + float toAlignmentForResumedState = isResumed && goingToUnstashedLauncherState() ? 1 : 0; + // If we're already animating to the value, just leave it be instead of restarting it. + if (!mIconAlignmentForResumedState.isAnimatingToValue(toAlignmentForResumedState)) { + ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState + .animateToValue(toAlignmentForResumedState) + .setDuration(duration); + + resumeAlignAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsAnimatingToLauncherViaResume = false; + } + + @Override + public void onAnimationStart(Animator animation) { + mIsAnimatingToLauncherViaResume = isResumed; + + TaskbarStashController stashController = + mControllers.taskbarStashController; + stashController.updateStateForFlag(FLAG_IN_APP, !isResumed); + stashController.applyState(duration); + } + }); + animatorSet.play(resumeAlignAnim); + } } - if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)) { + + boolean launcherStateChangedDuringAnimToGestureAlignment = + mIconAlignmentForGestureState.isAnimating() && goingToUnstashedLauncherStateChanged; + if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING) + || launcherStateChangedDuringAnimToGestureAlignment) { boolean isRecentsAnimationRunning = isRecentsAnimationRunning(); - Animator animator = mIconAlignmentForGestureState - .animateToValue(isRecentsAnimationRunning && goingToUnstashedLauncherState() - ? 1 : 0); - if (isRecentsAnimationRunning) { - animator.setDuration(duration); - } - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mIsAnimatingToLauncherViaGesture = false; + float toAlignmentForGestureState = isRecentsAnimationRunning + && goingToUnstashedLauncherState() ? 1 : 0; + // If we're already animating to the value, just leave it be instead of restarting it. + if (!mIconAlignmentForGestureState.isAnimatingToValue(toAlignmentForGestureState)) { + Animator gestureAlignAnim = mIconAlignmentForGestureState + .animateToValue(toAlignmentForGestureState); + if (isRecentsAnimationRunning) { + gestureAlignAnim.setDuration(duration); } + gestureAlignAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsAnimatingToLauncherViaGesture = false; + } - @Override - public void onAnimationStart(Animator animation) { - mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning(); - } - }); - animatorSet.play(animator); + @Override + public void onAnimationStart(Animator animation) { + mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning(); + } + }); + animatorSet.play(gestureAlignAnim); + } } if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) { @@ -260,17 +292,6 @@ import java.util.function.Supplier; .setDuration(duration)); } - if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) { - boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING); - playStateTransitionAnim(animatorSet, duration, committed); - - if (committed && mLauncherState == LauncherState.QUICK_SWITCH) { - // We're about to be paused, set immediately to ensure seamless handoff. - updateStateForFlag(FLAG_RESUMED, false); - applyState(0 /* duration */); - } - } - if (start) { animatorSet.start(); } @@ -310,8 +331,11 @@ import java.util.function.Supplier; animatorSet.play(stashAnimator); } - animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment) - .setDuration(duration)); + // If we're already animating to the value, just leave it be instead of restarting it. + if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) { + animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment) + .setDuration(duration)); + } } private boolean isResumed() { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 3cdcdf7f893bd89e7506f6f79ffb47e6f03fe717..bec717d8a918074a5fae4f4acb208e67a3484878 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -110,6 +110,13 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen } else { // Config change might be handled without re-creating the taskbar if (mTaskbarActivityContext != null) { + DeviceProfile dp = mUserUnlocked + ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) + : null; + + if (dp != null && dp.isTaskbarPresent) { + mTaskbarActivityContext.updateDeviceProfile(dp.copy(mContext)); + } mTaskbarActivityContext.onConfigurationChanged(configDiff); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index 0eaea8380187bd63c19731b1513a042770008e07..84b3839825d04b9f0d405d5e817a9c23a9a4e9af 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -26,12 +26,14 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SC import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; import android.util.FloatProperty; +import android.util.Log; import androidx.annotation.NonNull; @@ -65,7 +67,10 @@ public abstract class BaseRecentsViewStateController ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mRecentsView, scaleAndOffset[1]); TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f); - getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0); + float recentsAlpha = state.overviewUi ? 1f : 0; + Log.d(BAD_STATE, "BaseRecentsViewStateController setState state=" + state + + ", alpha=" + recentsAlpha); + getContentAlphaProperty().set(mRecentsView, recentsAlpha); getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness()); RECENTS_GRID_PROGRESS.set(mRecentsView, state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f); @@ -74,6 +79,8 @@ public abstract class BaseRecentsViewStateController @Override public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config, PendingAnimation builder) { + Log.d(BAD_STATE, "BaseRecentsViewStateController setStateWithAnimation state=" + toState + + ", config.skipOverview=" + config.hasAnimationFlag(SKIP_OVERVIEW)); if (config.hasAnimationFlag(SKIP_OVERVIEW)) { return; } @@ -97,7 +104,10 @@ public abstract class BaseRecentsViewStateController setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f, config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR)); - setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0, + float recentsAlpha = toState.overviewUi ? 1 : 0; + Log.d(BAD_STATE, "BaseRecentsViewStateController setStateWithAnimationInternal toState=" + + toState + ", alpha=" + recentsAlpha); + setter.setFloat(mRecentsView, getContentAlphaProperty(), recentsAlpha, config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); setter.setFloat( diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java index 1cf50f7f64d2e10b9abdc55f62b41c196edc992a..ed715626437bdf8713f2e90a0a40dbfde93a7ba9 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java @@ -21,6 +21,7 @@ import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.content.Intent; +import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.util.Pair; @@ -58,6 +59,12 @@ class QuickstepInteractionHandler implements RemoteViews.InteractionHandler { Pair options = remoteResponse.getLaunchOptions(view); ActivityOptionsWrapper activityOptions = mLauncher.getAppTransitionManager() .getActivityLaunchOptions(hostView); + Object itemInfo = hostView.getTag(); + IBinder launchCookie = null; + if (itemInfo instanceof ItemInfo) { + launchCookie = mLauncher.getLaunchCookie((ItemInfo) itemInfo); + activityOptions.options.setLaunchCookie(launchCookie); + } if (Utilities.ATLEAST_S && !pendingIntent.isActivity()) { // In the event this pending intent eventually launches an activity, i.e. a trampoline, // use the Quickstep transition animation. @@ -65,17 +72,14 @@ class QuickstepInteractionHandler implements RemoteViews.InteractionHandler { ActivityTaskManager.getService() .registerRemoteAnimationForNextActivityStart( pendingIntent.getCreatorPackage(), - activityOptions.options.getRemoteAnimationAdapter()); + activityOptions.options.getRemoteAnimationAdapter(), + launchCookie); } catch (RemoteException e) { // Do nothing. } } activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK); activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY); - Object itemInfo = hostView.getTag(); - if (itemInfo instanceof ItemInfo) { - mLauncher.addLaunchCookie((ItemInfo) itemInfo, activityOptions.options); - } options = Pair.create(options.first, activityOptions.options); if (pendingIntent.isActivity()) { logAppLaunch(itemInfo); diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index f6148a7c8f81fad03bd66150224b4276bc315e57..dadc706cf05707c53ab5a91042b1854fb2c2cfb3 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -38,6 +38,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_S import static com.android.launcher3.states.StateAnimationConfig.SKIP_ALL_ANIMATIONS; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT; import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP; import static com.android.launcher3.util.DisplayController.getSingleFrameMs; @@ -54,6 +55,7 @@ import android.animation.Animator.AnimatorListener; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.graphics.PointF; +import android.util.Log; import android.view.MotionEvent; import android.view.animation.Interpolator; @@ -224,6 +226,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, // Set RecentView's initial properties. RECENTS_SCALE_PROPERTY.set(mRecentsView, fromState.getOverviewScaleAndOffset(mLauncher)[0]); ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mRecentsView, 1f); + Log.d(BAD_STATE, "NBQSTC setupOverviewAnimators setContentAlpha=1"); mRecentsView.setContentAlpha(1); mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress()); mLauncher.getActionsView().getVisibilityAlpha().setValue( @@ -242,6 +245,24 @@ public class NoButtonQuickSwitchTouchController implements TouchController, QUICK_SWITCH.getWorkspaceScrimColor(mLauncher), LINEAR); if (mRecentsView.getTaskViewCount() == 0) { xAnim.addFloat(mRecentsView, CONTENT_ALPHA, 0f, 1f, LINEAR); + Log.d(BAD_STATE, "NBQSTC setupOverviewAnimators from: 0 to: 1"); + xAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + Log.d(BAD_STATE, "NBQSTC setupOverviewAnimators onStart"); + } + + @Override + public void onAnimationCancel(Animator animation) { + float alpha = mRecentsView == null ? -1 : CONTENT_ALPHA.get(mRecentsView); + Log.d(BAD_STATE, "NBQSTC setupOverviewAnimators onCancel, alpha=" + alpha); + } + + @Override + public void onAnimationEnd(Animator animation) { + Log.d(BAD_STATE, "NBQSTC setupOverviewAnimators onEnd"); + } + }); } mXOverviewAnim = xAnim.createPlaybackController(); mXOverviewAnim.dispatchOnStart(); diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java index f0ef9cc2d7183ce2b309009c30d62a41d58b76c8..59c2859d12430dc366c0bc530fdc929e4d1fbe22 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java @@ -29,6 +29,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TR import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; @@ -36,6 +37,7 @@ import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHO import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; +import android.util.Log; import android.view.MotionEvent; import com.android.launcher3.Launcher; @@ -112,6 +114,7 @@ public class QuickSwitchTouchController extends AbstractStateChangeTouchControll RECENTS_SCALE_PROPERTY.set(mOverviewPanel, QUICK_SWITCH.getOverviewScaleAndOffset(mLauncher)[0] * 0.85f); ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mOverviewPanel, 1f); + Log.d(BAD_STATE, "QuickSwitchTouchController initCurrentAnimation setContentAlpha=1"); mOverviewPanel.setContentAlpha(1); mCurrentAnimation = mLauncher.getStateManager() diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 9f1e47f15affb9e722c1e0fc457f18d937d8e98f..2f52c9d6c3dbfc4e8c7b8a6841b07fbbeb3b2e55 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -249,6 +249,8 @@ public abstract class AbsSwipeUpHandler, private RunningWindowAnim[] mRunningWindowAnim; // Possible second animation running at the same time as mRunningWindowAnim private Animator mParallelRunningAnim; + // Current running divider animation + private ValueAnimator mDividerAnimator; private boolean mIsMotionPaused; private boolean mHasMotionEverBeenPaused; @@ -831,8 +833,8 @@ public abstract class AbsSwipeUpHandler, // Notify when the animation starts flushOnRecentsAnimationAndLauncherBound(); - TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, - false /*shown*/, true /*animate*/); + // Start hiding the divider + setDividerShown(false, false /* immediate */); // Only add the callback to enable the input consumer after we actually have the controller mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED, @@ -849,8 +851,7 @@ public abstract class AbsSwipeUpHandler, mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED); if (mRecentsAnimationTargets != null) { - TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, - true /*shown*/, true /*animate*/); + setDividerShown(true, false /* immediate */); } // Defer clearing the controller and the targets until after we've updated the state @@ -1000,8 +1001,7 @@ public abstract class AbsSwipeUpHandler, mStateCallback.setState(STATE_RESUME_LAST_TASK); } if (mRecentsAnimationTargets != null) { - TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, - true /*shown*/, false /*animate*/); + setDividerShown(true, true /* immediate */); } break; } @@ -1653,8 +1653,7 @@ public abstract class AbsSwipeUpHandler, mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget()); if (mRecentsAnimationTargets != null) { - TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, - true /*shown*/, false /*animate*/); + setDividerShown(true, true /* immediate */); } // Leave the pending invisible flag, as it may be used by wallpaper open animation. @@ -1920,8 +1919,7 @@ public abstract class AbsSwipeUpHandler, @Override public void onRecentsAnimationFinished(RecentsAnimationController controller) { if (!controller.getFinishTargetIsLauncher()) { - TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, - true /*shown*/, true /*animate*/); + setDividerShown(true, false /* immediate */); } mRecentsAnimationController = null; mRecentsAnimationTargets = null; @@ -2026,6 +2024,19 @@ public abstract class AbsSwipeUpHandler, return scaleProgress; } + private void setDividerShown(boolean shown, boolean immediate) { + if (mDividerAnimator != null) { + mDividerAnimator.cancel(); + } + mDividerAnimator = TaskViewUtils.createSplitAuxiliarySurfacesAnimator( + mRecentsAnimationTargets.nonApps, shown, (dividerAnimator) -> { + dividerAnimator.start(); + if (immediate) { + dividerAnimator.end(); + } + }); + } + /** * Used for winscope tracing, see launcher_trace.proto * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java index 95c871099b0f5d30960f1b8d0d07c72ce6fbf766..6a7d066cd8fc3dab7ca3a8914ca5bee0f41c2301 100644 --- a/quickstep/src/com/android/quickstep/AnimatedFloat.java +++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java @@ -42,6 +42,8 @@ public class AnimatedFloat { private final Runnable mUpdateCallback; private ObjectAnimator mValueAnimator; + // Only non-null when an animation is playing to this value. + private Float mEndValue; public float value; @@ -67,10 +69,18 @@ public class AnimatedFloat { cancelAnimation(); mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, start, end); mValueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + if (mValueAnimator == animator) { + mEndValue = end; + } + } + @Override public void onAnimationEnd(Animator animator) { if (mValueAnimator == animator) { mValueAnimator = null; + mEndValue = null; } } }); @@ -103,4 +113,15 @@ public class AnimatedFloat { public ObjectAnimator getCurrentAnimation() { return mValueAnimator; } + + public boolean isAnimating() { + return mValueAnimator != null; + } + + /** + * Returns whether we are currently animating, and the animation's end value matches the given. + */ + public boolean isAnimatingToValue(float endValue) { + return isAnimating() && mEndValue != null && mEndValue == endValue; + } } diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java index a72935b250254483dbff7f23bc8628d30970c0af..4fb03c4de4135eda0c5258cd27454ef7c43433db 100644 --- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java +++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java @@ -246,7 +246,8 @@ public class LauncherSwipeHandlerV2 extends return mActivity.getFirstMatchForAppClose(launchCookieItemId, runningTaskView.getTask().key.getComponent().getPackageName(), - UserHandle.of(runningTaskView.getTask().key.userId)); + UserHandle.of(runningTaskView.getTask().key.userId), + false /* supportsAllAppsState */); } @Override diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 1dc49339b610b5bdca732cc15cc8ade272a8f3a4..e6424d764270613b31b34c73fc9457f9edbc80d7 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -24,6 +24,7 @@ import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSI import static com.android.launcher3.Utilities.createHomeIntent; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator; @@ -38,6 +39,8 @@ import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.util.Log; +import android.view.Display; import android.view.SurfaceControl.Transaction; import android.view.View; import android.window.SplashScreen; @@ -308,6 +311,7 @@ public final class RecentsActivity extends StatefulActivity { protected void onStart() { // Set the alpha to 1 before calling super, as it may get set back to 0 due to // onActivityStart callback. + Log.d(BAD_STATE, "RecentsActivity onStart mFallbackRecentsView.setContentAlpha(1)"); mFallbackRecentsView.setContentAlpha(1); super.onStart(); mFallbackRecentsView.updateLocusId(); diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 73d14246a00ef0c0dd313f9940b4fbe25cdbbae8..99a02e15cea2e8e0229e003214755bd4649c7a84 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -554,15 +554,13 @@ public class RecentsAnimationDeviceState implements /** * @param ev An ACTION_DOWN motion event - * @param task Info for the currently running task * @return whether the given motion event can trigger the assistant over the current task. */ - public boolean canTriggerAssistantAction(MotionEvent ev, ActivityManager.RunningTaskInfo task) { + public boolean canTriggerAssistantAction(MotionEvent ev) { return mAssistantAvailable && !QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags) && mRotationTouchHelper.touchInAssistantRegion(ev) - && !isLockToAppActive() - && !isGestureBlockedActivity(task); + && !isLockToAppActive(); } /** diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 5d9a5371651df2962b577ed87bb6e86f7b01ba38..dbf8acf39bce5c578b44eeca8b8ab7d38f8000f5 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -36,6 +36,8 @@ import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLAT import static com.android.launcher3.anim.Interpolators.clampToProgress; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.statehandlers.DepthController.DEPTH; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; +import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; @@ -52,6 +54,7 @@ import android.graphics.Matrix.ScaleToFit; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; +import android.util.Log; import android.view.SurfaceControl; import android.view.View; import android.window.TransitionInfo; @@ -85,6 +88,7 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat. import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; /** * Utility class for helpful methods related to {@link TaskView} objects and their tasks. @@ -538,8 +542,16 @@ public final class TaskViewUtils { nonAppTargets, depthController, pa); if (launcherClosing) { // TODO(b/182592057): differentiate between "restore split" vs "launch fullscreen app" - TaskViewUtils.setSplitAuxiliarySurfacesShown(nonAppTargets, - true /*shown*/, true /*animate*/, pa); + TaskViewUtils.createSplitAuxiliarySurfacesAnimator(nonAppTargets, true /*shown*/, + (dividerAnimator) -> { + // If split apps are launching, we want to delay showing the divider bar + // until the very end once the apps are mostly in place. This is because we + // aren't moving the divider leash in the relative position with the + // launching apps. + dividerAnimator.setStartDelay(pa.getDuration() + - SPLIT_DIVIDER_ANIM_DURATION); + pa.add(dividerAnimator); + }); } Animator childStateAnimation = null; @@ -552,6 +564,29 @@ public final class TaskViewUtils { launcherAnim = dp.overviewShowAsGrid ? ObjectAnimator.ofFloat(recentsView, RecentsView.CONTENT_ALPHA, 0) : recentsView.createAdjacentPageAnimForTaskLaunch(taskView); + if (dp.isTablet) { + Log.d(BAD_STATE, "TVU composeRecentsLaunchAnimator alpha=" + 0); + launcherAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + Log.d(BAD_STATE, "TVU composeRecentsLaunchAnimator onStart"); + } + + @Override + public void onAnimationCancel(Animator animation) { + float alpha = recentsView == null + ? -1 + : RecentsView.CONTENT_ALPHA.get(recentsView); + Log.d(BAD_STATE, "TVU composeRecentsLaunchAnimator onCancel, alpha=" + + alpha); + } + + @Override + public void onAnimationEnd(Animator animation) { + Log.d(BAD_STATE, "TVU composeRecentsLaunchAnimator onEnd"); + } + }); + } launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); launcherAnim.setDuration(RECENTS_LAUNCH_DURATION); @@ -594,16 +629,17 @@ public final class TaskViewUtils { anim.addListener(windowAnimEndListener); } - public static void setSplitAuxiliarySurfacesShown(RemoteAnimationTargetCompat[] nonApps, - boolean shown, boolean animate) { - setSplitAuxiliarySurfacesShown(nonApps, shown, animate,null); - } - - private static void setSplitAuxiliarySurfacesShown( - @NonNull RemoteAnimationTargetCompat[] nonApps, boolean shown, boolean animate, - @Nullable PendingAnimation splitLaunchAnimation) { + /** + * Creates an animation to show/hide the auxiliary surfaces (aka. divider bar), only calling + * {@param animatorHandler} if there are valid surfaces to animate. + * + * @return the animator animating the surfaces + */ + public static ValueAnimator createSplitAuxiliarySurfacesAnimator( + RemoteAnimationTargetCompat[] nonApps, boolean shown, + Consumer animatorHandler) { if (nonApps == null || nonApps.length == 0) { - return; + return null; } SurfaceControl.Transaction t = new SurfaceControl.Transaction(); @@ -618,20 +654,7 @@ public final class TaskViewUtils { } } if (!hasSurfaceToAnimate) { - return; - } - - if (!animate) { - for (SurfaceControl leash : auxiliarySurfaces) { - t.setAlpha(leash, shown ? 1 : 0); - if (shown) { - t.show(leash); - } else { - t.hide(leash); - } - } - t.apply(); - return; + return null; } ValueAnimator dockFadeAnimator = ValueAnimator.ofFloat(0f, 1f); @@ -668,15 +691,7 @@ public final class TaskViewUtils { } }); dockFadeAnimator.setDuration(SPLIT_DIVIDER_ANIM_DURATION); - if (splitLaunchAnimation != null) { - // If split apps are launching, we want to delay showing the divider bar until the very - // end once the apps are mostly in place. This is because we aren't moving the divider - // leash in the relative position with the launching apps. - dockFadeAnimator.setStartDelay( - splitLaunchAnimation.getDuration() - SPLIT_DIVIDER_ANIM_DURATION); - splitLaunchAnimation.add(dockFadeAnimator); - } else { - dockFadeAnimator.start(); - } + animatorHandler.accept(dockFadeAnimator); + return dockFadeAnimator; } } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 1f6a974c23f8a09caa20fd728832c8939771b9cb..af8fec23fb773357aabae23af5b9ac6b4024ab69 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -37,7 +37,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED; import android.annotation.TargetApi; -import android.app.ActivityManager; import android.app.PendingIntent; import android.app.RemoteAction; import android.app.Service; @@ -600,26 +599,14 @@ public class TouchInteractionService extends Service ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + mConsumer.getName()); mUncheckedConsumer = mConsumer; - } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()) { + } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode() + && mDeviceState.canTriggerAssistantAction(event)) { mGestureState = createGestureState(mGestureState); - ActivityManager.RunningTaskInfo runningTask = mGestureState.getRunningTask(); - if (mDeviceState.canTriggerAssistantAction(event, runningTask)) { - // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we - // should not interrupt it. QuickSwitch assumes that interruption can only - // happen if the next gesture is also quick switch. - mUncheckedConsumer = new AssistantInputConsumer( - this, - mGestureState, - InputConsumer.NO_OP, mInputMonitorCompat, - mDeviceState, - event); - } else if (mDeviceState.canTriggerOneHandedAction(event)) { - // Consume gesture event for triggering one handed feature. - mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState, - InputConsumer.NO_OP, mInputMonitorCompat); - } else { - mUncheckedConsumer = InputConsumer.NO_OP; - } + // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we + // should not interrupt it. QuickSwitch assumes that interruption can only + // happen if the next gesture is also quick switch. + mUncheckedConsumer = tryCreateAssistantInputConsumer( + InputConsumer.NO_OP, mGestureState, event); } else if (mDeviceState.canTriggerOneHandedAction(event)) { // Consume gesture event for triggering one handed feature. mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState, @@ -666,6 +653,14 @@ public class TouchInteractionService extends Service ProtoTracer.INSTANCE.get(this).scheduleFrameUpdate(); } + private InputConsumer tryCreateAssistantInputConsumer(InputConsumer base, + GestureState gestureState, MotionEvent motionEvent) { + return mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask()) + ? base + : new AssistantInputConsumer(this, gestureState, base, mInputMonitorCompat, + mDeviceState, motionEvent); + } + public GestureState createGestureState(GestureState previousGestureState) { GestureState gestureState = new GestureState(mOverviewComponentObserver, ActiveGestureLog.INSTANCE.generateAndSetLogId()); @@ -711,9 +706,8 @@ public class TouchInteractionService extends Service handleOrientationSetup(base); } if (mDeviceState.isFullyGesturalNavMode()) { - if (mDeviceState.canTriggerAssistantAction(event, newGestureState.getRunningTask())) { - base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat, - mDeviceState, event); + if (mDeviceState.canTriggerAssistantAction(event)) { + base = tryCreateAssistantInputConsumer(base, newGestureState, event); } // If Taskbar is present, we listen for long press to unstash it. diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index 6d22b17bfbc2f670bd4d3fc3761cd58d384abccb..d7da74b5c6cf411f8d82837a5a66fab0b9f88800 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -15,6 +15,7 @@ */ package com.android.quickstep.fallback; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.fallback.RecentsState.DEFAULT; import static com.android.quickstep.fallback.RecentsState.HOME; @@ -27,6 +28,7 @@ import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.os.Build; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import androidx.annotation.Nullable; @@ -219,6 +221,7 @@ public class FallbackRecentsView extends RecentsView + + + \ No newline at end of file diff --git a/res/color-night/accent_ripple_color.xml b/res/color-night/accent_ripple_color.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a37b00ab8983524da8500b05f6dceca978c7f76 --- /dev/null +++ b/res/color-night/accent_ripple_color.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/res/color-v31/accent_ripple_color.xml b/res/color-v31/accent_ripple_color.xml new file mode 100644 index 0000000000000000000000000000000000000000..a996228daa3ed75dcdd2e21f88c0fff77dd75465 --- /dev/null +++ b/res/color-v31/accent_ripple_color.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/res/color/accent_ripple_color.xml b/res/color/accent_ripple_color.xml new file mode 100644 index 0000000000000000000000000000000000000000..697f415ec797f9c9f9929bcf0d7ff6bc475a872f --- /dev/null +++ b/res/color/accent_ripple_color.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/res/drawable/all_apps_tabs_background.xml b/res/drawable/all_apps_tabs_background.xml index aea2e7a98b9b9315b4d31e35046e856fd586ed6b..8471cd4539882af598002564c8c4ef4357fab5a8 100644 --- a/res/drawable/all_apps_tabs_background.xml +++ b/res/drawable/all_apps_tabs_background.xml @@ -13,23 +13,36 @@ See the License for the specific language governing permissions and limitations under the License. --> - - + + + - + - - - - - + + + + + + + + + + + + + + + + - \ No newline at end of file + + \ No newline at end of file diff --git a/res/drawable/personal_work_tabs_ripple.xml b/res/drawable/personal_work_tabs_ripple.xml deleted file mode 100644 index 2e57b80570ba6d00462c83dd0e06e01a2de5f564..0000000000000000000000000000000000000000 --- a/res/drawable/personal_work_tabs_ripple.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 1f1d57adc9010b0384f2ac7f19a5db5fac93d3f7..163b442b6e8996e0677190a5211e914483f1e0bd 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -35,6 +35,7 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.icu.text.MessageFormat; import android.text.TextPaint; +import android.text.TextUtils; import android.text.TextUtils.TruncateAt; import android.util.AttributeSet; import android.util.Property; @@ -785,7 +786,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, invalidate(); } } - if (itemInfo.contentDescription != null) { + if (!TextUtils.isEmpty(itemInfo.contentDescription)) { if (itemInfo.isDisabled()) { setContentDescription(getContext().getString(R.string.disabled_app_label, itemInfo.contentDescription)); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 81a0d5b1be5d41b64635236415158025cbdab82f..87eb222c62b6f69dd1f23e7794cbe6ac3c2dbca3 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -57,6 +57,7 @@ import static com.android.launcher3.popup.SystemShortcut.INSTALL; import static com.android.launcher3.popup.SystemShortcut.WIDGETS; import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK; import static com.android.launcher3.states.RotationHelper.REQUEST_NONE; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import static com.android.launcher3.util.ItemInfoMatcher.forFolderMatch; import android.animation.Animator; @@ -493,6 +494,8 @@ public class Launcher extends StatefulActivity implements Launche if (!mModel.addCallbacksAndLoad(this)) { if (!internalStateHandled) { + Log.d(BAD_STATE, "Launcher onCreate not binding sync, setting DragLayer alpha " + + "ALPHA_INDEX_LAUNCHER_LOAD to 0"); // If we are not binding synchronously, show a fade in animation when // the first page bind completes. mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0); @@ -986,6 +989,9 @@ public class Launcher extends StatefulActivity implements Launche DiscoveryBounce.showForHomeIfNeeded(this); mAppWidgetHost.setActivityResumed(true); + + // Temporary workaround for apps using SHOW_FORCED IME flag. + hideKeyboard(); } private void logStopAndResume(boolean isResume) { @@ -2626,6 +2632,28 @@ public class Launcher extends StatefulActivity implements Launche AlphaProperty property = mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD); if (property.getValue() < 1) { ObjectAnimator anim = ObjectAnimator.ofFloat(property, MultiValueAlpha.VALUE, 1); + + Log.d(BAD_STATE, "Launcher onInitialBindComplete toAlpha=" + 1); + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + Log.d(BAD_STATE, "Launcher onInitialBindComplete onStart"); + } + + @Override + public void onAnimationCancel(Animator animation) { + float alpha = mDragLayer == null + ? -1 + : mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).getValue(); + Log.d(BAD_STATE, "Launcher onInitialBindComplete onCancel, alpha=" + alpha); + } + + @Override + public void onAnimationEnd(Animator animation) { + Log.d(BAD_STATE, "Launcher onInitialBindComplete onEnd"); + } + }); + anim.addListener(AnimatorListeners.forEndCallback(executor::onLoadAnimationCompleted)); anim.start(); } else { @@ -2688,8 +2716,11 @@ public class Launcher extends StatefulActivity implements Launche * @param preferredItemId The id of the preferred item to match to if it exists. * @param packageName The package name of the app to match. * @param user The user of the app to match. + * @param supportsAllAppsState If true and we are in All Apps state, looks for view in All Apps. + * Else we only looks on the workspace. */ - public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user) { + public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user, + boolean supportsAllAppsState) { final ItemInfoMatcher preferredItem = (info, cn) -> info != null && info.id == preferredItemId; final ItemInfoMatcher packageAndUserAndApp = (info, cn) -> @@ -2700,7 +2731,7 @@ public class Launcher extends StatefulActivity implements Launche && TextUtils.equals(info.getTargetComponent().getPackageName(), packageName); - if (isInState(LauncherState.ALL_APPS)) { + if (supportsAllAppsState && isInState(LauncherState.ALL_APPS)) { return getFirstMatch(Collections.singletonList(mAppsView.getActiveRecyclerView()), preferredItem, packageAndUserAndApp); } else { diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index d2fe483c9645feb63064e9cb19ccf6a452bf672c..63313f770f8605ad3f3d652e8c5946a26fdf51f3 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -460,9 +460,10 @@ public final class Utilities { * Trims the string, removing all whitespace at the beginning and end of the string. * Non-breaking whitespaces are also removed. */ + @NonNull public static String trim(CharSequence s) { if (s == null) { - return null; + return ""; } // Just strip any sequence of whitespace or java space characters from the beginning and end diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 281dfea492a7b80a99c24d8e323c6e35fb3a0a5a..f18ff3bee3515c6f5a1b520e1fd2158904ab214a 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -30,6 +30,7 @@ import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPELEFT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPERIGHT; +import static com.android.launcher3.testing.TestProtocol.BAD_STATE; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -1254,6 +1255,7 @@ public class Workspace extends PagedView // different effects based on device performance. On at least one relatively high-end // device I've tried, translating the launcher causes things to get quite laggy. mLauncher.getDragLayer().setTranslationX(transX); + Log.d(BAD_STATE, "Workspace onOverlayScrollChanged DragLayer ALPHA_INDEX_OVERLAY=" + alpha); mLauncher.getDragLayer().getAlphaProperty(ALPHA_INDEX_OVERLAY).setValue(alpha); } @@ -1686,7 +1688,7 @@ public class Workspace extends PagedView PopupContainerWithArrow popupContainer = PopupContainerWithArrow .showForIcon((BubbleTextView) child); if (popupContainer != null) { - dragOptions.preDragCondition = popupContainer.createPreDragCondition(); + dragOptions.preDragCondition = popupContainer.createPreDragCondition(true); } } diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java index 08b38e88acdb7b44b9a4f71973e5e0080631c2f1..178fbdb7b8ec1a7c2dd1c4a77a2e3c48520df5a2 100644 --- a/src/com/android/launcher3/model/LoaderCursor.java +++ b/src/com/android/launcher3/model/LoaderCursor.java @@ -202,8 +202,7 @@ public class LoaderCursor extends CursorWrapper { * Returns the title or empty string */ private String getTitle() { - String title = getString(titleIndex); - return TextUtils.isEmpty(title) ? "" : Utilities.trim(title); + return Utilities.trim(getString(titleIndex)); } /** diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index b96395052c3f264689d74ece1958b6eaee7dad1b..6d2b12f45121355dedce527f7122d569218aca28 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -396,7 +396,7 @@ public class PopupContainerWithArrow * Current behavior: * - Start the drag if the touch passes a certain distance from the original touch down. */ - public DragOptions.PreDragCondition createPreDragCondition() { + public DragOptions.PreDragCondition createPreDragCondition(boolean updateIconUi) { return new DragOptions.PreDragCondition() { @Override @@ -406,6 +406,9 @@ public class PopupContainerWithArrow @Override public void onPreDragStart(DropTarget.DragObject dragObject) { + if (!updateIconUi) { + return; + } if (mIsAboveIcon) { // Hide only the icon, keep the text visible. mOriginalIcon.setIconVisible(false); @@ -418,6 +421,9 @@ public class PopupContainerWithArrow @Override public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) { + if (!updateIconUi) { + return; + } mOriginalIcon.setIconVisible(true); if (dragStarted) { // Make sure we keep the original icon hidden while it is being dragged. @@ -480,6 +486,9 @@ public class PopupContainerWithArrow @Override protected void closeComplete() { super.closeComplete(); + if (mActivityContext.getDragController() != null) { + mActivityContext.getDragController().removeDragListener(this); + } PopupContainerWithArrow openPopup = getOpen(mActivityContext); if (openPopup == null || openPopup.mOriginalIcon != mOriginalIcon) { mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible()); diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 673b0116eddf17ebfd44b5b55040cd13bfd09e0a..28e7553e782ccb1d8f05d5cdd962e024b8039eb1 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -125,4 +125,6 @@ public final class TestProtocol { public static final String TASK_VIEW_ID_CRASH = "b/195430732"; public static final String NO_DROP_TARGET = "b/195031154"; public static final String NULL_INT_SET = "b/200572078"; + + public static final String BAD_STATE = "b/223498680"; } diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java index 76dfb3ce2ab2b4410c45fcc1e44383daaba92f7e..6e44a43d61861ba9f3220c18c1f9c790b4e40e5f 100644 --- a/src/com/android/launcher3/views/BaseDragLayer.java +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -40,6 +40,7 @@ import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.Utilities; import com.android.launcher3.util.MultiValueAlpha; @@ -545,8 +546,14 @@ public abstract class BaseDragLayer public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { if (Utilities.ATLEAST_Q) { Insets gestureInsets = insets.getMandatorySystemGestureInsets(); + int gestureInsetBottom = gestureInsets.bottom; + DeviceProfile dp = mActivity.getDeviceProfile(); + if (dp.isTaskbarPresent) { + // Ignore taskbar gesture insets to avoid interfering with TouchControllers. + gestureInsetBottom = Math.max(0, gestureInsetBottom - dp.taskbarSize); + } mSystemGestureRegion.set(gestureInsets.left, gestureInsets.top, - gestureInsets.right, gestureInsets.bottom); + gestureInsets.right, gestureInsetBottom); } return super.dispatchApplyWindowInsets(insets); } diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index dc3ee43548af9e650f588f747eb0a3687bfac53e..0a800c3c6e8e67d38582b6d183547c75b6100ada 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -564,6 +564,12 @@ public class FloatingIconView extends FrameLayout implements launcher, parent); view.recycle(); + // Init properties before getting the drawable. + view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout(); + view.mIsOpening = isOpening; + view.mOriginalIcon = originalView; + view.mPositionOut = positionOut; + // Get the drawable on the background thread boolean shouldLoadIcon = originalView.getTag() instanceof ItemInfo && hideOriginal; if (shouldLoadIcon) { @@ -577,11 +583,6 @@ public class FloatingIconView extends FrameLayout implements } sIconLoadResult = null; - view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout(); - view.mIsOpening = isOpening; - view.mOriginalIcon = originalView; - view.mPositionOut = positionOut; - // Match the position of the original view. view.matchPositionOf(launcher, originalView, isOpening, positionOut); @@ -639,6 +640,7 @@ public class FloatingIconView extends FrameLayout implements mLoadIconSignal = null; mEndRunnable = null; mFinalDrawableBounds.setEmpty(); + mIsOpening = false; mPositionOut = null; mListenerView.setListener(null); mOriginalIcon = null; diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java index f32f904981e9091aab96055b9b84c5066280a145..09c8c64087f3bdb81a658560508bc08764f9b32c 100644 --- a/src/com/android/launcher3/views/FloatingSurfaceView.java +++ b/src/com/android/launcher3/views/FloatingSurfaceView.java @@ -159,7 +159,8 @@ public class FloatingSurfaceView extends AbstractFloatingView implements return; } View icon = mLauncher.getFirstMatchForAppClose(-1, - mContract.componentName.getPackageName(), mContract.user); + mContract.componentName.getPackageName(), mContract.user, + false /* supportsAllAppsState */); boolean iconChanged = mIcon != icon; if (iconChanged) {