Fix freeze issue after launch single app

Wrapping remote animation within options is not suitable for
starting shortcut/intent cases, it might lead to not performing
the remote animation due to an empty pid.

Handle remote animation of entering split screen as:
1. wct.startTask: Use activity option to adapt it.
2. wct.sendPendingIntent and wct.startShortcut: Use legacy
   transition to adapt it.

Fix: 271216878
Test: manual
Test: pass existing tests
Change-Id: I5c37135b004a459f31205d2f0c2e0d9c9aabcac4
This commit is contained in:
Tony Huang
2023-03-01 19:39:38 +08:00
parent b85665b316
commit 7f05e1a97a

View File

@@ -764,17 +764,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
if (pendingIntent2 == null) {
// Launching a solo task.
ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
options1 = activityOptions.toBundle();
addActivityOptions(options1, null /* launchTarget */);
if (shortcutInfo1 != null) {
wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
} else {
wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
}
mSyncQueue.queue(wct);
// Launching a solo intent or shortcut as fullscreen.
launchAsFullscreenWithRemoteAnimation(pendingIntent1, fillInIntent1, shortcutInfo1,
options1, adapter, wct);
return;
}
@@ -797,13 +789,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
if (taskId == INVALID_TASK_ID) {
// Launching a solo task.
ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
options1 = activityOptions.toBundle();
addActivityOptions(options1, null /* launchTarget */);
wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
mSyncQueue.queue(wct);
// Launching a solo intent as fullscreen.
launchAsFullscreenWithRemoteAnimation(pendingIntent, fillInIntent, null, options1,
adapter, wct);
return;
}
@@ -822,13 +810,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
if (taskId == INVALID_TASK_ID) {
// Launching a solo task.
ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
options1 = activityOptions.toBundle();
addActivityOptions(options1, null /* launchTarget */);
wct.startShortcut(mContext.getPackageName(), shortcutInfo, options1);
mSyncQueue.queue(wct);
// Launching a solo shortcut as fullscreen.
launchAsFullscreenWithRemoteAnimation(null, null, shortcutInfo, options1, adapter, wct);
return;
}
@@ -838,6 +821,49 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
instanceId);
}
private void launchAsFullscreenWithRemoteAnimation(@Nullable PendingIntent pendingIntent,
@Nullable Intent fillInIntent, @Nullable ShortcutInfo shortcutInfo,
@Nullable Bundle options, RemoteAnimationAdapter adapter,
WindowContainerTransaction wct) {
LegacyTransitions.ILegacyTransition transition =
(transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
if (apps == null || apps.length == 0) {
onRemoteAnimationFinished(apps);
t.apply();
try {
adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
return;
}
for (int i = 0; i < apps.length; ++i) {
if (apps[i].mode == MODE_OPENING) {
t.show(apps[i].leash);
}
}
t.apply();
try {
adapter.getRunner().onAnimationStart(
transit, apps, wallpapers, nonApps, finishedCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
};
addActivityOptions(options, null /* launchTarget */);
if (shortcutInfo != null) {
wct.startShortcut(mContext.getPackageName(), shortcutInfo, options);
} else if (pendingIntent != null) {
wct.sendPendingIntent(pendingIntent, fillInIntent, options);
} else {
Slog.e(TAG, "Pending intent and shortcut are null is invalid case.");
}
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
}
private void startWithLegacyTransition(WindowContainerTransaction wct,
@Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
@Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle mainOptions,
@@ -894,23 +920,25 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (options == null) options = new Bundle();
addActivityOptions(options, mMainStage);
options = wrapAsSplitRemoteAnimation(adapter, options);
updateWindowBounds(mSplitLayout, wct);
// TODO(b/268008375): Merge APIs to start a split pair into one.
if (mainTaskId != INVALID_TASK_ID) {
wct.startTask(mainTaskId, options);
} else if (mainShortcutInfo != null) {
wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
} else {
wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
}
wct.reorder(mRootTaskInfo.token, true);
wct.setForceTranslucent(mRootTaskInfo.token, false);
mSyncQueue.queue(wct);
// TODO(b/268008375): Merge APIs to start a split pair into one.
if (mainTaskId != INVALID_TASK_ID) {
options = wrapAsSplitRemoteAnimation(adapter, options);
wct.startTask(mainTaskId, options);
mSyncQueue.queue(wct);
} else {
if (mainShortcutInfo != null) {
wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
} else {
wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
}
mSyncQueue.queue(wrapAsSplitRemoteAnimation(adapter), WindowManager.TRANSIT_OPEN, wct);
}
mSyncQueue.runInSync(t -> {
setDividerVisibility(true, t);
});
@@ -967,6 +995,54 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return activityOptions.toBundle();
}
private LegacyTransitions.ILegacyTransition wrapAsSplitRemoteAnimation(
RemoteAnimationAdapter adapter) {
LegacyTransitions.ILegacyTransition transition =
(transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
if (apps == null || apps.length == 0) {
onRemoteAnimationFinished(apps);
t.apply();
try {
adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
return;
}
// Wrap the divider bar into non-apps target to animate together.
nonApps = ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps,
getDividerBarLegacyTarget());
for (int i = 0; i < apps.length; ++i) {
if (apps[i].mode == MODE_OPENING) {
t.show(apps[i].leash);
// Reset the surface position of the opening app to prevent offset.
t.setPosition(apps[i].leash, 0, 0);
}
}
t.apply();
IRemoteAnimationFinishedCallback wrapCallback =
new IRemoteAnimationFinishedCallback.Stub() {
@Override
public void onAnimationFinished() throws RemoteException {
onRemoteAnimationFinished(apps);
finishedCallback.onAnimationFinished();
}
};
Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication());
try {
adapter.getRunner().onAnimationStart(
transit, apps, wallpapers, nonApps, wrapCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
};
return transition;
}
private void setEnterInstanceId(InstanceId instanceId) {
if (instanceId != null) {
mLogger.enterRequested(instanceId, ENTER_REASON_LAUNCHER);
@@ -993,6 +1069,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
private void onRemoteAnimationFinished(RemoteAnimationTarget[] apps) {
mIsDividerRemoteAnimating = false;
mShouldUpdateRecents = true;
mSplitRequest = null;
// If any stage has no child after finished animation, that side of the split will display
// nothing. This might happen if starting the same app on the both sides while not
// supporting multi-instance. Exit the split screen and expand that app to full screen.
if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
mMainExecutor.execute(() -> exitSplitScreen(mMainStage.getChildCount() == 0
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
mSplitUnsupportedToast.show();
return;
}
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
prepareEvictNonOpeningChildTasks(SPLIT_POSITION_TOP_OR_LEFT, apps, evictWct);
prepareEvictNonOpeningChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, apps, evictWct);
mSyncQueue.queue(evictWct);
}
/**
* Collects all the current child tasks of a specific split and prepares transaction to evict
* them to display.