summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Lin <ericth@google.com> 2025-01-10 23:06:21 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-01-10 23:06:21 -0800
commitecae5d80bcb219251bbe84bb7baa6a9fe52171b2 (patch)
treeb531a8c0648c1ca49a9d6ae0b5ba540bccbda5c6
parente2be8cf7eac354b5582a832b4416df47d9be9e60 (diff)
parent32e1982d50517dd4a4305c22fa87f7fd5e9c5579 (diff)
Merge "Extract WindowManagerService test support logic." into main
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java48
-rw-r--r--services/tests/wmtests/Android.bp66
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java40
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTestSupport.kt112
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,
+ )
+ }
+ }
+}