From a5545793853a653ab4adf3a8192f3d4beaba9498 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Thu, 15 Jul 2021 14:42:27 +0800 Subject: [PATCH] Correct StartingWindowInfo for non-top activity. When finishing a top activity and goes to resume the below activity, if the resumed activity was gone and need to recreate, this should be treat as warm launch and there should show an empty style splash screen on it. Previous there do create a splash screen window but the parameters are wrong because we are trying to create the StartingWIndowInfo from the top activity. Fixes: 193040222 Test: atest ActivityRecordTests Test: 1. enable "Dont keep Activities" 2. Launch twitter, open link. 3. Click back key and there should show empty splash screen. Change-Id: I33ac43ef6ca79c7422a818e468a7af32c7894eeb --- .../com/android/server/wm/ActivityRecord.java | 52 +++++++++++++++-- .../server/wm/StartingSurfaceController.java | 4 +- .../core/java/com/android/server/wm/Task.java | 56 +++++-------------- .../server/wm/TaskOrganizerController.java | 16 +++--- .../server/wm/ActivityRecordTests.java | 6 +- 5 files changed, 75 insertions(+), 59 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 4c1992ef18b2b..22bff21831deb 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -253,6 +253,7 @@ import android.app.servertransaction.TopResumedActivityChangeItem; import android.app.servertransaction.TransferSplashScreenViewStateItem; import android.app.usage.UsageEvents.Event; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.LocusId; import android.content.pm.ActivityInfo; @@ -6236,7 +6237,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void showStartingWindow(boolean taskSwitch) { showStartingWindow(null /* prev */, false /* newTask */, taskSwitch, - 0 /* splashScreenTheme */, null); + false /* startActivity */, null); } /** @@ -6271,7 +6272,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return null; } - private boolean shouldUseEmptySplashScreen(ActivityRecord sourceRecord) { + private boolean shouldUseEmptySplashScreen(ActivityRecord sourceRecord, boolean startActivity) { + if (sourceRecord == null && !startActivity) { + // Use empty style if this activity is not top activity. This could happen when adding + // a splash screen window to the warm start activity which is re-create because top is + // finishing. + final ActivityRecord above = task.getActivityAbove(this); + if (above != null) { + return true; + } + } if (mPendingOptions != null) { final int optionsStyle = mPendingOptions.getSplashScreenStyle(); if (optionsStyle == SplashScreen.SPLASH_SCREEN_STYLE_EMPTY) { @@ -6298,8 +6308,41 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return true; } + private int getSplashscreenTheme() { + // Find the splash screen theme. User can override the persisted theme by + // ActivityOptions. + String splashScreenThemeResName = mPendingOptions != null + ? mPendingOptions.getSplashScreenThemeResName() : null; + if (splashScreenThemeResName == null || splashScreenThemeResName.isEmpty()) { + try { + splashScreenThemeResName = mAtmService.getPackageManager() + .getSplashScreenTheme(packageName, mUserId); + } catch (RemoteException ignore) { + // Just use the default theme + } + } + int splashScreenThemeResId = 0; + if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) { + try { + final Context packageContext = mAtmService.mContext + .createPackageContext(packageName, 0); + splashScreenThemeResId = packageContext.getResources() + .getIdentifier(splashScreenThemeResName, null, null); + } catch (PackageManager.NameNotFoundException + | Resources.NotFoundException ignore) { + // Just use the default theme + } + } + return splashScreenThemeResId; + } + + /** + * @param prev Previous activity which contains a starting window. + * @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, - int splashScreenTheme, ActivityRecord sourceRecord) { + boolean startActivity, ActivityRecord sourceRecord) { if (mTaskOverlay) { // We don't show starting window for overlay activities. return; @@ -6313,8 +6356,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final CompatibilityInfo compatInfo = mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo); - mSplashScreenStyleEmpty = shouldUseEmptySplashScreen(sourceRecord); + mSplashScreenStyleEmpty = shouldUseEmptySplashScreen(sourceRecord, startActivity); + final int splashScreenTheme = startActivity ? getSplashscreenTheme() : 0; final int resolvedTheme = evaluateStartingWindowTheme(prev, packageName, theme, splashScreenTheme); diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java index 45b53a1a99b91..26f03844d2674 100644 --- a/services/core/java/com/android/server/wm/StartingSurfaceController.java +++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java @@ -69,7 +69,7 @@ public class StartingSurfaceController { synchronized (mService.mGlobalLock) { final Task task = activity.getTask(); if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow( - task, activity.token, theme, null /* taskSnapshot */)) { + task, activity, theme, null /* taskSnapshot */)) { return new ShellStartingSurface(task); } } @@ -149,7 +149,7 @@ public class StartingSurfaceController { } if (DEBUG_ENABLE_SHELL_DRAWER) { mService.mAtmService.mTaskOrganizerController.addStartingWindow(task, - activity.token, 0 /* launchTheme */, taskSnapshot); + activity, 0 /* launchTheme */, taskSnapshot); return new ShellStartingSurface(task); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 936b2efa00ad5..a11325422e296 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -179,14 +179,12 @@ import android.app.servertransaction.NewIntentItem; import android.app.servertransaction.PauseActivityItem; import android.app.servertransaction.ResumeActivityItem; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; @@ -4163,26 +4161,25 @@ class Task extends WindowContainer { return info; } - StartingWindowInfo getStartingWindowInfo() { + /** + * Returns a {@link StartingWindowInfo} with information from this task and the target activity. + * @param activity Target activity which to show the starting window. + */ + StartingWindowInfo getStartingWindowInfo(ActivityRecord activity) { final StartingWindowInfo info = new StartingWindowInfo(); info.taskInfo = getTaskInfo(); info.isKeyguardOccluded = mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY); - final ActivityRecord topActivity = getTopMostActivity(); - if (topActivity != null) { - info.startingWindowTypeParameter = - topActivity.mStartingData != null - ? topActivity.mStartingData.mTypeParams - : 0; - final WindowState mainWindow = topActivity.findMainWindow(); - if (mainWindow != null) { - info.mainWindowLayoutParams = mainWindow.getAttrs(); - } - // 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. - info.taskInfo.configuration.setTo(topActivity.getConfiguration()); + + info.startingWindowTypeParameter = activity.mStartingData.mTypeParams; + final WindowState mainWindow = activity.findMainWindow(); + if (mainWindow != null) { + info.mainWindowLayoutParams = mainWindow.getAttrs(); } + // 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. + info.taskInfo.configuration.setTo(activity.getConfiguration()); final ActivityRecord topFullscreenActivity = getTopFullscreenActivity(); if (topFullscreenActivity != null) { final WindowState topFullscreenOpaqueWindow = @@ -6691,33 +6688,8 @@ class Task extends WindowContainer { } } - // Find the splash screen theme. User can override the persisted theme by - // ActivityOptions. - String splashScreenThemeResName = options != null - ? options.getSplashScreenThemeResName() : null; - if (splashScreenThemeResName == null || splashScreenThemeResName.isEmpty()) { - try { - splashScreenThemeResName = mAtmService.getPackageManager() - .getSplashScreenTheme(r.packageName, r.mUserId); - } catch (RemoteException ignore) { - // Just use the default theme - } - } - int splashScreenThemeResId = 0; - if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) { - try { - final Context packageContext = mAtmService.mContext - .createPackageContext(r.packageName, 0); - splashScreenThemeResId = packageContext.getResources() - .getIdentifier(splashScreenThemeResName, null, null); - } catch (PackageManager.NameNotFoundException - | Resources.NotFoundException ignore) { - // Just use the default theme - } - } - r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity), - splashScreenThemeResId, sourceRecord); + true /* startActivity */, sourceRecord); } } else { // If this is the first activity, don't do any fancy animations, diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 2dc63ce381111..09c5581385dd0 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -122,16 +122,16 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { return mTaskOrganizer.asBinder(); } - void addStartingWindow(Task task, IBinder appToken, int launchTheme, + void addStartingWindow(Task task, ActivityRecord activity, int launchTheme, TaskSnapshot taskSnapshot) { - final StartingWindowInfo info = task.getStartingWindowInfo(); + final StartingWindowInfo info = task.getStartingWindowInfo(activity); if (launchTheme != 0) { info.splashScreenThemeResId = launchTheme; } info.mTaskSnapshot = taskSnapshot; // make this happen prior than prepare surface try { - mTaskOrganizer.addStartingWindow(info, appToken); + mTaskOrganizer.addStartingWindow(info, activity.token); } catch (RemoteException e) { Slog.e(TAG, "Exception sending onTaskStart callback", e); } @@ -311,9 +311,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { mUid = uid; } - void addStartingWindow(Task t, IBinder appToken, int launchTheme, + void addStartingWindow(Task t, ActivityRecord activity, int launchTheme, TaskSnapshot taskSnapshot) { - mOrganizer.addStartingWindow(t, appToken, launchTheme, taskSnapshot); + mOrganizer.addStartingWindow(t, activity, launchTheme, taskSnapshot); } void removeStartingWindow(Task t, boolean prepareAnimation) { @@ -547,15 +547,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { return !ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, winMode); } - boolean addStartingWindow(Task task, IBinder appToken, int launchTheme, + boolean addStartingWindow(Task task, ActivityRecord activity, int launchTheme, TaskSnapshot taskSnapshot) { final Task rootTask = task.getRootTask(); - if (rootTask == null || rootTask.mTaskOrganizer == null) { + if (rootTask == null || rootTask.mTaskOrganizer == null || activity.mStartingData == null) { return false; } final TaskOrganizerState state = mTaskOrganizerStates.get(rootTask.mTaskOrganizer.asBinder()); - state.addStartingWindow(task, appToken, launchTheme, taskSnapshot); + state.addStartingWindow(task, activity, launchTheme, taskSnapshot); return true; } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index a1f1610d95db9..293e862a6b74c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2561,19 +2561,19 @@ public class ActivityRecordTests extends WindowTestsBase { final ActivityRecord sourceRecord = new ActivityBuilder(mAtm) .setCreateTask(true).setLaunchedFromUid(Process.SYSTEM_UID).build(); sourceRecord.showStartingWindow(null /* prev */, true /* newTask */, false, - 0 /* splashScreenTheme */, null); + true /* startActivity */, null); final ActivityRecord secondRecord = new ActivityBuilder(mAtm) .setTask(sourceRecord.getTask()).build(); secondRecord.showStartingWindow(null /* prev */, true /* newTask */, false, - 0 /* splashScreenTheme */, sourceRecord); + true /* startActivity */, sourceRecord); assertFalse(secondRecord.mSplashScreenStyleEmpty); secondRecord.onStartingWindowDrawn(); final ActivityRecord finalRecord = new ActivityBuilder(mAtm) .setTask(sourceRecord.getTask()).build(); finalRecord.showStartingWindow(null /* prev */, true /* newTask */, false, - 0 /* splashScreenTheme */, secondRecord); + true /* startActivity */, secondRecord); assertTrue(finalRecord.mSplashScreenStyleEmpty); }