Only use snapshot starting window for the same rotation
So the snapshot won't show half if the its has a delta of 90 degree rotation with the actual activity. If the snapshot is not compatible with the activity, the starting window type will be splash screen. Bug: 155862858 Test: atest ActivityRecordTests#testIsSnapshotCompatible Change-Id: I8d8a926d057f1d18d028fcc03bddbb17ffbbf96b
This commit is contained in:
@@ -1705,7 +1705,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
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 fromRecents) {
|
||||
boolean allowTaskSnapshot, boolean activityCreated) {
|
||||
// If the display is frozen, we won't do anything until the actual window is
|
||||
// displayed so there is no reason to put in the starting window.
|
||||
if (!okToDisplay()) {
|
||||
@@ -1726,7 +1726,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
|
||||
false /* restoreFromDisk */, false /* isLowResolution */);
|
||||
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
|
||||
allowTaskSnapshot, activityCreated, fromRecents, snapshot);
|
||||
allowTaskSnapshot, activityCreated, snapshot);
|
||||
|
||||
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
|
||||
if (isActivityTypeHome()) {
|
||||
@@ -1888,12 +1888,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
|
||||
|
||||
private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
|
||||
boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
|
||||
boolean allowTaskSnapshot, boolean activityCreated,
|
||||
ActivityManager.TaskSnapshot snapshot) {
|
||||
if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
|
||||
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||
} else if (taskSwitch && allowTaskSnapshot) {
|
||||
if (snapshotOrientationSameAsTask(snapshot) || (snapshot != null && fromRecents)) {
|
||||
if (isSnapshotCompatible(snapshot)) {
|
||||
return STARTING_WINDOW_TYPE_SNAPSHOT;
|
||||
}
|
||||
if (!isActivityTypeHome()) {
|
||||
@@ -1905,11 +1905,22 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
}
|
||||
|
||||
private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
|
||||
/**
|
||||
* Returns {@code true} if the task snapshot is compatible with this activity (at least the
|
||||
* rotation must be the same).
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isSnapshotCompatible(ActivityManager.TaskSnapshot snapshot) {
|
||||
if (snapshot == null) {
|
||||
return false;
|
||||
}
|
||||
return task.getConfiguration().orientation == snapshot.getOrientation();
|
||||
final int rotation = mDisplayContent.rotationForActivityInDifferentOrientation(this);
|
||||
final int targetRotation = rotation != ROTATION_UNDEFINED
|
||||
// The display may rotate according to the orientation of this activity.
|
||||
? rotation
|
||||
// The activity won't change display orientation.
|
||||
: task.getWindowConfiguration().getRotation();
|
||||
return snapshot.getRotation() == targetRotation;
|
||||
}
|
||||
|
||||
void removeStartingWindow() {
|
||||
@@ -5664,11 +5675,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
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 (mTaskOverlay) {
|
||||
// We don't show starting window for overlay activities.
|
||||
return;
|
||||
@@ -5685,8 +5691,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
|
||||
prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
|
||||
allowTaskSnapshot(),
|
||||
mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
|
||||
fromRecents);
|
||||
mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal());
|
||||
if (shown) {
|
||||
mStartingWindowState = STARTING_WINDOW_SHOWN;
|
||||
}
|
||||
|
||||
@@ -2498,7 +2498,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
|
||||
mActivityMetricsLogger.notifyActivityLaunching(task.intent);
|
||||
try {
|
||||
mService.moveTaskToFrontLocked(null /* appThread */, null /* callingPackage */,
|
||||
task.mTaskId, 0, options, true /* fromRecents */);
|
||||
task.mTaskId, 0, options);
|
||||
// Apply options to prevent pendingOptions be taken by client to make sure
|
||||
// the override pending app transition will be applied immediately.
|
||||
targetActivity.applyOptionsLocked();
|
||||
|
||||
@@ -2476,13 +2476,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
|
||||
synchronized (mGlobalLock) {
|
||||
moveTaskToFrontLocked(appThread, callingPackage, taskId, flags,
|
||||
SafeActivityOptions.fromBundle(bOptions), false /* fromRecents */);
|
||||
SafeActivityOptions.fromBundle(bOptions));
|
||||
}
|
||||
}
|
||||
|
||||
void moveTaskToFrontLocked(@Nullable IApplicationThread appThread,
|
||||
@Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options,
|
||||
boolean fromRecents) {
|
||||
@Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options) {
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
assertPackageMatchesCallingUid(callingPackage);
|
||||
@@ -2527,7 +2526,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
// 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 */, fromRecents);
|
||||
true /* taskSwitch */);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
|
||||
@@ -235,7 +235,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
implements WindowManagerPolicy.DisplayContentInfo {
|
||||
private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
|
||||
private static final String TAG_STACK = TAG + POSTFIX_STACK;
|
||||
private static final int NO_ROTATION = -1;
|
||||
|
||||
/** The default scaling mode that scales content automatically. */
|
||||
static final int FORCE_SCALING_MODE_AUTO = 0;
|
||||
@@ -1409,21 +1408,24 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
return mDisplayRotation.updateOrientation(orientation, forceUpdate);
|
||||
}
|
||||
|
||||
/** @return a valid rotation if the activity can use different orientation than the display. */
|
||||
/**
|
||||
* Returns a valid rotation if the activity can use different orientation than the display.
|
||||
* Otherwise {@link #ROTATION_UNDEFINED}.
|
||||
*/
|
||||
@Surface.Rotation
|
||||
private int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
|
||||
int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
|
||||
if (!mWmService.mIsFixedRotationTransformEnabled) {
|
||||
return NO_ROTATION;
|
||||
return ROTATION_UNDEFINED;
|
||||
}
|
||||
if (r.inMultiWindowMode()
|
||||
|| r.getRequestedConfigurationOrientation() == getConfiguration().orientation) {
|
||||
return NO_ROTATION;
|
||||
return ROTATION_UNDEFINED;
|
||||
}
|
||||
final int currentRotation = getRotation();
|
||||
final int rotation = mDisplayRotation.rotationForOrientation(r.getRequestedOrientation(),
|
||||
currentRotation);
|
||||
if (rotation == currentRotation) {
|
||||
return NO_ROTATION;
|
||||
return ROTATION_UNDEFINED;
|
||||
}
|
||||
return rotation;
|
||||
}
|
||||
@@ -1458,7 +1460,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
return false;
|
||||
}
|
||||
final int rotation = rotationForActivityInDifferentOrientation(r);
|
||||
if (rotation == NO_ROTATION) {
|
||||
if (rotation == ROTATION_UNDEFINED) {
|
||||
return false;
|
||||
}
|
||||
if (!r.getParent().matchParentBounds()) {
|
||||
@@ -1555,7 +1557,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
*/
|
||||
void rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord) {
|
||||
int rotation = rotationForActivityInDifferentOrientation(activityRecord);
|
||||
if (rotation != NO_ROTATION) {
|
||||
if (rotation != ROTATION_UNDEFINED) {
|
||||
startFixedRotationTransform(activityRecord, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
||||
import android.app.ActivityManager.TaskSnapshot;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.app.servertransaction.ActivityConfigurationChangeItem;
|
||||
@@ -1439,6 +1440,32 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
assertFalse(mActivity.hasFixedRotationTransform());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSnapshotCompatible() {
|
||||
mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
|
||||
final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
|
||||
.setRotation(mActivity.getWindowConfiguration().getRotation())
|
||||
.build();
|
||||
|
||||
assertTrue(mActivity.isSnapshotCompatible(snapshot));
|
||||
|
||||
setRotatedScreenOrientationSilently(mActivity);
|
||||
|
||||
assertFalse(mActivity.isSnapshotCompatible(snapshot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets orientation without notifying the parent to simulate that the display has not applied
|
||||
* the requested orientation yet.
|
||||
*/
|
||||
private static void setRotatedScreenOrientationSilently(ActivityRecord r) {
|
||||
final int rotatedOrentation = r.getConfiguration().orientation == ORIENTATION_PORTRAIT
|
||||
? SCREEN_ORIENTATION_LANDSCAPE
|
||||
: SCREEN_ORIENTATION_PORTRAIT;
|
||||
doReturn(false).when(r).onDescendantOrientationChanged(any(), any());
|
||||
r.setOrientation(rotatedOrentation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActivityOnDifferentDisplayUpdatesProcessOverride() {
|
||||
final ActivityRecord secondaryDisplayActivity =
|
||||
|
||||
@@ -307,7 +307,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
public void testCreateRemoveStartingWindow() {
|
||||
mActivity.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
|
||||
false, false);
|
||||
false);
|
||||
waitUntilHandlersIdle();
|
||||
assertHasStartingWindow(mActivity);
|
||||
mActivity.removeStartingWindow();
|
||||
@@ -322,7 +322,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
appToken.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
|
||||
false, false);
|
||||
false);
|
||||
appToken.removeStartingWindow();
|
||||
waitUntilHandlersIdle();
|
||||
assertNoStartingWindow(appToken);
|
||||
@@ -335,11 +335,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
final ActivityRecord activity2 = createIsolatedTestActivityRecord();
|
||||
activity1.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
|
||||
false, false);
|
||||
false);
|
||||
waitUntilHandlersIdle();
|
||||
activity2.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1.appToken.asBinder(),
|
||||
true, true, false, true, false, false);
|
||||
true, true, false, true, false);
|
||||
waitUntilHandlersIdle();
|
||||
assertNoStartingWindow(activity1);
|
||||
assertHasStartingWindow(activity2);
|
||||
@@ -355,11 +355,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
activity2.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0,
|
||||
activity1.appToken.asBinder(), true, true, false,
|
||||
true, false, false);
|
||||
true, false);
|
||||
});
|
||||
activity1.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
|
||||
false, false);
|
||||
false);
|
||||
waitUntilHandlersIdle();
|
||||
assertNoStartingWindow(activity1);
|
||||
assertHasStartingWindow(activity2);
|
||||
@@ -371,11 +371,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
final ActivityRecord activity2 = createIsolatedTestActivityRecord();
|
||||
activity1.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
|
||||
false, false);
|
||||
false);
|
||||
waitUntilHandlersIdle();
|
||||
activity2.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1.appToken.asBinder(),
|
||||
true, true, false, true, false, false);
|
||||
true, true, false, true, false);
|
||||
waitUntilHandlersIdle();
|
||||
assertNoStartingWindow(activity1);
|
||||
assertHasStartingWindow(activity2);
|
||||
@@ -413,7 +413,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
// Add a starting window.
|
||||
activityTop.addStartingWindow(mPackageName,
|
||||
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
|
||||
false, false);
|
||||
false);
|
||||
waitUntilHandlersIdle();
|
||||
|
||||
// Make the top one invisible, and try transferring the starting window from the top to the
|
||||
|
||||
Reference in New Issue
Block a user