diff options
| author | 2025-01-10 23:06:21 -0800 | |
|---|---|---|
| committer | 2025-01-10 23:06:21 -0800 | |
| commit | ecae5d80bcb219251bbe84bb7baa6a9fe52171b2 (patch) | |
| tree | b531a8c0648c1ca49a9d6ae0b5ba540bccbda5c6 | |
| parent | e2be8cf7eac354b5582a832b4416df47d9be9e60 (diff) | |
| parent | 32e1982d50517dd4a4305c22fa87f7fd5e9c5579 (diff) | |
Merge "Extract WindowManagerService test support logic." into main
4 files changed, 204 insertions, 62 deletions
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e4ef3d186bdb..dd6e15b74a58 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -331,6 +331,7 @@ import android.window.WindowContextInfo; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.internal.os.IResultReceiver; import com.android.internal.os.TransferPipe; import com.android.internal.policy.IKeyguardDismissCallback; @@ -600,6 +601,7 @@ public class WindowManagerService extends IWindowManager.Stub final boolean mLimitedAlphaCompositing; final int mMaxUiWidth; + @NonNull @VisibleForTesting WindowManagerPolicy mPolicy; @@ -1054,13 +1056,16 @@ public class WindowManagerService extends IWindowManager.Stub private boolean mAnimationsDisabled = false; boolean mPointerLocationEnabled = false; + @NonNull final AppCompatConfiguration mAppCompatConfiguration; private boolean mIsIgnoreOrientationRequestDisabled; + @NonNull final InputManagerService mInputManager; final DisplayManagerInternal mDisplayManagerInternal; final DisplayManager mDisplayManager; + @NonNull final ActivityTaskManagerService mAtmService; /** Indicates whether this device supports wide color gamut / HDR rendering */ @@ -1116,7 +1121,9 @@ public class WindowManagerService extends IWindowManager.Stub static WindowManagerThreadPriorityBooster sThreadPriorityBooster = new WindowManagerThreadPriorityBooster(); + @NonNull Supplier<SurfaceControl.Builder> mSurfaceControlFactory; + @NonNull Supplier<SurfaceControl.Transaction> mTransactionFactory; private final SurfaceControl.Transaction mTransaction; @@ -1188,9 +1195,11 @@ public class WindowManagerService extends IWindowManager.Stub private volatile boolean mDisableSecureWindows = false; - public static WindowManagerService main(final Context context, final InputManagerService im, - final boolean showBootMsgs, WindowManagerPolicy policy, - ActivityTaskManagerService atm) { + /** Creates an instance of the WindowManagerService for the system server. */ + public static WindowManagerService main(@NonNull final Context context, + @NonNull final InputManagerService im, final boolean showBootMsgs, + @NonNull final WindowManagerPolicy policy, + @NonNull final ActivityTaskManagerService atm) { // Using SysUI context to have access to Material colors extracted from Wallpaper. final AppCompatConfiguration appCompat = new AppCompatConfiguration( ActivityThread.currentActivityThread().getSystemUiContext()); @@ -1204,15 +1213,19 @@ public class WindowManagerService extends IWindowManager.Stub /** * Creates and returns an instance of the WindowManagerService. This call allows the caller - * to override factories that can be used to stub native calls during test. + * to override factories that can be used to stub native calls during test. Tests should use + * {@link WindowManagerServiceTestSupport} instead of calling this directly to ensure + * proper initialization and cleanup of dependencies. */ - @VisibleForTesting - public static WindowManagerService main(final Context context, final InputManagerService im, - final boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm, - DisplayWindowSettingsProvider displayWindowSettingsProvider, - Supplier<SurfaceControl.Transaction> transactionFactory, - Supplier<SurfaceControl.Builder> surfaceControlFactory, - AppCompatConfiguration appCompat) { + @VisibleForTesting(visibility = Visibility.PRIVATE) + static WindowManagerService main(@NonNull final Context context, + @NonNull final InputManagerService im, boolean showBootMsgs, + @NonNull final WindowManagerPolicy policy, + @NonNull final ActivityTaskManagerService atm, + @NonNull final DisplayWindowSettingsProvider displayWindowSettingsProvider, + @NonNull final Supplier<SurfaceControl.Transaction> transactionFactory, + @NonNull final Supplier<SurfaceControl.Builder> surfaceControlFactory, + @NonNull final AppCompatConfiguration appCompat) { final WindowManagerService[] wms = new WindowManagerService[1]; DisplayThread.getHandler().runWithScissors(() -> @@ -1238,12 +1251,13 @@ public class WindowManagerService extends IWindowManager.Stub new WindowManagerShellCommand(this).exec(this, in, out, err, args, callback, result); } - private WindowManagerService(Context context, InputManagerService inputManager, - boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm, - DisplayWindowSettingsProvider displayWindowSettingsProvider, - Supplier<SurfaceControl.Transaction> transactionFactory, - Supplier<SurfaceControl.Builder> surfaceControlFactory, - AppCompatConfiguration appCompat) { + private WindowManagerService(@NonNull Context context, + @NonNull InputManagerService inputManager, boolean showBootMsgs, + @NonNull WindowManagerPolicy policy, @NonNull ActivityTaskManagerService atm, + @NonNull DisplayWindowSettingsProvider displayWindowSettingsProvider, + @NonNull Supplier<SurfaceControl.Transaction> transactionFactory, + @NonNull Supplier<SurfaceControl.Builder> surfaceControlFactory, + @NonNull AppCompatConfiguration appCompat) { installLock(this, INDEX_WINDOW); mGlobalLock = atm.getGlobalLock(); mAtmService = atm; diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp index 132f95bea360..b328fc2d5868 100644 --- a/services/tests/wmtests/Android.bp +++ b/services/tests/wmtests/Android.bp @@ -11,19 +11,46 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -// Include all test java files. filegroup { - name: "wmtests-sources", + name: "wmtests-support-sources", srcs: [ - "src/**/*.java", + "src/com/android/server/wm/WindowManagerServiceTestSupport.kt", ], + path: "src", + visibility: ["//visibility:private"], +} + +java_library { + name: "wmtests-support", + srcs: [":wmtests-support-sources"], + static_libs: [ + "com.android.window.flags.window-aconfig-java", + "kotlin-stdlib", + "services.core", + ], + lint: { + test: true, + }, + visibility: [ + "//frameworks/base/services/tests/wmtests", + "//frameworks/opt/car/services/updatableServices/tests", + ], +} + +// Include all test files, but exclude test support files. +filegroup { + name: "wmtests-sources", + srcs: ["src/**/*.java"], + exclude_srcs: [":wmtests-support-sources"], + path: "src", + visibility: ["//visibility:private"], } java_genrule { name: "wmtests.protologsrc", srcs: [ - ":protolog-impl", ":protolog-groups", + ":protolog-impl", ":wmtests-sources", ], tools: ["protologtool"], @@ -52,33 +79,34 @@ android_test { ], static_libs: [ - "frameworks-base-testutils", - "services.core", - "service-permission.stubs.system_server", - "androidx.test.runner", + "CtsSurfaceValidatorLib", + "android.view.inputmethod.flags-aconfig-java", "androidx.test.rules", + "androidx.test.runner", + "com.android.window.flags.window-aconfig-java", + "flag-junit", "flickerlib", + "frameworks-base-testutils", + "hamcrest-library", "junit-params", + "mockito-kotlin2", "mockito-target-extended-minus-junit4", + "platform-compat-test-rules", "platform-test-annotations", + "service-permission.stubs.system_server", + "service-sdksandbox.impl", + "services.core", "servicestests-utils", + "testables", "testng", "truth", - "testables", - "hamcrest-library", - "flag-junit", - "platform-compat-test-rules", - "CtsSurfaceValidatorLib", - "service-sdksandbox.impl", - "com.android.window.flags.window-aconfig-java", - "android.view.inputmethod.flags-aconfig-java", - "flag-junit", + "wmtests-support", ], libs: [ "android.hardware.power-V1-java", - "android.test.mock.stubs.system", "android.test.base.stubs.system", + "android.test.mock.stubs.system", "android.test.runner.stubs.system", ], @@ -94,8 +122,8 @@ android_test { platform_apis: true, test_suites: [ - "device-tests", "automotive-tests", + "device-tests", ], certificate: "platform", diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index a12831e1ccf1..a95093d7e113 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -43,6 +43,7 @@ import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; +import android.annotation.Nullable; import android.app.ActivityManagerInternal; import android.app.ActivityThread; import android.app.AppOpsManager; @@ -67,7 +68,6 @@ import android.os.Looper; import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.PowerSaveState; -import android.os.StrictMode; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; @@ -75,7 +75,6 @@ import android.util.Log; import android.view.DisplayInfo; import android.view.InputChannel; import android.view.SurfaceControl; -import android.window.ConfigurationChangeSetting; import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.internal.os.BackgroundThread; @@ -96,11 +95,9 @@ import com.android.server.input.InputManagerService; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerService; import com.android.server.policy.PermissionPolicyInternal; -import com.android.server.policy.WindowManagerPolicy; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.testutils.StubTransaction; import com.android.server.uri.UriGrantsManagerInternal; -import com.android.window.flags.Flags; import org.junit.rules.TestRule; import org.junit.runner.Description; @@ -144,13 +141,15 @@ public class SystemServicesTestRule implements TestRule { private ActivityTaskManagerService mAtmService; private WindowManagerService mWmService; private InputManagerService mImService; - private Runnable mOnBeforeServicesCreated; + @Nullable + private final Runnable mOnBeforeServicesCreated; + /** * Spied {@link SurfaceControl.Transaction} class than can be used to verify calls. */ SurfaceControl.Transaction mTransaction; - public SystemServicesTestRule(Runnable onBeforeServicesCreated) { + public SystemServicesTestRule(@Nullable Runnable onBeforeServicesCreated) { mOnBeforeServicesCreated = onBeforeServicesCreated; } @@ -398,15 +397,13 @@ public class SystemServicesTestRule implements TestRule { } private void setUpWindowManagerService() { - TestWindowManagerPolicy wmPolicy = new TestWindowManagerPolicy(); - TestDisplayWindowSettingsProvider testDisplayWindowSettingsProvider = - new TestDisplayWindowSettingsProvider(); - // Suppress StrictMode violation (DisplayWindowSettings) to avoid log flood. - DisplayThread.getHandler().post(StrictMode::allowThreadDiskWritesMask); - mWmService = WindowManagerService.main( - mContext, mImService, false, wmPolicy, mAtmService, - testDisplayWindowSettingsProvider, StubTransaction::new, - MockSurfaceControlBuilder::new, mAppCompat); + // Use a spied Transaction class to prevent native code calls and verify interactions. + mTransaction = spy(StubTransaction.class); + + mWmService = WindowManagerServiceTestSupport.setUpService(mContext, mImService, + new TestWindowManagerPolicy(), mAtmService, new TestDisplayWindowSettingsProvider(), + mTransaction, new MockSurfaceControlBuilder(), mAppCompat); + spyOn(mWmService); spyOn(mWmService.mRoot); // Invoked during {@link ActivityStack} creation. @@ -418,10 +415,6 @@ public class SystemServicesTestRule implements TestRule { spyOn(mWmService.mDisplayWindowSettings); spyOn(mWmService.mDisplayWindowSettingsProvider); - // Setup factory classes to prevent calls to native code. - mTransaction = spy(StubTransaction.class); - // Return a spied Transaction class than can be used to verify calls. - mWmService.mTransactionFactory = () -> mTransaction; mWmService.mSurfaceAnimationRunner = new SurfaceAnimationRunner( null, null, mTransaction, mWmService.mPowerManagerInternal); @@ -488,12 +481,12 @@ public class SystemServicesTestRule implements TestRule { } private static void tearDownLocalServices() { + WindowManagerServiceTestSupport.tearDownService(); + LocalServices.removeServiceForTest(DisplayManagerInternal.class); LocalServices.removeServiceForTest(PowerManagerInternal.class); LocalServices.removeServiceForTest(ActivityManagerInternal.class); LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class); - LocalServices.removeServiceForTest(WindowManagerInternal.class); - LocalServices.removeServiceForTest(WindowManagerPolicy.class); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.removeServiceForTest(UriGrantsManagerInternal.class); LocalServices.removeServiceForTest(PermissionPolicyInternal.class); @@ -501,12 +494,7 @@ public class SystemServicesTestRule implements TestRule { LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); LocalServices.removeServiceForTest(StatusBarManagerInternal.class); LocalServices.removeServiceForTest(UserManagerInternal.class); - LocalServices.removeServiceForTest(ImeTargetVisibilityPolicy.class); LocalServices.removeServiceForTest(GrammaticalInflectionManagerInternal.class); - if (Flags.condenseConfigurationChangeForSimpleMode()) { - LocalServices.removeServiceForTest( - ConfigurationChangeSetting.ConfigurationChangeSettingInternal.class); - } } Description getDescription() { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTestSupport.kt b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTestSupport.kt new file mode 100644 index 000000000000..24deee29b5ac --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTestSupport.kt @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2025 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 com.android.server.wm + +import android.content.Context +import android.os.StrictMode +import android.view.SurfaceControl +import android.window.ConfigurationChangeSetting +import com.android.server.DisplayThread +import com.android.server.LocalServices +import com.android.server.input.InputManagerService +import com.android.server.policy.WindowManagerPolicy +import com.android.window.flags.Flags + +/** + * Provides support for tests that require a [WindowManagerService]. + * + * It provides functionalities for setting up and tearing down the service with proper dependencies, + * which can be used across different test modules. + */ +object WindowManagerServiceTestSupport { + + /** + * Sets up and initializes a [WindowManagerService] instance with the provided dependencies. + * + * This method constructs a [WindowManagerService] using the provided dependencies for testing. + * It's marked as `internal` due to the package-private classes [DisplayWindowSettingsProvider] + * and [AppCompatConfiguration]. The `@JvmName` annotation is used to bypass name mangling and + * allow access from Java via `WindowManagerServiceTestSupport.setUpService`. + * + * **Important:** Before calling this method, ensure that any previous [WindowManagerService] + * instance and its related services are properly torn down. In your test's setup, it is + * recommended to call [tearDownService] before calling [setUpService] to handle cases where a + * previous test might have crashed and left services in an inconsistent state. This is crucial + * for test reliability. + * + * Example usage in a test's `setUp()` method: + * ``` + * @Before + * fun setUp() { + * WindowManagerServiceTestSupport.tearDownService() // Clean up before setup. + * mWindowManagerService = WindowManagerServiceTestSupport.setUpService(...) + * // ... rest of your setup logic ... + * } + * ``` + * + * @param context the [Context]] for the service. + * @param im the [InputManagerService] to use. + * @param policy the [WindowManagerPolicy] to use. + * @param atm the [ActivityTaskManagerService] to use. + * @param displayWindowSettingsProvider the [DisplayWindowSettingsProvider] to use. + * @param surfaceControlTransaction the [SurfaceControl.Transaction] instance to use. + * @param surfaceControlBuilder the [SurfaceControl.Builder] instance to use. + * @param appCompat the [AppCompatConfiguration] to use. + * @return the created [WindowManagerService] instance. + */ + @JvmStatic + @JvmName("setUpService") + internal fun setUpService( + context: Context, + im: InputManagerService, + policy: WindowManagerPolicy, + atm: ActivityTaskManagerService, + displayWindowSettingsProvider: DisplayWindowSettingsProvider, + surfaceControlTransaction: SurfaceControl.Transaction, + surfaceControlBuilder: SurfaceControl.Builder, + appCompat: AppCompatConfiguration, + ): WindowManagerService { + // Suppress StrictMode violation (DisplayWindowSettings) to avoid log flood. + DisplayThread.getHandler().post { StrictMode.allowThreadDiskWritesMask() } + + return WindowManagerService.main( + context, + im, + false, /* showBootMsgs */ + policy, + atm, + displayWindowSettingsProvider, + { surfaceControlTransaction }, + { surfaceControlBuilder }, + appCompat, + ) + } + + /** Tears down the [WindowManagerService] and removes related local services. */ + @JvmStatic + fun tearDownService() { + LocalServices.removeServiceForTest(WindowManagerPolicy::class.java) + LocalServices.removeServiceForTest(WindowManagerInternal::class.java) + LocalServices.removeServiceForTest(ImeTargetVisibilityPolicy::class.java) + + if (Flags.condenseConfigurationChangeForSimpleMode()) { + LocalServices.removeServiceForTest( + ConfigurationChangeSetting.ConfigurationChangeSettingInternal::class.java, + ) + } + } +} |