Launch AppPair live tile when not visible

* End the recents animation and then relaunch as if
from scratch
* We explicitly ignore the anim for end of recents animation
since that will cause the taskbar to quickly show and stash
again, and we know in this case that we'll quickly be launching
right back into an app

Test: Tested w/ live tile + non live,
fullscreen + app pairs
Bug: 316485863

Change-Id: I6ae8cccc01401935bf96fba8a154216e6b1ad701
(cherry picked from commit 637274ebc9)
Merged-In: I6ae8cccc01401935bf96fba8a154216e6b1ad701
This commit is contained in:
Vinit Nayak
2024-04-02 11:45:02 -07:00
parent fc7f52967d
commit 95a7ca485e
5 changed files with 70 additions and 18 deletions

View File

@@ -312,6 +312,11 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mControllers.taskbarEduTooltipController.maybeShowSwipeEdu();
}
/** Will make the next onRecentsAnimationFinished() animation a no-op. */
public void setSkipNextRecentsAnimEnd() {
mTaskbarLauncherStateController.setSkipNextRecentsAnimEnd();
}
/**
* Returns {@code true} if a Taskbar education should be shown on application launch.
*/

View File

@@ -1231,13 +1231,13 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
return;
}
boolean findExactPairMatch = itemInfos.size() == 2;
boolean isLaunchingAppPair = itemInfos.size() == 2;
// Convert the list of ItemInfo instances to a list of ComponentKeys
List<ComponentKey> componentKeys =
itemInfos.stream().map(ItemInfo::getComponentKey).toList();
recents.getSplitSelectController().findLastActiveTasksAndRunCallback(
componentKeys,
findExactPairMatch,
isLaunchingAppPair,
foundTasks -> {
@Nullable Task foundTask = foundTasks[0];
if (foundTask != null) {
@@ -1251,10 +1251,18 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
}
}
if (findExactPairMatch) {
// We did not find the app pair we were looking for, so launch one.
recents.getSplitSelectController().getAppPairsController().launchAppPair(
(AppPairIcon) launchingIconView, -1 /*cuj*/);
if (isLaunchingAppPair) {
// Finish recents animation if it's running before launching to ensure
// we get both leashes for the animation
mControllers.uiController.setSkipNextRecentsAnimEnd();
recents.switchToScreenshot(() ->
recents.finishRecentsAnimation(true /*toRecents*/,
false /*shouldPip*/,
() -> recents
.getSplitSelectController()
.getAppPairsController()
.launchAppPair((AppPairIcon) launchingIconView,
-1 /*cuj*/)));
} else {
startItemInfoActivity(itemInfos.get(0));
}

View File

@@ -148,6 +148,7 @@ public class TaskbarLauncherStateController {
private Integer mPrevState;
private int mState;
private LauncherState mLauncherState = LauncherState.NORMAL;
private boolean mSkipNextRecentsAnimEnd;
// Time when FLAG_TASKBAR_HIDDEN was last cleared, SystemClock.elapsedRealtime (milliseconds).
private long mLastUnlockTimeMs = 0;
@@ -292,12 +293,12 @@ public class TaskbarLauncherStateController {
if (mTaskBarRecentsAnimationListener != null) {
mTaskBarRecentsAnimationListener.endGestureStateOverride(
!mLauncher.isInState(LauncherState.OVERVIEW));
!mLauncher.isInState(LauncherState.OVERVIEW), false /*canceled*/);
}
mTaskBarRecentsAnimationListener = new TaskBarRecentsAnimationListener(callbacks);
callbacks.addListener(mTaskBarRecentsAnimationListener);
((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(() ->
mTaskBarRecentsAnimationListener.endGestureStateOverride(true));
mTaskBarRecentsAnimationListener.endGestureStateOverride(true, false /*canceled*/));
((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchCancelledRunnable(() -> {
updateStateForUserFinishedToApp(false /* finishedToApp */);
@@ -318,6 +319,11 @@ public class TaskbarLauncherStateController {
mShouldDelayLauncherStateAnim = shouldDelayLauncherStateAnim;
}
/** Will make the next onRecentsAnimationFinished() a no-op. */
public void setSkipNextRecentsAnimEnd() {
mSkipNextRecentsAnimEnd = true;
}
/** SysUI flags updated, see QuickStepContract.SYSUI_STATE_* values. */
public void updateStateForSysuiFlags(int systemUiStateFlags) {
updateStateForSysuiFlags(systemUiStateFlags, /* applyState */ true);
@@ -770,19 +776,33 @@ public class TaskbarLauncherStateController {
@Override
public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
boolean isInOverview = mLauncher.isInState(LauncherState.OVERVIEW);
endGestureStateOverride(!isInOverview);
endGestureStateOverride(!isInOverview, true /*canceled*/);
}
@Override
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
endGestureStateOverride(!controller.getFinishTargetIsLauncher());
endGestureStateOverride(!controller.getFinishTargetIsLauncher(), false /*canceled*/);
}
private void endGestureStateOverride(boolean finishedToApp) {
/**
* Handles whatever cleanup is needed after the recents animation is completed.
* NOTE: If {@link #mSkipNextRecentsAnimEnd} is set and we're coming from a non-cancelled
* path, this will not call {@link #updateStateForUserFinishedToApp(boolean)}
*
* @param finishedToApp {@code true} if the recents animation finished to showing an app and
* not workspace or overview
* @param canceled {@code true} if the recents animation was canceled instead of finishing
* to completion
*/
private void endGestureStateOverride(boolean finishedToApp, boolean canceled) {
mCallbacks.removeListener(this);
mTaskBarRecentsAnimationListener = null;
((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(null);
if (mSkipNextRecentsAnimEnd && !canceled) {
mSkipNextRecentsAnimEnd = false;
return;
}
updateStateForUserFinishedToApp(finishedToApp);
}
}

View File

@@ -394,4 +394,12 @@ public class TaskbarUIController {
mControllers.taskbarStashController.updateStateForFlag(FLAG_IN_APP, !isVisible);
mControllers.taskbarStashController.applyState();
}
/**
* Request for UI controller to ignore animations for the next callback for the end of recents
* animation
*/
public void setSkipNextRecentsAnimEnd() {
// Overridden
}
}

View File

@@ -1254,16 +1254,23 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
appAnimator.setInterpolator(ACCELERATE_DECELERATE);
final Matrix matrix = new Matrix();
appAnimator.addUpdateListener(valueAnimator -> {
float percent = valueAnimator.getAnimatedFraction();
SurfaceTransaction transaction = new SurfaceTransaction();
Matrix matrix = new Matrix();
matrix.postScale(percent, percent);
matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
transaction.forSurface(apps[apps.length - 1].leash)
.setAlpha(percent)
.setMatrix(matrix);
for (int i = apps.length - 1; i >= 0; --i) {
RemoteAnimationTarget app = apps[i];
float dx = mActivity.getDeviceProfile().widthPx * (1 - percent) / 2
+ app.screenSpaceBounds.left * percent;
float dy = mActivity.getDeviceProfile().heightPx * (1 - percent) / 2
+ app.screenSpaceBounds.top * percent;
matrix.setScale(percent, percent);
matrix.postTranslate(dx, dy);
transaction.forSurface(app.leash)
.setAlpha(percent)
.setMatrix(matrix);
}
surfaceApplier.scheduleApply(transaction);
});
appAnimator.addListener(new AnimatorListenerAdapter() {
@@ -5418,6 +5425,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
finishRecentsAnimation(toRecents, true /* shouldPip */, onFinishComplete);
}
/**
* NOTE: Whatever value gets passed through to the toRecents param may need to also be set on
* {@link #mRecentsAnimationController#setWillFinishToHome}.
*/
public void finishRecentsAnimation(boolean toRecents, boolean shouldPip,
@Nullable Runnable onFinishComplete) {
Log.d(TAG, "finishRecentsAnimation - mRecentsAnimationController: "