Merge "Deferring add splash screen window when launch with startActivities"

This commit is contained in:
Wei Sheng Shih
2022-01-13 06:35:13 +00:00
committed by Android (Google) Code Review
4 changed files with 103 additions and 6 deletions

View File

@@ -2134,7 +2134,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return activityInfo != null ? activityInfo.applicationInfo : null;
});
final int typeParameter = mWmService.mStartingSurfaceController
final int typeParameter = StartingSurfaceController
.makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn);
@@ -6616,13 +6616,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return splashScreenThemeResId;
}
void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
boolean startActivity, ActivityRecord sourceRecord) {
showStartingWindow(prev, newTask, taskSwitch, isProcessRunning(), startActivity,
sourceRecord);
}
/**
* @param prev Previous activity which contains a starting window.
* @param processRunning Whether the client process is running.
* @param startActivity Whether this activity is just created from starter.
* @param sourceRecord The source activity which start this activity.
*/
void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
boolean startActivity, ActivityRecord sourceRecord) {
boolean processRunning, boolean startActivity, ActivityRecord sourceRecord) {
if (mTaskOverlay) {
// We don't show starting window for overlay activities.
return;
@@ -6647,7 +6654,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
&& task.getActivity((r) -> !r.finishing && r != this) == null;
final boolean scheduled = addStartingWindow(packageName, resolvedTheme,
prev, newTask || newSingleActivity, taskSwitch, isProcessRunning(),
prev, newTask || newSingleActivity, taskSwitch, processRunning,
allowTaskSnapshot(), activityCreated, mSplashScreenStyleEmpty, allDrawn);
if (DEBUG_STARTING_WINDOW_VERBOSE && scheduled) {
Slog.d(TAG, "Scheduled starting window for " + this);

View File

@@ -455,6 +455,10 @@ public class ActivityStartController {
// Lock the loop to ensure the activities launched in a sequence.
synchronized (mService.mGlobalLock) {
mService.deferWindowLayout();
// To avoid creating multiple starting window when creating starting multiples
// activities, we defer the creation of the starting window once all start request
// are processed
mService.mWindowManager.mStartingSurfaceController.beginDeferAddStartingWindow();
try {
for (int i = 0; i < starters.length; i++) {
final int startResult = starters[i].setResultTo(resultTo)
@@ -480,6 +484,7 @@ public class ActivityStartController {
}
}
} finally {
mService.mWindowManager.mStartingSurfaceController.endDeferAddStartingWindow();
mService.continueWindowLayout();
}
}

View File

@@ -34,6 +34,7 @@ import android.content.pm.ApplicationInfo;
import android.util.Slog;
import android.window.TaskSnapshot;
import java.util.ArrayList;
import java.util.function.Supplier;
/**
@@ -45,6 +46,14 @@ public class StartingSurfaceController {
private final WindowManagerService mService;
private final SplashScreenExceptionList mSplashScreenExceptionsList;
// Cache status while deferring add starting window
boolean mInitProcessRunning;
boolean mInitNewTask;
boolean mInitTaskSwitch;
private final ArrayList<DeferringStartingWindowRecord> mDeferringAddStartActivities =
new ArrayList<>();
private boolean mDeferringAddStartingWindow;
public StartingSurfaceController(WindowManagerService wm) {
mService = wm;
mSplashScreenExceptionsList = new SplashScreenExceptionList(wm.mContext.getMainExecutor());
@@ -70,7 +79,7 @@ public class StartingSurfaceController {
return mSplashScreenExceptionsList.isException(packageName, targetSdk, infoProvider);
}
int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
static int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
boolean useEmpty, boolean useLegacy, boolean activityDrawn) {
int parameter = 0;
@@ -142,6 +151,82 @@ public class StartingSurfaceController {
}
}
private static final class DeferringStartingWindowRecord {
final ActivityRecord mDeferring;
final ActivityRecord mPrev;
final ActivityRecord mSource;
DeferringStartingWindowRecord(ActivityRecord deferring, ActivityRecord prev,
ActivityRecord source) {
mDeferring = deferring;
mPrev = prev;
mSource = source;
}
}
/**
* Shows a starting window while starting a new activity. Do not use this method to create a
* starting window for an existing activity.
*/
void showStartingWindow(ActivityRecord target, ActivityRecord prev,
boolean newTask, boolean isTaskSwitch, ActivityRecord source) {
if (mDeferringAddStartingWindow) {
addDeferringRecord(target, prev, newTask, isTaskSwitch, source);
} else {
target.showStartingWindow(prev, newTask, isTaskSwitch, true /* startActivity */,
source);
}
}
/**
* Queueing the starting activity status while deferring add starting window.
* @see Task#startActivityLocked
*/
private void addDeferringRecord(ActivityRecord deferring, ActivityRecord prev,
boolean newTask, boolean isTaskSwitch, ActivityRecord source) {
// Set newTask, taskSwitch, processRunning form first activity because those can change
// after first activity started.
if (mDeferringAddStartActivities.isEmpty()) {
mInitProcessRunning = deferring.isProcessRunning();
mInitNewTask = newTask;
mInitTaskSwitch = isTaskSwitch;
}
mDeferringAddStartActivities.add(new DeferringStartingWindowRecord(
deferring, prev, source));
}
private void showStartingWindowFromDeferringActivities() {
// Attempt to add starting window from the top-most activity.
for (int i = mDeferringAddStartActivities.size() - 1; i >= 0; --i) {
final DeferringStartingWindowRecord next = mDeferringAddStartActivities.get(i);
next.mDeferring.showStartingWindow(next.mPrev, mInitNewTask, mInitTaskSwitch,
mInitProcessRunning, true /* startActivity */, next.mSource);
// If one succeeds, it is done.
if (next.mDeferring.mStartingData != null) {
break;
}
}
mDeferringAddStartActivities.clear();
}
/**
* Begin deferring add starting window in one pass.
* This is used to deferring add starting window while starting multiples activities because
* system only need to provide a starting window to the top-visible activity.
* Most call {@link #endDeferAddStartingWindow} when starting activities process finished.
* @see #endDeferAddStartingWindow()
*/
void beginDeferAddStartingWindow() {
mDeferringAddStartingWindow = true;
}
/**
* End deferring add starting window.
*/
void endDeferAddStartingWindow() {
mDeferringAddStartingWindow = false;
showStartingWindowFromDeferringActivities();
}
final class StartingSurface {
private final Task mTask;

View File

@@ -5149,8 +5149,8 @@ class Task extends TaskFragment {
final ActivityRecord prev = baseTask.getActivity(
a -> a.mStartingData != null && a.showToCurrentUser());
r.showStartingWindow(prev, newTask, isTaskSwitch,
true /* startActivity */, sourceRecord);
mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,
isTaskSwitch, sourceRecord);
}
} else {
// If this is the first activity, don't do any fancy animations,