diff options
| author | 2023-08-21 18:55:20 +0800 | |
|---|---|---|
| committer | 2023-08-25 11:41:35 +0800 | |
| commit | 579d9cd8727e67a2083ab99a8f5034d740a58b79 (patch) | |
| tree | 148b6f615cc02e25e85efa45e9db23b3bb273555 | |
| parent | 8de14cacfba137ea426e0b48cba10f9eb2af54c7 (diff) | |
Synchronize window config updates (1/n)
When updating Configuration on the client side, check if this should
trigger onDisplayChanged.
Bug: 260873529
Test: atest WmTests:WindowConfigurationTests
Test: atest FrameworksCoreTests:WindowContextInfoChangeItemTest
Change-Id: I8baa0f43d6bd00a93910fed4aec2d53f2044e0c7
16 files changed, 366 insertions, 17 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 773d720d73fb..6210715440fb 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -496,15 +496,15 @@ package android.app { method public int compareTo(android.app.WindowConfiguration); method public int describeContents(); method public int getActivityType(); - method public android.graphics.Rect getAppBounds(); - method public android.graphics.Rect getBounds(); + method @Nullable public android.graphics.Rect getAppBounds(); + method @NonNull public android.graphics.Rect getBounds(); method @NonNull public android.graphics.Rect getMaxBounds(); method public int getRotation(); method public int getWindowingMode(); method public static boolean isFloating(int); method public void setActivityType(int); - method public void setAppBounds(android.graphics.Rect); - method public void setBounds(android.graphics.Rect); + method public void setAppBounds(@Nullable android.graphics.Rect); + method public void setBounds(@Nullable android.graphics.Rect); method public void setMaxBounds(@Nullable android.graphics.Rect); method public void setRotation(int); method public void setTo(android.app.WindowConfiguration); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index cc716ecfdafa..3dd69e46a7d9 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3580,6 +3580,12 @@ public final class ActivityThread extends ClientTransactionHandler return mActivities.get(token); } + @Nullable + @Override + public Context getWindowContext(@NonNull IBinder clientToken) { + return WindowTokenClientController.getInstance().getWindowContext(clientToken); + } + @VisibleForTesting(visibility = PACKAGE) public Configuration getConfiguration() { return mConfigurationController.getConfiguration(); diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java index 6753cb884ea7..98020ff2d173 100644 --- a/core/java/android/app/ClientTransactionHandler.java +++ b/core/java/android/app/ClientTransactionHandler.java @@ -16,11 +16,13 @@ package android.app; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityThread.ActivityClientRecord; import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.ClientTransactionItem; import android.app.servertransaction.PendingTransactionActions; import android.app.servertransaction.TransactionExecutor; +import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; @@ -28,6 +30,7 @@ import android.os.IBinder; import android.util.MergedConfiguration; import android.view.SurfaceControl; import android.window.SplashScreenView.SplashScreenViewParcelable; +import android.window.WindowContext; import android.window.WindowContextInfo; import com.android.internal.annotations.VisibleForTesting; @@ -85,6 +88,10 @@ public abstract class ClientTransactionHandler { /** Get activity instance for the token. */ public abstract Activity getActivity(IBinder token); + /** Gets the {@link WindowContext} instance for the token. */ + @Nullable + public abstract Context getWindowContext(@NonNull IBinder clientToken); + // Prepare phase related logic and handlers. Methods that inform about about pending changes or // do other internal bookkeeping. diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java index 5b955031a098..e3055e5042c6 100644 --- a/core/java/android/app/WindowConfiguration.java +++ b/core/java/android/app/WindowConfiguration.java @@ -36,6 +36,7 @@ import android.os.Parcelable; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; import android.util.proto.WireTypeMismatchException; +import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; import android.view.WindowManager; @@ -66,6 +67,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu * the display level. Lower levels can override these values to provide custom bounds to enforce * features such as a max aspect ratio. */ + @Nullable private Rect mAppBounds; /** @@ -269,7 +271,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu * Sets the bounds to the provided {@link Rect}. * @param rect the new bounds value. */ - public void setBounds(Rect rect) { + public void setBounds(@Nullable Rect rect) { if (rect == null) { mBounds.setEmpty(); return; @@ -283,7 +285,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu * @param rect The rect value to set {@link #mAppBounds} to. * @see #getAppBounds() */ - public void setAppBounds(Rect rect) { + public void setAppBounds(@Nullable Rect rect) { if (rect == null) { mAppBounds = null; return; @@ -356,11 +358,13 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu } /** @see #setAppBounds(Rect) */ + @Nullable public Rect getAppBounds() { return mAppBounds; } /** @see #setBounds(Rect) */ + @NonNull public Rect getBounds() { return mBounds; } @@ -905,6 +909,23 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu return activityType != ACTIVITY_TYPE_ASSISTANT && activityType != ACTIVITY_TYPE_DREAM; } + /** + * Checks if the two {@link Configuration}s are equal to each other for the fields that are read + * by {@link Display}. + * @hide + */ + public static boolean areConfigurationsEqualForDisplay(@NonNull Configuration newConfig, + @NonNull Configuration oldConfig) { + // Only report different if max bounds and display rotation is changed, so that it will not + // report on Task resizing. + if (!newConfig.windowConfiguration.getMaxBounds().equals( + oldConfig.windowConfiguration.getMaxBounds())) { + return false; + } + return newConfig.windowConfiguration.getDisplayRotation() + == oldConfig.windowConfiguration.getDisplayRotation(); + } + /** @hide */ public static String windowingModeToString(@WindowingMode int windowingMode) { switch (windowingMode) { diff --git a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java index 1c490be08381..e40925441f0f 100644 --- a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java +++ b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; +import android.content.Context; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.os.IBinder; @@ -40,7 +41,7 @@ public class ActivityConfigurationChangeItem extends ActivityTransactionItem { private Configuration mConfiguration; @Override - public void preExecute(android.app.ClientTransactionHandler client, IBinder token) { + public void preExecute(@NonNull ClientTransactionHandler client, @Nullable IBinder token) { CompatibilityInfo.applyOverrideScaleIfNeeded(mConfiguration); // Notify the client of an upcoming change in the token configuration. This ensures that // batches of config change items only process the newest configuration. @@ -48,14 +49,21 @@ public class ActivityConfigurationChangeItem extends ActivityTransactionItem { } @Override - public void execute(ClientTransactionHandler client, ActivityClientRecord r, - PendingTransactionActions pendingActions) { + public void execute(@NonNull ClientTransactionHandler client, @Nullable ActivityClientRecord r, + @NonNull PendingTransactionActions pendingActions) { // TODO(lifecycler): detect if PIP or multi-window mode changed and report it here. Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged"); client.handleActivityConfigurationChanged(r, mConfiguration, INVALID_DISPLAY); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } + @Nullable + @Override + public Context getContextToUpdate(@NonNull ClientTransactionHandler client, + @Nullable IBinder token) { + // TODO(b/260873529): Update ClientTransaction to bundle multiple activity config updates. + return client.getActivity(token); + } // ObjectPoolItem implementation diff --git a/core/java/android/app/servertransaction/ClientTransactionItem.java b/core/java/android/app/servertransaction/ClientTransactionItem.java index b159f336cd85..fe75d89e1257 100644 --- a/core/java/android/app/servertransaction/ClientTransactionItem.java +++ b/core/java/android/app/servertransaction/ClientTransactionItem.java @@ -19,6 +19,11 @@ package android.app.servertransaction; import static android.app.servertransaction.ActivityLifecycleItem.LifecycleState; import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ClientTransactionHandler; +import android.content.Context; +import android.os.IBinder; import android.os.Parcelable; /** @@ -42,6 +47,16 @@ public abstract class ClientTransactionItem implements BaseClientRequest, Parcel return true; } + /** + * If this {@link ClientTransactionItem} is updating configuration, returns the {@link Context} + * it is updating; otherwise, returns {@code null}. + */ + @Nullable + public Context getContextToUpdate(@NonNull ClientTransactionHandler client, + @NonNull IBinder token) { + return null; + } + // Parcelable @Override diff --git a/core/java/android/app/servertransaction/ConfigurationChangeItem.java b/core/java/android/app/servertransaction/ConfigurationChangeItem.java index a563bbc9c70d..f72e2e04deca 100644 --- a/core/java/android/app/servertransaction/ConfigurationChangeItem.java +++ b/core/java/android/app/servertransaction/ConfigurationChangeItem.java @@ -16,8 +16,11 @@ package android.app.servertransaction; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityThread; import android.app.ClientTransactionHandler; +import android.content.Context; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.os.IBinder; @@ -35,24 +38,30 @@ public class ConfigurationChangeItem extends ClientTransactionItem { private int mDeviceId; @Override - public void preExecute(android.app.ClientTransactionHandler client, IBinder token) { + public void preExecute(@NonNull ClientTransactionHandler client, @Nullable IBinder token) { CompatibilityInfo.applyOverrideScaleIfNeeded(mConfiguration); client.updatePendingConfiguration(mConfiguration); } @Override - public void execute(ClientTransactionHandler client, IBinder token, - PendingTransactionActions pendingActions) { + public void execute(@NonNull ClientTransactionHandler client, @Nullable IBinder token, + @NonNull PendingTransactionActions pendingActions) { client.handleConfigurationChanged(mConfiguration, mDeviceId); } + @Nullable + @Override + public Context getContextToUpdate(@NonNull ClientTransactionHandler client, + @Nullable IBinder token) { + return ActivityThread.currentApplication(); + } // ObjectPoolItem implementation private ConfigurationChangeItem() {} /** Obtain an instance initialized with provided params. */ - public static ConfigurationChangeItem obtain(Configuration config, int deviceId) { + public static ConfigurationChangeItem obtain(@NonNull Configuration config, int deviceId) { ConfigurationChangeItem instance = ObjectPool.obtain(ConfigurationChangeItem.class); if (instance == null) { instance = new ConfigurationChangeItem(); diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java index bfab61f3ae90..09a9ab326ef7 100644 --- a/core/java/android/app/servertransaction/TransactionExecutor.java +++ b/core/java/android/app/servertransaction/TransactionExecutor.java @@ -16,6 +16,7 @@ package android.app.servertransaction; +import static android.app.WindowConfiguration.areConfigurationsEqualForDisplay; import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE; import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY; import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE; @@ -30,10 +31,16 @@ import static android.app.servertransaction.TransactionExecutorHelper.lastCallba import static android.app.servertransaction.TransactionExecutorHelper.tId; import static android.app.servertransaction.TransactionExecutorHelper.transactionToString; +import static com.android.window.flags.Flags.syncWindowConfigUpdateFlag; + +import android.annotation.NonNull; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.content.Context; +import android.content.res.Configuration; import android.os.IBinder; +import android.os.Process; +import android.util.ArraySet; import android.util.IntArray; import android.util.Slog; @@ -51,12 +58,12 @@ public class TransactionExecutor { private static final boolean DEBUG_RESOLVER = false; private static final String TAG = "TransactionExecutor"; - private ClientTransactionHandler mTransactionHandler; - private PendingTransactionActions mPendingActions = new PendingTransactionActions(); - private TransactionExecutorHelper mHelper = new TransactionExecutorHelper(); + private final ClientTransactionHandler mTransactionHandler; + private final PendingTransactionActions mPendingActions = new PendingTransactionActions(); + private final TransactionExecutorHelper mHelper = new TransactionExecutorHelper(); /** Initialize an instance with transaction handler, that will execute all requested actions. */ - public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) { + public TransactionExecutor(@NonNull ClientTransactionHandler clientTransactionHandler) { mTransactionHandler = clientTransactionHandler; } @@ -122,6 +129,9 @@ public class TransactionExecutor { // Index of the last callback that requests some post-execution state. final int lastCallbackRequestingState = lastCallbackRequestingState(transaction); + // Keep track of display ids whose Configuration got updated with this transaction. + ArraySet<Integer> configUpdatedDisplays = null; + final int size = callbacks.size(); for (int i = 0; i < size; ++i) { final ClientTransactionItem item = callbacks.get(i); @@ -136,7 +146,29 @@ public class TransactionExecutor { } } + // Can't read flag from isolated process. + final boolean isSyncWindowConfigUpdateFlagEnabled = !Process.isIsolated() + && syncWindowConfigUpdateFlag(); + final Context configUpdatedContext = isSyncWindowConfigUpdateFlagEnabled + ? item.getContextToUpdate(mTransactionHandler, token) + : null; + final Configuration preExecutedConfig = configUpdatedContext != null + ? new Configuration(configUpdatedContext.getResources().getConfiguration()) + : null; + item.execute(mTransactionHandler, token, mPendingActions); + + if (configUpdatedContext != null) { + final Configuration postExecutedConfig = configUpdatedContext.getResources() + .getConfiguration(); + if (!areConfigurationsEqualForDisplay(postExecutedConfig, preExecutedConfig)) { + if (configUpdatedDisplays == null) { + configUpdatedDisplays = new ArraySet<>(); + } + configUpdatedDisplays.add(configUpdatedContext.getDisplayId()); + } + } + item.postExecute(mTransactionHandler, token, mPendingActions); if (r == null) { // Launch activity request will create an activity record. @@ -150,6 +182,13 @@ public class TransactionExecutor { cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction); } } + + if (configUpdatedDisplays != null) { + final int displayCount = configUpdatedDisplays.size(); + for (int i = 0; i < displayCount; i++) { + // TODO(b/260873529): trigger onDisplayChanged. + } + } } /** Transition to the final state if requested by the transaction. */ diff --git a/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java index 74721d555081..99824b000b70 100644 --- a/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java +++ b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java @@ -21,6 +21,7 @@ import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ClientTransactionHandler; +import android.content.Context; import android.content.res.Configuration; import android.os.IBinder; import android.os.Parcel; @@ -45,6 +46,13 @@ public class WindowContextInfoChangeItem extends ClientTransactionItem { client.handleWindowContextInfoChanged(mClientToken, mInfo); } + @Nullable + @Override + public Context getContextToUpdate(@NonNull ClientTransactionHandler client, + @Nullable IBinder token) { + return client.getWindowContext(mClientToken); + } + // ObjectPoolItem implementation private WindowContextInfoChangeItem() {} diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java index c1d1b2754895..f4f1b3b9b27b 100644 --- a/core/java/android/window/WindowTokenClient.java +++ b/core/java/android/window/WindowTokenClient.java @@ -22,6 +22,7 @@ import static android.window.ConfigurationHelper.shouldUpdateResources; import android.annotation.AnyThread; import android.annotation.MainThread; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityThread; import android.app.ResourcesManager; import android.content.Context; @@ -91,6 +92,15 @@ public class WindowTokenClient extends Binder { } /** + * Gets the {@link Context} that this {@link WindowTokenClient} is attached through + * {@link #attachContext(Context)}. + */ + @Nullable + public Context getContext() { + return mContextRef != null ? mContextRef.get() : null; + } + + /** * Called when {@link Configuration} updates from the server side receive. * * @param newConfig the updated {@link Configuration} diff --git a/core/java/android/window/WindowTokenClientController.java b/core/java/android/window/WindowTokenClientController.java index 10f6d5e7abaa..abf7bb15b3d8 100644 --- a/core/java/android/window/WindowTokenClientController.java +++ b/core/java/android/window/WindowTokenClientController.java @@ -82,6 +82,16 @@ public class WindowTokenClientController { private WindowTokenClientController() {} + /** Gets the {@link WindowContext} instance for the token. */ + @Nullable + public Context getWindowContext(@NonNull IBinder clientToken) { + final WindowTokenClient windowTokenClient; + synchronized (mLock) { + windowTokenClient = mWindowTokenClientMap.get(clientToken); + } + return windowTokenClient != null ? windowTokenClient.getContext() : null; + } + /** * Attaches a {@link WindowTokenClient} to a {@link com.android.server.wm.DisplayArea}. * diff --git a/core/tests/coretests/src/android/app/servertransaction/ActivityConfigurationChangeItemTest.java b/core/tests/coretests/src/android/app/servertransaction/ActivityConfigurationChangeItemTest.java new file mode 100644 index 000000000000..1560c0c2c195 --- /dev/null +++ b/core/tests/coretests/src/android/app/servertransaction/ActivityConfigurationChangeItemTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.servertransaction; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doReturn; + +import android.app.Activity; +import android.app.ClientTransactionHandler; +import android.content.Context; +import android.content.res.Configuration; +import android.os.IBinder; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for {@link ActivityConfigurationChangeItem}. + * + * Build/Install/Run: + * atest FrameworksCoreTests:ActivityConfigurationChangeItemTest + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +@Presubmit +public class ActivityConfigurationChangeItemTest { + + @Mock + private ClientTransactionHandler mHandler; + @Mock + private IBinder mToken; + @Mock + private Activity mActivity; + // Can't mock final class. + private final Configuration mConfiguration = new Configuration(); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetContextToUpdate() { + doReturn(mActivity).when(mHandler).getActivity(mToken); + + final ActivityConfigurationChangeItem item = ActivityConfigurationChangeItem + .obtain(mConfiguration); + final Context context = item.getContextToUpdate(mHandler, mToken); + + assertEquals(mActivity, context); + } +} diff --git a/core/tests/coretests/src/android/app/servertransaction/ConfigurationChangeItemTest.java b/core/tests/coretests/src/android/app/servertransaction/ConfigurationChangeItemTest.java new file mode 100644 index 000000000000..3926cfb14194 --- /dev/null +++ b/core/tests/coretests/src/android/app/servertransaction/ConfigurationChangeItemTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.servertransaction; + +import static android.content.Context.DEVICE_ID_DEFAULT; + +import static org.junit.Assert.assertEquals; + +import android.app.ActivityThread; +import android.app.ClientTransactionHandler; +import android.content.Context; +import android.content.res.Configuration; +import android.os.IBinder; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for {@link ConfigurationChangeItem}. + * + * Build/Install/Run: + * atest FrameworksCoreTests:ConfigurationChangeItemTest + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +@Presubmit +public class ConfigurationChangeItemTest { + + @Mock + private ClientTransactionHandler mHandler; + @Mock + private IBinder mToken; + // Can't mock final class. + private final Configuration mConfiguration = new Configuration(); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetContextToUpdate() { + final ConfigurationChangeItem item = ConfigurationChangeItem + .obtain(mConfiguration, DEVICE_ID_DEFAULT); + final Context context = item.getContextToUpdate(mHandler, mToken); + + assertEquals(ActivityThread.currentApplication(), context); + } +} diff --git a/core/tests/coretests/src/android/app/servertransaction/WindowContextInfoChangeItemTest.java b/core/tests/coretests/src/android/app/servertransaction/WindowContextInfoChangeItemTest.java index 37a517e87c74..db76d26b063e 100644 --- a/core/tests/coretests/src/android/app/servertransaction/WindowContextInfoChangeItemTest.java +++ b/core/tests/coretests/src/android/app/servertransaction/WindowContextInfoChangeItemTest.java @@ -18,15 +18,24 @@ package android.app.servertransaction; import static android.view.Display.DEFAULT_DISPLAY; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import android.app.ClientTransactionHandler; +import android.content.Context; import android.content.res.Configuration; import android.os.IBinder; +import android.platform.test.annotations.Presubmit; +import android.window.WindowContext; import android.window.WindowContextInfo; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -36,6 +45,9 @@ import org.mockito.MockitoAnnotations; * Build/Install/Run: * atest FrameworksCoreTests:WindowContextInfoChangeItemTest */ +@RunWith(AndroidJUnit4.class) +@SmallTest +@Presubmit public class WindowContextInfoChangeItemTest { @Mock @@ -46,6 +58,8 @@ public class WindowContextInfoChangeItemTest { private PendingTransactionActions mPendingActions; @Mock private IBinder mClientToken; + @Mock + private WindowContext mWindowContext; // Can't mock final class. private final Configuration mConfiguration = new Configuration(); @@ -63,4 +77,15 @@ public class WindowContextInfoChangeItemTest { verify(mHandler).handleWindowContextInfoChanged(mClientToken, new WindowContextInfo(mConfiguration, DEFAULT_DISPLAY)); } + + @Test + public void testGetContextToUpdate() { + doReturn(mWindowContext).when(mHandler).getWindowContext(mClientToken); + + final WindowContextInfoChangeItem item = WindowContextInfoChangeItem + .obtain(mClientToken, mConfiguration, DEFAULT_DISPLAY); + final Context context = item.getContextToUpdate(mHandler, mToken); + + assertEquals(mWindowContext, context); + } } diff --git a/core/tests/coretests/src/android/app/servertransaction/WindowContextWindowRemovalItemTest.java b/core/tests/coretests/src/android/app/servertransaction/WindowContextWindowRemovalItemTest.java index 2c83c70e9ae2..17e0ebc1edbc 100644 --- a/core/tests/coretests/src/android/app/servertransaction/WindowContextWindowRemovalItemTest.java +++ b/core/tests/coretests/src/android/app/servertransaction/WindowContextWindowRemovalItemTest.java @@ -20,9 +20,14 @@ import static org.mockito.Mockito.verify; import android.app.ClientTransactionHandler; import android.os.IBinder; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -32,6 +37,9 @@ import org.mockito.MockitoAnnotations; * Build/Install/Run: * atest FrameworksCoreTests:WindowContextWindowRemovalItemTest */ +@RunWith(AndroidJUnit4.class) +@SmallTest +@Presubmit public class WindowContextWindowRemovalItemTest { @Mock diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java index 45cd6a200d01..38aac7cfee22 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java @@ -30,6 +30,7 @@ import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS; import static android.app.WindowConfiguration.WINDOW_CONFIG_MAX_BOUNDS; import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION; import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE; +import static android.app.WindowConfiguration.areConfigurationsEqualForDisplay; import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; import static android.view.Surface.ROTATION_270; @@ -269,4 +270,43 @@ public class WindowConfigurationTests extends WindowTestsBase { config.setTo(other, justWindowingMode); assertEquals(WINDOWING_MODE_UNDEFINED, config.getWindowingMode()); } + + @Test + public void testAreConfigurationsEqualForDisplay() { + final Configuration config0 = new Configuration(); + final Configuration config1 = new Configuration(); + + assertTrue(areConfigurationsEqualForDisplay(config0, config1)); + + // Only compare fields read in Display. + config0.densityDpi = 1; + config1.densityDpi = 2; + + assertTrue(areConfigurationsEqualForDisplay(config0, config1)); + + // MaxBounds + final Rect bounds0 = new Rect(0, 0, 500, 1000); + final Rect bounds1 = new Rect(0, 0, 1000, 500); + + config0.windowConfiguration.setMaxBounds(bounds0); + config1.windowConfiguration.setMaxBounds(bounds1); + + assertFalse(areConfigurationsEqualForDisplay(config0, config1)); + + config0.windowConfiguration.setMaxBounds(null); + config1.windowConfiguration.setMaxBounds(null); + + assertTrue(areConfigurationsEqualForDisplay(config0, config1)); + + // DisplayRotation + config0.windowConfiguration.setDisplayRotation(0); + config1.windowConfiguration.setDisplayRotation(1); + + assertFalse(areConfigurationsEqualForDisplay(config0, config1)); + + config0.windowConfiguration.setDisplayRotation(2); + config1.windowConfiguration.setDisplayRotation(2); + + assertTrue(areConfigurationsEqualForDisplay(config0, config1)); + } } |