From 6bb2b9c716d5395318c6964b936b5c3ff3c1c503 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Mon, 14 Sep 2020 22:39:16 +0800 Subject: Make process level rotated config and display metrics consistent The application may get Resources instance from Resources.getSystem() and context.getApplicationContext().getResources(). Since fixed rotation is introduced that allows an activity to start in a different rotation than the current display, when using getConfiguration() and getDisplayMetrics() of these Resources instances, the orientation and metrics need to be the same as current display is rotated. Otherwise the app may show unexpected UI layout. Although it is not recommended to use global resources/config for activity. One of the goal of fixed rotation transform is to simulate the app is started in a rotated environment, so this CL makes the configuration and display metrics of system resources are consistent with application and activity for compatibility. About WindowProcessController and ActivityStackSupervisor: The process configuration passed to LaunchActivityItem may be associated from activity. if the sequence number of configuration is overridden by activity, the configuration may be ignored when launching the activity because the sequence number isn't larger than the previous process configuration. Although there will be a ConfigurationChangeItem later to update correct state, the app may get the intermediate state with old configuration and metrics. About ResourcesManager and DisplayAdjustments: There are 2 new fields appWidth and appHeight added to DisplayAdjustments#FixedRotationAdjustments because the display metrics from Resources.getSystem() is independent from activity configuration. Only window manager knows the rotated size, so the values need to send to client and then ResourcesManager takes the adjustment to change the global display metrics. About WindowToken: When fixed rotation is applied on the token, send the FixedRotationAdjustmentsItem first so the later configuration change can pick the adjustment at ActivityThread. And because the registration of activity configuration only occurs on add/remove activity, if it is only switching to another existing activity in different orientation, the process configuration still needs to be updated. About ActivityThread: The code flow for a rotated activity (DA = display adjustments): - Launch new activity handleLaunchActivity: override app DA handleConfigurationChanged: adjust global display metrics by DA performLaunchActivity createBaseContextForActivity: override activity DA - Resume existing activity handleFixedRotationAdjustments: override app and activity DA handleConfigurationChanged: adjust global display metrics by DA handleResumeActivity Also some minor corrections: - Fix wrong display metrics adjustment that xdpi and ydpi should not be swapped because they are physical attributes. Bug: 167564038 Test: atest DisplayAdjustmentsTests AppConfigurationTests#testRotatedInfoWithFixedRotationTransform WindowProcessControllerTests#testProcessLevelConfiguration DisplayContentTests#testApplyTopFixedRotationTransform Change-Id: I60bedc7e09f54683d5e857ccc51402d5d144cd9e Merged-In: I60bedc7e09f54683d5e857ccc51402d5d144cd9e --- core/java/android/app/ActivityThread.java | 99 +++++++++++----------- core/java/android/app/ResourcesManager.java | 15 +++- core/java/android/view/DisplayAdjustments.java | 40 +++++++-- .../servertransaction/TransactionParcelTests.java | 5 +- .../src/android/view/DisplayAdjustmentsTests.java | 18 +++- .../android/server/wm/ActivityStackSupervisor.java | 15 +++- .../android/server/wm/WindowProcessController.java | 80 +++++++++++------ .../java/com/android/server/wm/WindowToken.java | 52 +++++++----- .../com/android/server/wm/DisplayContentTests.java | 12 ++- .../server/wm/WindowProcessControllerTests.java | 9 ++ 10 files changed, 231 insertions(+), 114 deletions(-) diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 8d64661ef8a6..b47d44d60790 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3250,12 +3250,6 @@ public final class ActivityThread extends ClientTransactionHandler { sendMessage(H.CLEAN_UP_CONTEXT, cci); } - @Override - public void handleFixedRotationAdjustments(@NonNull IBinder token, - @Nullable FixedRotationAdjustments fixedRotationAdjustments) { - handleFixedRotationAdjustments(token, fixedRotationAdjustments, null /* overrideConfig */); - } - /** * Applies the rotation adjustments to override display information in resources belong to the * provided token. If the token is activity token, the adjustments also apply to application @@ -3265,51 +3259,39 @@ public final class ActivityThread extends ClientTransactionHandler { * @param fixedRotationAdjustments The information to override the display adjustments of * corresponding resources. If it is null, the exiting override * will be cleared. - * @param overrideConfig The override configuration of activity. It is used to override - * application configuration. If it is non-null, it means the token is - * confirmed as activity token. Especially when launching new activity, - * {@link #mActivities} hasn't put the new token. */ - private void handleFixedRotationAdjustments(@NonNull IBinder token, - @Nullable FixedRotationAdjustments fixedRotationAdjustments, - @Nullable Configuration overrideConfig) { - // The element of application configuration override is set only if the application - // adjustments are needed, because activity already has its own override configuration. - final Configuration[] appConfigOverride; - final Consumer override; - if (fixedRotationAdjustments != null) { - appConfigOverride = new Configuration[1]; - override = displayAdjustments -> { - displayAdjustments.setFixedRotationAdjustments(fixedRotationAdjustments); - if (appConfigOverride[0] != null) { - displayAdjustments.getConfiguration().updateFrom(appConfigOverride[0]); - } - }; - } else { - appConfigOverride = null; - override = null; - } + @Override + public void handleFixedRotationAdjustments(@NonNull IBinder token, + @Nullable FixedRotationAdjustments fixedRotationAdjustments) { + final Consumer override = fixedRotationAdjustments != null + ? displayAdjustments -> displayAdjustments + .setFixedRotationAdjustments(fixedRotationAdjustments) + : null; if (!mResourcesManager.overrideTokenDisplayAdjustments(token, override)) { // No resources are associated with the token. return; } - if (overrideConfig == null) { - final ActivityClientRecord r = mActivities.get(token); - if (r == null) { - // It is not an activity token. Nothing to do for application. - return; - } - overrideConfig = r.overrideConfig; - } - if (appConfigOverride != null) { - appConfigOverride[0] = overrideConfig; + if (mActivities.get(token) == null) { + // Nothing to do for application if it is not an activity token. + return; } - // Apply the last override to application resources for compatibility. Because the Resources - // of Display can be from application, e.g. - // applicationContext.getSystemService(DisplayManager.class).getDisplay(displayId) - // and the deprecated usage: - // applicationContext.getSystemService(WindowManager.class).getDefaultDisplay(); + overrideApplicationDisplayAdjustments(token, override); + } + + /** + * Applies the last override to application resources for compatibility. Because the Resources + * of Display can be from application, e.g. + * applicationContext.getSystemService(DisplayManager.class).getDisplay(displayId) + * and the deprecated usage: + * applicationContext.getSystemService(WindowManager.class).getDefaultDisplay(); + * + * @param token The owner and target of the override. + * @param override The display adjustments override for application resources. If it is null, + * the override of the token will be removed and pop the last one to use. + */ + private void overrideApplicationDisplayAdjustments(@NonNull IBinder token, + @Nullable Consumer override) { final Consumer appOverride; if (mActiveRotationAdjustments == null) { mActiveRotationAdjustments = new ArrayList<>(2); @@ -3542,8 +3524,13 @@ public final class ActivityThread extends ClientTransactionHandler { // The rotation adjustments must be applied before creating the activity, so the activity // can get the adjusted display info during creation. if (r.mPendingFixedRotationAdjustments != null) { - handleFixedRotationAdjustments(r.token, r.mPendingFixedRotationAdjustments, - r.overrideConfig); + // The adjustments should have been set by handleLaunchActivity, so the last one is the + // override for activity resources. + if (mActiveRotationAdjustments != null && !mActiveRotationAdjustments.isEmpty()) { + mResourcesManager.overrideTokenDisplayAdjustments(r.token, + mActiveRotationAdjustments.get( + mActiveRotationAdjustments.size() - 1).second); + } r.mPendingFixedRotationAdjustments = null; } @@ -3582,6 +3569,13 @@ public final class ActivityThread extends ClientTransactionHandler { mProfiler.startProfiling(); } + if (r.mPendingFixedRotationAdjustments != null) { + // The rotation adjustments must be applied before handling configuration, so process + // level display metrics can be adjusted. + overrideApplicationDisplayAdjustments(r.token, adjustments -> + adjustments.setFixedRotationAdjustments(r.mPendingFixedRotationAdjustments)); + } + // Make sure we are running with the most recent config. handleConfigurationChanged(null, null); @@ -5777,7 +5771,15 @@ public final class ActivityThread extends ClientTransactionHandler { if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: " + config); - mResourcesManager.applyConfigurationToResourcesLocked(config, compat); + final Resources appResources = mInitialApplication.getResources(); + if (appResources.hasOverrideDisplayAdjustments()) { + // The value of Display#getRealSize will be adjusted by FixedRotationAdjustments, + // but Display#getSize refers to DisplayAdjustments#mConfiguration. So the rotated + // configuration also needs to set to the adjustments for consistency. + appResources.getDisplayAdjustments().getConfiguration().updateFrom(config); + } + mResourcesManager.applyConfigurationToResourcesLocked(config, compat, + appResources.getDisplayAdjustments()); updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(), mResourcesManager.getConfiguration().getLocales()); @@ -7390,7 +7392,8 @@ public final class ActivityThread extends ClientTransactionHandler { // We need to apply this change to the resources immediately, because upon returning // the view hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig, - null /* compat */)) { + null /* compat */, + mInitialApplication.getResources().getDisplayAdjustments())) { updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(), mResourcesManager.getConfiguration().getLocales()); diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 4cba6ea74955..62475060dc20 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -1047,12 +1047,18 @@ public class ResourcesManager { public final boolean applyConfigurationToResources(@NonNull Configuration config, @Nullable CompatibilityInfo compat) { synchronized(this) { - return applyConfigurationToResourcesLocked(config, compat); + return applyConfigurationToResourcesLocked(config, compat, null /* adjustments */); } } public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config, - @Nullable CompatibilityInfo compat) { + @Nullable CompatibilityInfo compat) { + return applyConfigurationToResourcesLocked(config, compat, null /* adjustments */); + } + + /** Applies the global configuration to the managed resources. */ + public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config, + @Nullable CompatibilityInfo compat, @Nullable DisplayAdjustments adjustments) { try { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#applyConfigurationToResourcesLocked"); @@ -1076,6 +1082,11 @@ public class ResourcesManager { | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; } + if (adjustments != null) { + // Currently the only case where the adjustment takes effect is to simulate placing + // an app in a rotated display. + adjustments.adjustGlobalAppMetrics(defaultDisplayMetrics); + } Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat); ApplicationPackageManager.configurationChanged(); diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java index c726bee9f402..7c01f7a8739a 100644 --- a/core/java/android/view/DisplayAdjustments.java +++ b/core/java/android/view/DisplayAdjustments.java @@ -130,14 +130,16 @@ public class DisplayAdjustments { w = metrics.noncompatWidthPixels; metrics.noncompatWidthPixels = metrics.noncompatHeightPixels; metrics.noncompatHeightPixels = w; + } - float x = metrics.xdpi; - metrics.xdpi = metrics.ydpi; - metrics.ydpi = x; - - x = metrics.noncompatXdpi; - metrics.noncompatXdpi = metrics.noncompatYdpi; - metrics.noncompatYdpi = x; + /** Adjusts global display metrics that is available to applications. */ + public void adjustGlobalAppMetrics(@NonNull DisplayMetrics metrics) { + final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments; + if (rotationAdjustments == null) { + return; + } + metrics.noncompatWidthPixels = metrics.widthPixels = rotationAdjustments.mAppWidth; + metrics.noncompatHeightPixels = metrics.heightPixels = rotationAdjustments.mAppHeight; } /** Returns the adjusted cutout if available. Otherwise the original cutout is returned. */ @@ -178,7 +180,7 @@ public class DisplayAdjustments { /** * An application can be launched in different rotation than the real display. This class - * provides the information to adjust the values returned by {@link #Display}. + * provides the information to adjust the values returned by {@link Display}. * @hide */ public static class FixedRotationAdjustments implements Parcelable { @@ -186,12 +188,24 @@ public class DisplayAdjustments { @Surface.Rotation final int mRotation; + /** + * The rotated {@link DisplayInfo#appWidth}. The value cannot be simply swapped according + * to rotation because it minus the region of screen decorations. + */ + final int mAppWidth; + + /** The rotated {@link DisplayInfo#appHeight}. */ + final int mAppHeight; + /** Non-null if the device has cutout. */ @Nullable final DisplayCutout mRotatedDisplayCutout; - public FixedRotationAdjustments(@Surface.Rotation int rotation, DisplayCutout cutout) { + public FixedRotationAdjustments(@Surface.Rotation int rotation, int appWidth, int appHeight, + DisplayCutout cutout) { mRotation = rotation; + mAppWidth = appWidth; + mAppHeight = appHeight; mRotatedDisplayCutout = cutout; } @@ -199,6 +213,8 @@ public class DisplayAdjustments { public int hashCode() { int hash = 17; hash = hash * 31 + mRotation; + hash = hash * 31 + mAppWidth; + hash = hash * 31 + mAppHeight; hash = hash * 31 + Objects.hashCode(mRotatedDisplayCutout); return hash; } @@ -210,12 +226,14 @@ public class DisplayAdjustments { } final FixedRotationAdjustments other = (FixedRotationAdjustments) o; return mRotation == other.mRotation + && mAppWidth == other.mAppWidth && mAppHeight == other.mAppHeight && Objects.equals(mRotatedDisplayCutout, other.mRotatedDisplayCutout); } @Override public String toString() { return "FixedRotationAdjustments{rotation=" + Surface.rotationToString(mRotation) + + " appWidth=" + mAppWidth + " appHeight=" + mAppHeight + " cutout=" + mRotatedDisplayCutout + "}"; } @@ -227,12 +245,16 @@ public class DisplayAdjustments { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mRotation); + dest.writeInt(mAppWidth); + dest.writeInt(mAppHeight); dest.writeTypedObject( new DisplayCutout.ParcelableWrapper(mRotatedDisplayCutout), flags); } private FixedRotationAdjustments(Parcel in) { mRotation = in.readInt(); + mAppWidth = in.readInt(); + mAppHeight = in.readInt(); final DisplayCutout.ParcelableWrapper cutoutWrapper = in.readTypedObject(DisplayCutout.ParcelableWrapper.CREATOR); mRotatedDisplayCutout = cutoutWrapper != null ? cutoutWrapper.get() : null; diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index f11adef81793..7d2e32ab08d3 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -191,7 +191,7 @@ public class TransactionParcelTests { PersistableBundle persistableBundle = new PersistableBundle(); persistableBundle.putInt("k", 4); FixedRotationAdjustments fixedRotationAdjustments = new FixedRotationAdjustments( - Surface.ROTATION_90, DisplayCutout.NO_CUTOUT); + Surface.ROTATION_90, 1920, 1080, DisplayCutout.NO_CUTOUT); LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo, config(), overrideConfig, compat, referrer, null /* voiceInteractor */, @@ -351,7 +351,8 @@ public class TransactionParcelTests { ClientTransaction transaction = ClientTransaction.obtain(new StubAppThread(), null /* activityToken */); transaction.addCallback(FixedRotationAdjustmentsItem.obtain(new Binder(), - new FixedRotationAdjustments(Surface.ROTATION_270, DisplayCutout.NO_CUTOUT))); + new FixedRotationAdjustments(Surface.ROTATION_270, 1920, 1080, + DisplayCutout.NO_CUTOUT))); writeAndPrepareForReading(transaction); diff --git a/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java b/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java index 2fc42e91a8cc..3cf1722d49d3 100644 --- a/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java +++ b/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java @@ -77,8 +77,10 @@ public class DisplayAdjustmentsTests { final int realRotation = Surface.ROTATION_0; final int fixedRotation = Surface.ROTATION_90; - mDisplayAdjustments.setFixedRotationAdjustments( - new FixedRotationAdjustments(fixedRotation, null /* cutout */)); + final int appWidth = 1080; + final int appHeight = 1920; + mDisplayAdjustments.setFixedRotationAdjustments(new FixedRotationAdjustments( + fixedRotation, appWidth, appHeight, null /* cutout */)); final int w = 1000; final int h = 2000; @@ -95,13 +97,21 @@ public class DisplayAdjustmentsTests { metrics.heightPixels = metrics.noncompatHeightPixels = h; final DisplayMetrics flippedMetrics = new DisplayMetrics(); - flippedMetrics.xdpi = flippedMetrics.noncompatXdpi = h; + // The physical dpi should not be adjusted. + flippedMetrics.xdpi = flippedMetrics.noncompatXdpi = w; flippedMetrics.widthPixels = flippedMetrics.noncompatWidthPixels = h; - flippedMetrics.ydpi = flippedMetrics.noncompatYdpi = w; + flippedMetrics.ydpi = flippedMetrics.noncompatYdpi = h; flippedMetrics.heightPixels = flippedMetrics.noncompatHeightPixels = w; mDisplayAdjustments.adjustMetrics(metrics, realRotation); assertEquals(flippedMetrics, metrics); + + mDisplayAdjustments.adjustGlobalAppMetrics(metrics); + + assertEquals(appWidth, metrics.widthPixels); + assertEquals(appWidth, metrics.noncompatWidthPixels); + assertEquals(appHeight, metrics.heightPixels); + assertEquals(appHeight, metrics.noncompatHeightPixels); } } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 3dd82a6221c6..7e6b7cd05762 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -732,6 +732,11 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { final ActivityStack stack = task.getStack(); beginDeferResume(); + // The LaunchActivityItem also contains process configuration, so the configuration change + // from WindowProcessController#setProcess can be deferred. The major reason is that if + // the activity has FixedRotationAdjustments, it needs to be applied with configuration. + // In general, this reduces a binder transaction if process configuration is changed. + proc.pauseConfigurationDispatch(); try { r.startFreezingScreenLocked(proc, 0); @@ -826,9 +831,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // Because we could be starting an Activity in the system process this may not go // across a Binder interface which would create a new Configuration. Consequently // we have to always create a new Configuration here. - + final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity(); final MergedConfiguration mergedConfiguration = new MergedConfiguration( - proc.getConfiguration(), r.getMergedOverrideConfiguration()); + procConfig, r.getMergedOverrideConfiguration()); r.setLastReportedConfiguration(mergedConfiguration); logIfTransactionTooLarge(r.intent, r.getSavedState()); @@ -862,6 +867,11 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); + if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) { + // If the seq is increased, there should be something changed (e.g. registered + // activity configuration). + proc.setLastReportedConfiguration(procConfig); + } if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 && mService.mHasHeavyWeightFeature) { // This may be a heavy-weight process! Note that the package manager will ensure @@ -896,6 +906,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } finally { endDeferResume(); + proc.resumeConfigurationDispatch(); } r.launchFailed = false; diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index bd959aba5bb1..df49ac71334f 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -186,13 +186,16 @@ public class WindowProcessController extends ConfigurationContainer 0) { + mHasPendingConfigurationChange = true; + return; + } + mHasPendingConfigurationChange = false; if (mThread == null) { if (Build.IS_DEBUGGABLE && mHasImeService) { // TODO (b/135719017): Temporary log for debugging IME service. @@ -1242,7 +1248,7 @@ public class WindowProcessController extends ConfigurationContainer { } } } + + /** The state may not only be used by self. Make sure to leave the influence by others. */ + void disassociate(WindowToken token) { + mAssociatedTokens.remove(token); + mRotatedContainers.remove(token); + } } private class DeathRecipient implements IBinder.DeathRecipient { @@ -531,7 +537,7 @@ class WindowToken extends WindowContainer { void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames, Configuration config) { if (mFixedRotationTransformState != null) { - cleanUpFixedRotationTransformState(true /* replacing */); + mFixedRotationTransformState.disassociate(this); } mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames, new Configuration(config), mDisplayContent.getRotation()); @@ -539,8 +545,7 @@ class WindowToken extends WindowContainer { mDisplayContent.getDisplayPolicy().simulateLayoutDisplay(displayFrames, mFixedRotationTransformState.mInsetsState, mFixedRotationTransformState.mBarContentFrames); - onConfigurationChanged(getParent().getConfiguration()); - notifyFixedRotationTransform(true /* enabled */); + onFixedRotationStatePrepared(); } /** @@ -553,12 +558,29 @@ class WindowToken extends WindowContainer { return; } if (mFixedRotationTransformState != null) { - cleanUpFixedRotationTransformState(true /* replacing */); + mFixedRotationTransformState.disassociate(this); } mFixedRotationTransformState = fixedRotationState; fixedRotationState.mAssociatedTokens.add(this); - onConfigurationChanged(getParent().getConfiguration()); + onFixedRotationStatePrepared(); + } + + /** + * Makes the rotated states take effect for this window container and its client process. + * This should only be called when {@link #mFixedRotationTransformState} is non-null. + */ + private void onFixedRotationStatePrepared() { + // Send the adjustment info first so when the client receives configuration change, it can + // get the rotated display metrics. notifyFixedRotationTransform(true /* enabled */); + // Resolve the rotated configuration. + onConfigurationChanged(getParent().getConfiguration()); + final ActivityRecord r = asActivityRecord(); + if (r != null && r.hasProcess()) { + // The application needs to be configured as in a rotated environment for compatibility. + // This registration will send the rotated configuration to its process. + r.app.registerActivityConfigurationListener(r); + } } /** @@ -609,21 +631,12 @@ class WindowToken extends WindowContainer { // The state is cleared at the end, because it is used to indicate that other windows can // use seamless rotation when applying rotation to display. for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) { - state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState( - false /* replacing */); + final WindowToken token = state.mAssociatedTokens.get(i); + token.mFixedRotationTransformState = null; + token.notifyFixedRotationTransform(false /* enabled */); } } - private void cleanUpFixedRotationTransformState(boolean replacing) { - if (replacing && mFixedRotationTransformState.mAssociatedTokens.size() > 1) { - // The state is not only used by self. Make sure to leave the influence by others. - mFixedRotationTransformState.mAssociatedTokens.remove(this); - mFixedRotationTransformState.mRotatedContainers.remove(this); - } - mFixedRotationTransformState = null; - notifyFixedRotationTransform(false /* enabled */); - } - /** Notifies application side to enable or disable the rotation adjustment of display info. */ private void notifyFixedRotationTransform(boolean enabled) { FixedRotationAdjustments adjustments = null; @@ -687,8 +700,9 @@ class WindowToken extends WindowContainer { if (!isFixedRotationTransforming()) { return null; } - return new FixedRotationAdjustments(mFixedRotationTransformState.mDisplayInfo.rotation, - mFixedRotationTransformState.mDisplayInfo.displayCutout); + final DisplayInfo displayInfo = mFixedRotationTransformState.mDisplayInfo; + return new FixedRotationAdjustments(displayInfo.rotation, displayInfo.appWidth, + displayInfo.appHeight, displayInfo.displayCutout); } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index dc838f1bb288..e23f34ade355 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1147,8 +1147,10 @@ public class DisplayContentTests extends WindowTestsBase { verify(t, never()).setPosition(any(), eq(0), eq(0)); // Launch another activity before the transition is finished. - final ActivityRecord app2 = new ActivityTestsBase.StackBuilder(mWm.mRoot) - .setDisplay(mDisplayContent).build().getTopMostActivity(); + final ActivityStack stack2 = new ActivityTestsBase.StackBuilder(mWm.mRoot) + .setDisplay(mDisplayContent).build(); + final ActivityRecord app2 = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService) + .setStack(stack2).setUseProcess(app.app).build(); app2.setVisible(false); mDisplayContent.mOpeningApps.add(app2); app2.setRequestedOrientation(newOrientation); @@ -1158,6 +1160,12 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(app.hasFixedRotationTransform(app2)); assertTrue(mDisplayContent.isFixedRotationLaunchingApp(app2)); + final Configuration expectedProcConfig = new Configuration(app2.app.getConfiguration()); + expectedProcConfig.windowConfiguration.setActivityType( + WindowConfiguration.ACTIVITY_TYPE_UNDEFINED); + assertEquals("The process should receive rotated configuration for compatibility", + expectedProcConfig, app2.app.getConfiguration()); + // The fixed rotation transform can only be finished when all animation finished. doReturn(false).when(app2).isAnimating(anyInt(), anyInt()); mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app2.token); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java index 24950ce6a882..a46e6d35ee97 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java @@ -266,6 +266,15 @@ public class WindowProcessControllerTests extends ActivityTestsBase { mWpc.onMergedOverrideConfigurationChanged(config); assertEquals(ACTIVITY_TYPE_HOME, config.windowConfiguration.getActivityType()); assertEquals(ACTIVITY_TYPE_UNDEFINED, mWpc.getActivityType()); + + final int globalSeq = 100; + mRootWindowContainer.getConfiguration().seq = globalSeq; + invertOrientation(mWpc.getConfiguration()); + new ActivityBuilder(mService).setCreateTask(true).setUseProcess(mWpc).build(); + + assertTrue(mWpc.registeredForActivityConfigChanges()); + assertEquals("Config seq of process should not be affected by activity", + mWpc.getConfiguration().seq, globalSeq); } private TestDisplayContent createTestDisplayContentInContainer() { -- cgit v1.2.3-59-g8ed1b