Fix app pairs launch from in-app Taskbar

This CL adds a handler function in SplitAnimationController that manages the complicated logic flow for launching an app pair when already inside of an app.

To give an idea of the complicated logic:
If the user tapped on an app pair while already in an app pair, there are 4 general cases:
  a) Clicked app pair A|B, but both apps are already running on screen
  b) App A is already on-screen, but App B isn't
  c) App B is on-screen, but App A isn't
  d) Neither is on-screen

If the user tapped an app pair while inside a single app, there are 3 cases:
   a) The on-screen app is App A of the app pair
   b) The on-screen app is App B of the app pair
   c) It is neither

For each case, we call a different animation and launch the app pair in a different way.

When merged, this patch will fix all animation glitches that are currently happening in these situations, and get us 90% of the way to having the ideal animation in all cases. There are still a few complicated cases that need a polished animation (like when you launch app pairs with custom ratios), which will be implemented in a following patch soon (I thought this CL was big enough already as is).

Bug: 316485863
Fixes: 315190686
Test: Manual testing of all the different launch combinations
Flag: ACONFIG com.android.wm.shell.enable_app_pairs TEAMFOOD
Change-Id: I5c0e03512bb706360c575d833cac6ed02a5de936
This commit is contained in:
Jeremy Sim
2024-02-06 16:23:04 +08:00
parent 6474a3b455
commit cf9132e07c
5 changed files with 587 additions and 19 deletions
@@ -1063,7 +1063,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
Toast.LENGTH_SHORT).show();
} else {
// Else launch the selected app pair
launchFromTaskbarPreservingSplitIfVisible(recents, view, fi.contents);
launchFromTaskbar(recents, view, fi.contents);
mControllers.uiController.onTaskbarIconLaunched(fi);
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
}
@@ -1097,8 +1097,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
getSystemService(LauncherApps.class)
.startShortcut(packageName, id, null, null, info.user);
} else {
launchFromTaskbarPreservingSplitIfVisible(
recents, view, Collections.singletonList(info));
launchFromTaskbar(recents, view, Collections.singletonList(info));
}
} catch (NullPointerException
@@ -1136,8 +1135,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
// If we are selecting a second app for split, launch the split tasks
taskbarUIController.triggerSecondAppForSplit(info, info.intent, view);
} else {
launchFromTaskbarPreservingSplitIfVisible(
recents, view, Collections.singletonList(info));
launchFromTaskbar(recents, view, Collections.singletonList(info));
}
mControllers.uiController.onTaskbarIconLaunched(info);
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
@@ -1152,13 +1150,49 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
}
}
/**
* Runs when the user taps a Taskbar icon in TaskbarActivityContext (Overview or inside an app),
* and calls the appropriate method to animate and launch.
*/
private void launchFromTaskbar(@Nullable RecentsView recents, @Nullable View launchingIconView,
List<? extends ItemInfo> itemInfos) {
if (isInApp()) {
launchFromInAppTaskbar(recents, launchingIconView, itemInfos);
} else {
launchFromOverviewTaskbar(recents, launchingIconView, itemInfos);
}
}
/**
* Runs when the user taps a Taskbar icon while inside an app.
*/
private void launchFromInAppTaskbar(@Nullable RecentsView recents,
@Nullable View launchingIconView, List<? extends ItemInfo> itemInfos) {
if (recents == null) {
return;
}
boolean tappedAppPair = itemInfos.size() == 2;
if (tappedAppPair) {
// If the icon is an app pair, the logic gets a bit complicated because we play
// different animations depending on which app (or app pair) is currently running on
// screen, so delegate logic to appPairsController.
recents.getSplitSelectController().getAppPairsController()
.handleAppPairLaunchInApp((AppPairIcon) launchingIconView, itemInfos);
} else {
// Tapped a single app, nothing complicated here.
startItemInfoActivity(itemInfos.get(0));
}
}
/**
* Run when the user taps a Taskbar icon while in Overview. If the tapped app is currently
* visible to the user in Overview, or is part of a visible split pair, we expand the TaskView
* as if the user tapped on it (preserving the split pair). Otherwise, launch it normally
* (potentially breaking a split pair).
*/
private void launchFromTaskbarPreservingSplitIfVisible(@Nullable RecentsView recents,
private void launchFromOverviewTaskbar(@Nullable RecentsView recents,
@Nullable View launchingIconView, List<? extends ItemInfo> itemInfos) {
if (recents == null) {
return;