Use splashscreen if we can't fill horizontaly with snapshot
A gap at the right side of the snapshot looks pretty bad. Thus,
we use a splash screen in case there would be a gap on the right
side. However, we don't want to do this from recents as we'd
produce another flicker
Test: go/wm-smoke
Test: Open app portrait, go launcher, rotate, open app landscape
Test: Open app landscape, go launcher rotate, open app portrait
Fixes: 62094756
Change-Id: Iaf1fecced822685187477a4698fa6b67c6e485d7
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 30df978..a25a1bf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10254,11 +10254,11 @@
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
synchronized(this) {
- moveTaskToFrontLocked(taskId, flags, bOptions);
+ moveTaskToFrontLocked(taskId, flags, bOptions, false /* fromRecents */);
}
}
- void moveTaskToFrontLocked(int taskId, int flags, Bundle bOptions) {
+ void moveTaskToFrontLocked(int taskId, int flags, Bundle bOptions, boolean fromRecents) {
ActivityOptions options = ActivityOptions.fromBundle(bOptions);
if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
@@ -10291,7 +10291,7 @@
// We are reshowing a task, use a starting window to hide the initial draw delay
// so the transition can start earlier.
topActivity.showStartingWindow(null /* prev */, false /* newTask */,
- true /* taskSwitch */);
+ true /* taskSwitch */, fromRecents);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index ec6a4f6..a826b68 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -2153,6 +2153,11 @@
}
void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
+ showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
+ }
+
+ void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
+ boolean fromRecents) {
if (mWindowContainerController == null) {
return;
}
@@ -2167,7 +2172,8 @@
compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
allowTaskSnapshot(),
- state.ordinal() >= RESUMED.ordinal() && state.ordinal() <= STOPPED.ordinal());
+ state.ordinal() >= RESUMED.ordinal() && state.ordinal() <= STOPPED.ordinal(),
+ fromRecents);
if (shown) {
mStartingWindowState = STARTING_WINDOW_SHOWN;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 53afe78..7de56fa 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -5131,7 +5131,7 @@
&& task.getRootActivity() != null) {
mService.mActivityStarter.sendPowerHintForLaunchStartIfNeeded(true /* forceSend */);
mActivityMetricsLogger.notifyActivityLaunching();
- mService.moveTaskToFrontLocked(task.taskId, 0, bOptions);
+ mService.moveTaskToFrontLocked(task.taskId, 0, bOptions, true /* fromRecents */);
mActivityMetricsLogger.notifyActivityLaunched(ActivityManager.START_TASK_TO_FRONT,
task.getTopActivity());
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 8cfbf68..e550a5e 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -40,6 +40,7 @@
import android.os.IBinder;
import android.os.Trace;
import android.util.Slog;
+import android.view.DisplayInfo;
import android.view.IApplicationToken;
import android.view.WindowManagerPolicy.StartingSurface;
@@ -481,7 +482,7 @@
public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
- boolean allowTaskSnapshot, boolean activityCreated) {
+ boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
synchronized(mWindowMap) {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
+ " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
@@ -510,11 +511,14 @@
return false;
}
+ final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot(
+ mContainer.getTask().mTaskId, mContainer.getTask().mUserId,
+ false /* restoreFromDisk */, false /* reducedResolution */);
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
- allowTaskSnapshot, activityCreated);
+ allowTaskSnapshot, activityCreated, fromRecents, snapshot);
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
- return createSnapshot();
+ return createSnapshot(snapshot);
}
// If this is a translucent window, then don't show a starting window -- the current
@@ -582,7 +586,8 @@
}
private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
- boolean allowTaskSnapshot, boolean activityCreated) {
+ boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
+ TaskSnapshot snapshot) {
if (mService.mAppTransition.getAppTransition() == TRANSIT_DOCK_TASK_FROM_RECENTS) {
// TODO(b/34099271): Remove this statement to add back the starting window and figure
// out why it causes flickering, the starting window appears over the thumbnail while
@@ -591,7 +596,9 @@
} else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else if (taskSwitch && allowTaskSnapshot) {
- return STARTING_WINDOW_TYPE_SNAPSHOT;
+ return snapshot == null ? STARTING_WINDOW_TYPE_NONE
+ : snapshotFillsWidth(snapshot) || fromRecents ? STARTING_WINDOW_TYPE_SNAPSHOT
+ : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else {
return STARTING_WINDOW_TYPE_NONE;
}
@@ -605,11 +612,7 @@
mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
}
- private boolean createSnapshot() {
- final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot(
- mContainer.getTask().mTaskId, mContainer.getTask().mUserId,
- false /* restoreFromDisk */, false /* reducedResolution */);
-
+ private boolean createSnapshot(TaskSnapshot snapshot) {
if (snapshot == null) {
return false;
}
@@ -620,6 +623,24 @@
return true;
}
+ private boolean snapshotFillsWidth(TaskSnapshot snapshot) {
+ if (snapshot == null) {
+ return false;
+ }
+ final Rect rect = new Rect(0, 0, snapshot.getSnapshot().getWidth(),
+ snapshot.getSnapshot().getHeight());
+ rect.inset(snapshot.getContentInsets());
+ final Rect taskBoundsWithoutInsets = new Rect();
+ mContainer.getTask().getBounds(taskBoundsWithoutInsets);
+ final DisplayInfo di = mContainer.getDisplayContent().getDisplayInfo();
+ final Rect displayBounds = new Rect(0, 0, di.logicalWidth, di.logicalHeight);
+ final Rect stableInsets = new Rect();
+ mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ stableInsets);
+ displayBounds.inset(stableInsets);
+ return rect.width() >= displayBounds.width();
+ }
+
public void removeStartingWindow() {
synchronized (mWindowMap) {
if (mHandler.hasCallbacks(mRemoveStartingWindow)) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 768b03a..6e1d0d8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1266,14 +1266,6 @@
+ token + ". Aborting.");
return WindowManagerGlobal.ADD_APP_EXITING;
}
- if (rootType == TYPE_APPLICATION_STARTING
- && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0
- && atoken.firstWindowDrawn) {
- // No need for this guy!
- if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v(
- TAG_WM, "**** NO NEED TO START: " + attrs.getTitle());
- return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
- }
} else if (rootType == TYPE_INPUT_METHOD) {
if (token.windowType != TYPE_INPUT_METHOD) {
Slog.w(TAG_WM, "Attempted to add input method window with bad token "
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 65a5632..6060881 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -107,7 +107,7 @@
createAppWindowController();
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false);
+ false, false);
waitUntilHandlersIdle();
final AppWindowToken atoken = controller.getAppWindowToken(mDisplayContent);
assertHasStartingWindow(atoken);
@@ -125,7 +125,7 @@
createAppWindowController();
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false);
+ false, false);
controller.removeStartingWindow();
waitUntilHandlersIdle();
assertNoStartingWindow(controller.getAppWindowToken(mDisplayContent));
@@ -140,11 +140,11 @@
createAppWindowController();
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false);
+ false, false);
waitUntilHandlersIdle();
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false, true, false);
+ true, true, false, true, false, false);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));
@@ -161,11 +161,11 @@
// Surprise, ...! Transfer window in the middle of the creation flow.
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false, true, false);
+ true, true, false, true, false, false);
});
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false);
+ false, false);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));