Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a95bd4a8 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Attempt to use snapshot starting window for task trampoline

When launching a singleTask activity, it may find an existing
task to add. If the app uses it as trampoline/splash activity
(finished after redirecting to main), then it will still be
created every time.

For example: (A and B are in the same task)
First launch: Launch A from launcher, A starts B, A finished.
Second launch: Launch A from launcher, A finished, resume B.

Because it satisfies task-switch and activity-creation, by
default there will be a splash screen activity. But because the
new activity will finish itself immediately, it may be weird to
see the splash screen starting window at the second launch.

This approach infers that if the launching activity is the one
that started the task with other existing activities, it is
usually a temporal trampoline activity. So if the original top
activity of the task matches the existing snapshot, then use
snapshot starting window to make the visual result more continuous.

Bug: 229959739
Test: Second launch an app which declares singleTask for its
      trampoline and main activity. There should not show a
      splash screen starting window.
Change-Id: Ib0a39545e5b354fdb61d1cc0cb259900dba35a12
parent 9736fb2a
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2436,6 +2436,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
            boolean allowTaskSnapshot, boolean activityCreated, boolean activityAllDrawn,
            TaskSnapshot snapshot) {
        // A special case that a new activity is launching to an existing task which is moving to
        // front. If the launching activity is the one that started the task, it could be a
        // trampoline that will be always created and finished immediately. Then give a chance to
        // see if the snapshot is usable for the current running activity so the transition will
        // look smoother, instead of showing a splash screen on the second launch.
        if (!newTask && taskSwitch && processRunning && !activityCreated && task.intent != null
                && mActivityComponent.equals(task.intent.getComponent())) {
            final ActivityRecord topAttached = task.getActivity(ActivityRecord::attachedToProcess);
            if (topAttached != null && topAttached.isSnapshotCompatible(snapshot)) {
                return STARTING_WINDOW_TYPE_SNAPSHOT;
            }
        }
        final boolean isActivityHome = isActivityTypeHome();
        if ((newTask || !processRunning || (taskSwitch && !activityCreated))
                && !isActivityHome) {
+5 −5
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN;

import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_TYPE_SNAPSHOT;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -114,7 +115,7 @@ public class StartingSurfaceController {
        if (allowTaskSnapshot) {
            parameter |= TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
        }
        if (activityCreated) {
        if (activityCreated || startingWindowType == STARTING_WINDOW_TYPE_SNAPSHOT) {
            parameter |= TYPE_PARAMETER_ACTIVITY_CREATED;
        }
        if (isSolidColor) {
@@ -138,7 +139,6 @@ public class StartingSurfaceController {
        final WindowState topFullscreenOpaqueWindow;
        final Task task;
        synchronized (mService.mGlobalLock) {
            final WindowState mainWindow = activity.findMainWindow();
            task = activity.getTask();
            if (task == null) {
                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
@@ -153,9 +153,9 @@ public class StartingSurfaceController {
                return null;
            }
            topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
            if (mainWindow == null || topFullscreenOpaqueWindow == null) {
                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
                        + activity);
            if (topFullscreenOpaqueWindow == null) {
                Slog.w(TAG, "TaskSnapshotSurface.create: no opaque window in "
                        + topFullscreenActivity);
                return null;
            }
            if (topFullscreenActivity.getWindowConfiguration().getRotation()
+8 −4
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import static android.view.SurfaceControl.METADATA_TASK_ID;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
@@ -3525,10 +3526,13 @@ class Task extends TaskFragment {
            mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY);

        info.startingWindowTypeParameter = activity.mStartingData.mTypeParams;
        final WindowState mainWindow = activity.findMainWindow();
        if (mainWindow != null) {
            info.mainWindowLayoutParams = mainWindow.getAttrs();
            info.requestedVisibilities.set(mainWindow.getRequestedVisibilities());
        if ((info.startingWindowTypeParameter
                & StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED) != 0) {
            final WindowState topMainWin = getWindow(w -> w.mAttrs.type == TYPE_BASE_APPLICATION);
            if (topMainWin != null) {
                info.mainWindowLayoutParams = topMainWin.getAttrs();
                info.requestedVisibilities.set(topMainWin.getRequestedVisibilities());
            }
        }
        // If the developer has persist a different configuration, we need to override it to the
        // starting window because persisted configuration does not effect to Task.