diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index e5fd605904..ca9c5771b1 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -18,6 +18,7 @@ package com.android.launcher3; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; @@ -144,6 +145,7 @@ import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.util.SurfaceTransaction; import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties; import com.android.quickstep.util.SurfaceTransactionApplier; +import com.android.quickstep.util.TaskRestartedDuringLaunchListener; import com.android.quickstep.util.WorkspaceRevealAnim; import com.android.quickstep.views.FloatingWidgetView; import com.android.quickstep.views.RecentsView; @@ -229,6 +231,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener private RemoteAnimationProvider mRemoteAnimationProvider; // Strong refs to runners which are cleared when the launcher activity is destroyed private RemoteAnimationFactory mWallpaperOpenRunner; + private RemoteAnimationFactory mAppLaunchRunner; private RemoteAnimationFactory mKeyguardGoingAwayRunner; private RemoteAnimationFactory mWallpaperOpenTransitionRunner; @@ -298,17 +301,23 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener boolean fromRecents = isLaunchingFromRecents(v, null /* targets */); RunnableList onEndCallback = new RunnableList(); - RemoteAnimationFactory delegateRunner = new AppLaunchAnimationRunner(v, onEndCallback); + // Handle the case where an already visible task is launched which results in no transition + TaskRestartedDuringLaunchListener restartedListener = + new TaskRestartedDuringLaunchListener(); + restartedListener.register(onEndCallback::executeAllAndDestroy); + onEndCallback.add(restartedListener::unregister); + + mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback); ItemInfo tag = (ItemInfo) v.getTag(); if (tag != null && tag.shouldUseBackgroundAnimation()) { ContainerAnimationRunner containerAnimationRunner = ContainerAnimationRunner.from(v, mStartingWindowListener, onEndCallback); if (containerAnimationRunner != null) { - delegateRunner = containerAnimationRunner; + mAppLaunchRunner = containerAnimationRunner; } } RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner( - mHandler, delegateRunner, true /* startAtFrontOfQueue */); + mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */); // Note that this duration is a guess as we do not know if the animation will be a // recents launch or not for sure until we know the opening app targets. @@ -1164,6 +1173,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener // Also clear strong references to the runners registered with the remote animation // definition so we don't have to wait for the system gc mWallpaperOpenRunner = null; + mAppLaunchRunner = null; mKeyguardGoingAwayRunner = null; } } @@ -1201,14 +1211,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener return false; } - private boolean hasMultipleTargetsWithMode(RemoteAnimationTarget[] targets, int mode) { + private boolean shouldPlayFallbackClosingAnimation(RemoteAnimationTarget[] targets) { int numTargets = 0; for (RemoteAnimationTarget target : targets) { - if (target.mode == mode) { + if (target.mode == MODE_CLOSING) { numTargets++; - } - if (numTargets > 1) { - return true; + if (numTargets > 1 || target.windowConfiguration.getWindowingMode() + == WINDOWING_MODE_MULTI_WINDOW) { + return true; + } } } return false; @@ -1595,7 +1606,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener boolean playFallBackAnimation = (launcherView == null && launcherIsForceInvisibleOrOpening) || mLauncher.getWorkspace().isOverlayShown() - || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING); + || shouldPlayFallbackClosingAnimation(appTargets); boolean playWorkspaceReveal = true; boolean skipAllAppsScale = false; diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index ba6f1651ed..abf49eb195 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -50,6 +50,7 @@ import com.android.quickstep.util.GroupTask; import com.android.quickstep.views.RecentsView; import java.io.PrintWriter; +import java.util.Arrays; /** * A data source which integrates with a Launcher instance @@ -105,6 +106,10 @@ public class LauncherTaskbarUIController extends TaskbarUIController { // Restore the in-app display progress from before Taskbar was recreated. float[] prevProgresses = mControllers.getSharedState().inAppDisplayProgressMultiPropValues; + // Make a copy of the previous progress to set since updating the multiprop will update + // the property which also calls onInAppDisplayProgressChanged() which writes the current + // values into the shared state + prevProgresses = Arrays.copyOf(prevProgresses, prevProgresses.length); for (int i = 0; i < prevProgresses.length; i++) { mTaskbarInAppDisplayProgressMultiProp.get(i).setValue(prevProgresses[i]); } diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index 9a9e0ba70c..9c463cb68c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -923,6 +923,15 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); } + /** + * Called whenever a new ui controller is set, and should update anything that depends on the + * ui controller. + */ + public void onUiControllerChanged() { + updateNavButtonInAppDisplayProgressForSysui(); + updateNavButtonTranslationY(); + } + @Override public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "NavbarButtonsViewController:"); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 43feec716d..a1390aeabb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -591,9 +591,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { * Sets a new data-source for this taskbar instance */ public void setUIController(@NonNull TaskbarUIController uiController) { - mControllers.uiController.onDestroy(); - mControllers.uiController = uiController; - mControllers.uiController.init(mControllers); + mControllers.setUiController(uiController); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index 66c2eb3314..d3f80e31cd 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -196,6 +196,19 @@ public class TaskbarControllers { mPostInitCallbacks.clear(); } + /** + * Sets the ui controller. + */ + public void setUiController(@NonNull TaskbarUIController newUiController) { + uiController.onDestroy(); + uiController = newUiController; + uiController.init(this); + uiController.updateStateForSysuiFlags(mSharedState.sysuiStateFlags); + + // Notify that the ui controller has changed + navbarButtonsViewController.onUiControllerChanged(); + } + @Nullable public TaskbarSharedState getSharedState() { // This should only be null if called before init() and after destroy(). diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 17e7e1b9bb..ddea51f737 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -202,6 +202,11 @@ public class TaskbarLauncherStateController { public void onStateTransitionComplete(LauncherState finalState) { mLauncherState = finalState; updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, false); + // TODO(b/279514548) Cleans up bad state that can occur when user interacts with + // taskbar on top of transparent activity. + if (finalState == LauncherState.NORMAL && mLauncher.isResumed()) { + updateStateForFlag(FLAG_RESUMED, true); + } applyState(); boolean disallowLongClick = finalState == LauncherState.OVERVIEW_SPLIT_SELECT; com.android.launcher3.taskbar.Utilities.setOverviewDragState( diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java index 5eec726e27..512b77a92a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java @@ -177,7 +177,6 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba systemShortcuts); } - icon.clearAccessibilityFocus(); container.addOnAttachStateChangeListener( new PopupLiveUpdateHandler(context, container) { @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 658bf2d865..2f13c5de44 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -345,11 +345,13 @@ public class QuickstepLauncher extends Launcher { @Override public RunnableList startActivitySafely(View v, Intent intent, ItemInfo item) { - // Only pause is taskbar controller is not present + // Only pause is taskbar controller is not present until the transition (if it exists) ends mHotseatPredictionController.setPauseUIUpdate(getTaskbarUIController() == null); RunnableList result = super.startActivitySafely(v, intent, item); - if (getTaskbarUIController() == null && result == null) { - mHotseatPredictionController.setPauseUIUpdate(false); + if (result == null) { + if (getTaskbarUIController() == null) { + mHotseatPredictionController.setPauseUIUpdate(false); + } } else { result.add(() -> mHotseatPredictionController.setPauseUIUpdate(false)); } diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java index 1913091695..eff53f3c85 100644 --- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java @@ -139,6 +139,7 @@ public class FallbackSwipeHandler extends mTmpMatrix.setScale(scale, scale, app.localBounds.exactCenterX(), app.localBounds.exactCenterY()); builder.setMatrix(mTmpMatrix).setAlpha(alpha); + builder.setShow(); } @Override diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index 523a98ec4b..2256cbf14b 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -15,6 +15,7 @@ */ package com.android.quickstep; +import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; @@ -37,6 +38,7 @@ import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Set; @@ -101,9 +103,22 @@ public class RecentsAnimationCallbacks implements RemoteAnimationTarget[] appTargets, RemoteAnimationTarget[] wallpaperTargets, Rect homeContentInsets, Rect minimizedHomeBounds) { + long appCount = Arrays.stream(appTargets) + .filter(app -> app.mode == MODE_CLOSING) + .count(); + if (appCount == 0) { + // Edge case, if there are no closing app targets, then Launcher has nothing to handle + ActiveGestureLog.INSTANCE.addLog( + /* event= */ "RecentsAnimationCallbacks.onAnimationStart (canceled)", + /* extras= */ 0, + /* gestureEvent= */ START_RECENTS_ANIMATION); + notifyAnimationCanceled(); + animationController.finish(false /* toHome */, false /* sendUserLeaveHint */); + return; + } + mController = new RecentsAnimationController(animationController, mAllowMinimizeSplitScreen, this::onAnimationFinished); - if (mCancelled) { Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), mController::finishAnimationToApp); diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 410ba21866..eacca0dbab 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -19,6 +19,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; +import static com.android.launcher3.util.NavigationMode.NO_BUTTON; 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; @@ -37,6 +38,7 @@ import androidx.annotation.UiThread; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.util.DisplayController; import com.android.quickstep.TopTaskTracker.CachedTaskInfo; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.views.DesktopTaskView; @@ -162,10 +164,16 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn for (RemoteAnimationTarget compat : appearedTaskTargets) { if (compat.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME - && activityInterface.getCreatedActivity() instanceof RecentsActivity) { - // When receive opening home activity while recents is running, enter home - // and dismiss recents. - ((RecentsActivity) activityInterface.getCreatedActivity()).startHome(); + && activityInterface.getCreatedActivity() instanceof RecentsActivity + && DisplayController.getNavigationMode(mCtx) != NO_BUTTON) { + // The only time we get onTasksAppeared() in button navigation with a + // 3p launcher is if the user goes to overview first, and in this case we + // can immediately finish the transition + RecentsView recentsView = + activityInterface.getCreatedActivity().getOverviewPanel(); + if (recentsView != null) { + recentsView.finishRecentsAnimation(true, null); + } return; } } diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 499a2601a9..1238819acd 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -473,16 +473,14 @@ public final class TaskViewUtils { throw new IllegalStateException( "Expected task to be showing, but it is " + mode); } - if (change.getParent() == null) { - throw new IllegalStateException("Initiating multi-split launch but the split" - + "root of " + taskId + " is already visible or has broken hierarchy."); - } } if (taskId == initialTaskId) { - splitRoot1 = transitionInfo.getChange(change.getParent()); + splitRoot1 = change.getParent() == null ? change : + transitionInfo.getChange(change.getParent()); } if (taskId == secondTaskId) { - splitRoot2 = transitionInfo.getChange(change.getParent()); + splitRoot2 = change.getParent() == null ? change : + transitionInfo.getChange(change.getParent()); } } diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java index ab70272852..eac09ad7dc 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java @@ -103,7 +103,8 @@ public class ProgressDelegateInputConsumer implements InputConsumer, mStateCallback = new MultiStateCallback(STATE_NAMES); mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED, this::endRemoteAnimation); - mStateCallback.runOnceAtState(STATE_FLING_FINISHED, this::onFlingFinished); + mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_FLING_FINISHED, + this::onFlingFinished); mSwipeDetector = new SingleAxisSwipeDetector(mContext, this, VERTICAL); mSwipeDetector.setDetectableScrollConditions(DIRECTION_POSITIVE, false); diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java index 2eaff46715..6619dd86f6 100644 --- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java +++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java @@ -254,6 +254,9 @@ public class AllSetActivity extends Activity { mBinder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null); mBinder.setOverviewTargetChangeListener(mBinder::preloadOverviewForSUWAllSet); mBinder.preloadOverviewForSUWAllSet(); + if (mTaskbarManager != null) { + mLauncherStartAnim = mTaskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION); + } } @Override @@ -328,12 +331,9 @@ public class AllSetActivity extends Activity { mRootView.setAlpha(alpha); mRootView.setTranslationY((alpha - 1) * mSwipeUpShift); - if (mLauncherStartAnim == null && mTaskbarManager != null) { - mLauncherStartAnim = mTaskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION); - } if (mLauncherStartAnim != null) { - mLauncherStartAnim.setPlayFraction(Utilities.mapBoundToRange( - mSwipeProgress.value, 0, 1, 0, 1, FAST_OUT_SLOW_IN)); + mLauncherStartAnim.setPlayFraction( + FAST_OUT_SLOW_IN.getInterpolation(mSwipeProgress.value)); } maybeResumeOrPauseBackgroundAnimation(); } diff --git a/quickstep/src/com/android/quickstep/util/TaskRestartedDuringLaunchListener.java b/quickstep/src/com/android/quickstep/util/TaskRestartedDuringLaunchListener.java new file mode 100644 index 0000000000..91e8376990 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/TaskRestartedDuringLaunchListener.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep.util; + +import static android.app.ActivityTaskManager.INVALID_TASK_ID; + +import android.app.Activity; +import android.app.ActivityManager; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter; +import com.android.quickstep.RecentsModel; +import com.android.systemui.shared.system.TaskStackChangeListener; +import com.android.systemui.shared.system.TaskStackChangeListeners; + +/** + * This class tracks the failure of a task launch through the Launcher.startActivitySafely() call, + * in an edge case in which a task may already be visible on screen (ie. in PIP) and no transition + * will be run in WM, which results in expected callbacks to not be processed. + * + * We transiently register a task stack listener during a task launch and if the restart signal is + * received, then the registered callback will be notified. + */ +public class TaskRestartedDuringLaunchListener implements TaskStackChangeListener { + + private static final String TAG = "TaskRestartedDuringLaunchListener"; + + private @NonNull Runnable mTaskRestartedCallback = null; + + /** + * Registers a failure listener callback if it detects a scenario in which an app launch + * resulted in an already existing task to be "restarted". + */ + public void register(@NonNull Runnable taskRestartedCallback) { + TaskStackChangeListeners.getInstance().registerTaskStackListener(this); + mTaskRestartedCallback = taskRestartedCallback; + } + + /** + * Unregisters the failure listener. + */ + public void unregister() { + TaskStackChangeListeners.getInstance().unregisterTaskStackListener(this); + mTaskRestartedCallback = null; + } + + @Override + public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, + boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { + if (wasVisible) { + Log.d(TAG, "Detected activity restart during launch for task=" + task.taskId); + mTaskRestartedCallback.run(); + unregister(); + } + } +} diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 17d83ec208..83a5c72127 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -841,17 +841,20 @@ public class TaskView extends FrameLayout implements Reusable { // the actual overview state failureListener.register(mActivity, mTask.key.id, () -> { notifyTaskLaunchFailed(TAG); - // Disable animations for now, as it is an edge case and the app usually covers - // launcher and also any state transition animation also gets clobbered by - // QuickstepTransitionManager.createWallpaperOpenAnimations when launcher - // shows again - getRecentsView().startHome(false /* animated */); RecentsView rv = getRecentsView(); - if (rv != null && rv.mSizeStrategy.getTaskbarController() != null) { - // LauncherTaskbarUIController depends on the launcher state when checking - // whether to handle resume, but that can come in before startHome() changes - // the state, so force-refresh here to ensure the taskbar is updated - rv.mSizeStrategy.getTaskbarController().refreshResumedState(); + if (rv != null) { + // Disable animations for now, as it is an edge case and the app usually + // covers launcher and also any state transition animation also gets + // clobbered by QuickstepTransitionManager.createWallpaperOpenAnimations + // when launcher shows again + rv.startHome(false /* animated */); + if (rv.mSizeStrategy.getTaskbarController() != null) { + // LauncherTaskbarUIController depends on the launcher state when + // checking whether to handle resume, but that can come in before + // startHome() changes the state, so force-refresh here to ensure the + // taskbar is updated + rv.mSizeStrategy.getTaskbarController().refreshResumedState(); + } } }); } diff --git a/res/color-v31/surface.xml b/res/color-v31/surface.xml deleted file mode 100644 index da4571a61c..0000000000 --- a/res/color-v31/surface.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - diff --git a/res/drawable/add_item_dialog_background.xml b/res/drawable/add_item_dialog_background.xml index c3a82695c2..e279fa051a 100644 --- a/res/drawable/add_item_dialog_background.xml +++ b/res/drawable/add_item_dialog_background.xml @@ -1,7 +1,7 @@ - + diff --git a/res/drawable/button_top_rounded_bordered_ripple.xml b/res/drawable/button_top_rounded_bordered_ripple.xml index f15a4a0c5f..f5b68866cb 100644 --- a/res/drawable/button_top_rounded_bordered_ripple.xml +++ b/res/drawable/button_top_rounded_bordered_ripple.xml @@ -25,7 +25,7 @@ android:topRightRadius="12dp" android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp" /> - + diff --git a/res/layout/hotseat.xml b/res/layout/hotseat.xml index 95ebd94d0e..82b0b8d74e 100644 --- a/res/layout/hotseat.xml +++ b/res/layout/hotseat.xml @@ -21,5 +21,4 @@ android:layout_height="match_parent" android:theme="@style/HomeScreenElementTheme" android:importantForAccessibility="no" - android:preferKeepClear="true" launcher:containerType="hotseat" /> \ No newline at end of file diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 25eb16079f..66690431ec 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -2194,6 +2194,8 @@ public class Launcher extends StatefulActivity /** * Returns the CellLayout of the specified container at the specified screen. + * + * @param screenId must be presenterPos and not modelPos. */ public CellLayout getCellLayout(int container, int screenId) { return (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java index d4140d851c..1977704588 100644 --- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java @@ -43,7 +43,6 @@ import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; import android.util.SparseArray; -import android.util.TypedValue; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -272,9 +271,8 @@ public class ActivityAllAppsContainerView 0, 0 // Bottom left }; - final TypedValue value = new TypedValue(); - getContext().getTheme().resolveAttribute(android.R.attr.colorBackground, value, true); - mBottomSheetBackgroundColor = value.data; + mBottomSheetBackgroundColor = + Themes.getAttrColor(getContext(), R.attr.materialColorSurfaceDim); updateBackgroundVisibility(mActivityContext.getDeviceProfile()); mSearchUiManager.initializeSearch(this); } diff --git a/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java b/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java index cb1216109a..a2e26b37f3 100644 --- a/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java +++ b/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java @@ -19,8 +19,10 @@ import android.view.View; import com.android.launcher3.CellLayout; import com.android.launcher3.MultipageCellLayout; +import com.android.launcher3.ShortcutAndWidgetContainer; import com.android.launcher3.util.GridOccupancy; +import java.util.Arrays; import java.util.function.Supplier; /** @@ -79,7 +81,7 @@ public class MulticellReorderAlgorithm extends ReorderAlgorithm { lp.canReorder = false; mcl.setCountX(mcl.getCountX() + 1); mcl.getShortcutsAndWidgets().addViewInLayout(mSeam, lp); - mcl.setOccupied(createGridOccupancyWithSeam(mcl.getOccupied())); + mcl.setOccupied(createGridOccupancyWithSeam()); mcl.mTmpOccupied = new GridOccupancy(mcl.getCountX(), mcl.getCountY()); } @@ -93,7 +95,8 @@ public class MulticellReorderAlgorithm extends ReorderAlgorithm { /** * The function supplied here will execute while the CellLayout has a simulated seam added. - * @param f function to run under simulation + * + * @param f function to run under simulation * @param return value of the supplied function * @return Value of supplied function */ @@ -110,18 +113,17 @@ public class MulticellReorderAlgorithm extends ReorderAlgorithm { return res; } - GridOccupancy createGridOccupancyWithSeam(GridOccupancy gridOccupancy) { + GridOccupancy createGridOccupancyWithSeam() { + ShortcutAndWidgetContainer shortcutAndWidgets = mCellLayout.getShortcutsAndWidgets(); GridOccupancy grid = new GridOccupancy(mCellLayout.getCountX(), mCellLayout.getCountY()); - for (int x = 0; x < mCellLayout.getCountX(); x++) { - for (int y = 0; y < mCellLayout.getCountY(); y++) { - int offset = x >= mCellLayout.getCountX() / 2 ? 1 : 0; - if (x == mCellLayout.getCountX() / 2) { - grid.cells[x][y] = true; - } else { - grid.cells[x][y] = gridOccupancy.cells[x - offset][y]; - } - } + for (int i = 0; i < shortcutAndWidgets.getChildCount(); i++) { + View view = shortcutAndWidgets.getChildAt(i); + CellLayoutLayoutParams lp = (CellLayoutLayoutParams) view.getLayoutParams(); + int seamOffset = lp.getCellX() >= mCellLayout.getCountX() / 2 && lp.canReorder ? 1 : 0; + grid.markCells(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan, lp.cellVSpan, + true); } + Arrays.fill(grid.cells[mCellLayout.getCountX() / 2], true); return grid; } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index f5f6769c33..b255ea8a18 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -194,7 +194,7 @@ public final class FeatureFlags { "In foldables, when reordering the icons and widgets, is now going to use both sides"); public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274, - "FOLDABLE_SINGLE_PAGE", ENABLED, "Use a single page for the workspace"); + "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace"); // TODO(Block 12): Clean up flags public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680, diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java index f15dc83387..7ac2472319 100644 --- a/src/com/android/launcher3/folder/LauncherDelegate.java +++ b/src/com/android/launcher3/folder/LauncherDelegate.java @@ -93,7 +93,7 @@ public class LauncherDelegate { // Move the item from the folder to the workspace, in the position of the // folder CellLayout cellLayout = mLauncher.getCellLayout(info.container, - info.screenId); + mLauncher.getCellPosMapper().mapModelToPresenter(info).screenId); if (cellLayout == null) { return; } diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 8274789ef5..1f26bab502 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -125,6 +125,14 @@ public class PopupContainerWithArrow this(context, null, 0); } + @Override + protected View getAccessibilityInitialFocusView() { + if (mSystemShortcutContainer != null) { + return mSystemShortcutContainer.getChildAt(0); + } + return super.getAccessibilityInitialFocusView(); + } + public LauncherAccessibilityDelegate getAccessibilityDelegate() { return mAccessibilityDelegate; } @@ -242,7 +250,6 @@ public class PopupContainerWithArrow popupDataProvider.getNotificationKeysForItem(item), systemShortcuts); } - launcher.tryClearAccessibilityFocus(icon); launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item)); container.requestFocus(); return container;