diff options
author | 2024-11-21 23:26:02 +0000 | |
---|---|---|
committer | 2024-11-21 23:26:02 +0000 | |
commit | b870b936ca774ef624939cc06c4113421d065032 (patch) | |
tree | 118d2f330638d2fdc8b94c140427fbeec0159695 /ravenwood/junit-impl-src | |
parent | bf99335670cabe787dacb208c79b583ae509c6ca (diff) |
[Ravenwood] Decouple environment setup from RavenwoodConfig
- Also deprecate RavenwoodRule.setServicesRequired so that RavenwoodRule
is only used for setting system properties.
Flag: EXEMPT host test change only
Bug: 377765941
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Change-Id: Id7ca551bd797e786f2d71777eb9f972fb5fb6c88
Diffstat (limited to 'ravenwood/junit-impl-src')
5 files changed, 118 insertions, 270 deletions
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java index 9b71f8050c80..de3c5f2c23ab 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java @@ -133,9 +133,6 @@ public final class RavenwoodAwareTestRunner extends RavenwoodAwareTestRunnerBase Log.v(TAG, "RavenwoodAwareTestRunner starting for " + testClass.getCanonicalName()); - // This is needed to make AndroidJUnit4ClassRunner happy. - InstrumentationRegistry.registerInstance(null, Bundle.EMPTY); - // Hook point to allow more customization. runAnnotatedMethodsOnRavenwood(RavenwoodTestRunnerInitializing.class, null); diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java deleted file mode 100644 index 870a10a1f57e..000000000000 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2024 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.platform.test.ravenwood; - -import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_EMPTY_RESOURCES_APK; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.annotation.Nullable; -import android.app.ResourcesManager; -import android.content.res.Resources; -import android.view.DisplayAdjustments; - -import java.io.File; -import java.util.HashMap; - -/** - * Used to store various states associated with {@link RavenwoodConfig} that's inly needed - * in junit-impl. - * - * We don't want to put it in junit-src to avoid having to recompile all the downstream - * dependencies after changing this class. - * - * All members must be called from the runner's main thread. - */ -public class RavenwoodConfigState { - private static final String TAG = "RavenwoodConfigState"; - - private final RavenwoodConfig mConfig; - - // TODO: Move the other contexts from RavenwoodConfig to here too? They're used by - // RavenwoodRule too, but RavenwoodRule can probably use InstrumentationRegistry? - RavenwoodContext mSystemServerContext; - - public RavenwoodConfigState(RavenwoodConfig config) { - mConfig = config; - } - - /** Map from path -> resources. */ - private final HashMap<File, Resources> mCachedResources = new HashMap<>(); - - /** - * Load {@link Resources} from an APK, with cache. - */ - public Resources loadResources(@Nullable File apkPath) { - var cached = mCachedResources.get(apkPath); - if (cached != null) { - return cached; - } - - var fileToLoad = apkPath != null ? apkPath : new File(RAVENWOOD_EMPTY_RESOURCES_APK); - - assertTrue("File " + fileToLoad + " doesn't exist.", fileToLoad.isFile()); - - final String path = fileToLoad.getAbsolutePath(); - final var emptyPaths = new String[0]; - - ResourcesManager.getInstance().initializeApplicationPaths(path, emptyPaths); - - final var ret = ResourcesManager.getInstance().getResources(null, path, - emptyPaths, emptyPaths, emptyPaths, - emptyPaths, null, null, - new DisplayAdjustments().getCompatibilityInfo(), - RavenwoodRuntimeEnvironmentController.class.getClassLoader(), null); - - assertNotNull(ret); - - mCachedResources.put(apkPath, ret); - return ret; - } -} diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java index ec00e8fea887..4ab1fa1579e1 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java @@ -53,11 +53,6 @@ public final class RavenwoodRunnerState { } /** - * The RavenwoodConfig used to configure the current Ravenwood environment. - * This can either come from mConfig or mRule. - */ - private RavenwoodConfig mCurrentConfig; - /** * The RavenwoodConfig declared in the test class */ private RavenwoodConfig mConfig; @@ -68,10 +63,6 @@ public final class RavenwoodRunnerState { private boolean mHasRavenwoodRule; private Description mMethodDescription; - public RavenwoodConfig getConfig() { - return mCurrentConfig; - } - public void enterTestRunner() { Log.i(TAG, "enterTestRunner: " + mRunner); @@ -83,31 +74,19 @@ public final class RavenwoodRunnerState { fail("RavenwoodConfig and RavenwoodRule cannot be used in the same class." + " Suggest migrating to RavenwoodConfig."); } - mCurrentConfig = mConfig; - } else if (!mHasRavenwoodRule) { - // If no RavenwoodConfig and no RavenwoodRule, use a default config - mCurrentConfig = new RavenwoodConfig.Builder().build(); } - if (mCurrentConfig != null) { - RavenwoodRuntimeEnvironmentController.init(mRunner); - } + RavenwoodRuntimeEnvironmentController.initForRunner(); } public void enterTestClass() { Log.i(TAG, "enterTestClass: " + mRunner.mTestJavaClass.getName()); - - if (mCurrentConfig != null) { - RavenwoodRuntimeEnvironmentController.init(mRunner); - } } public void exitTestClass() { Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName()); try { - if (mCurrentConfig != null) { - RavenwoodRuntimeEnvironmentController.reset(); - } + RavenwoodRuntimeEnvironmentController.exitTestClass(); } finally { mConfig = null; mRule = null; @@ -116,11 +95,11 @@ public final class RavenwoodRunnerState { public void enterTestMethod(Description description) { mMethodDescription = description; + RavenwoodRuntimeEnvironmentController.initForMethod(); } public void exitTestMethod() { mMethodDescription = null; - RavenwoodRuntimeEnvironmentController.reinit(); } public void enterRavenwoodRule(RavenwoodRule rule) { @@ -133,10 +112,7 @@ public final class RavenwoodRunnerState { + " which is not supported."); } mRule = rule; - if (mCurrentConfig == null) { - mCurrentConfig = rule.getConfiguration(); - } - RavenwoodRuntimeEnvironmentController.init(mRunner); + RavenwoodRuntimeEnvironmentController.setSystemProperties(rule.mSystemProperties); } public void exitRavenwoodRule(RavenwoodRule rule) { diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java index 979076eaabfd..c2ed45d8f427 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java @@ -16,8 +16,11 @@ package android.platform.test.ravenwood; +import static android.os.Process.FIRST_APPLICATION_UID; +import static android.os.UserHandle.SYSTEM; import static android.platform.test.ravenwood.RavenwoodSystemServer.ANDROID_PACKAGE_NAME; +import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_EMPTY_RESOURCES_APK; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_INST_RESOURCE_APK; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOURCE_APK; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; @@ -25,7 +28,9 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERSIO import static com.android.ravenwood.common.RavenwoodCommonUtils.parseNullableInt; import static com.android.ravenwood.common.RavenwoodCommonUtils.withDefault; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -53,6 +58,7 @@ import android.provider.DeviceConfig_host; import android.system.ErrnoException; import android.system.Os; import android.util.Log; +import android.view.DisplayAdjustments; import androidx.test.platform.app.InstrumentationRegistry; @@ -62,7 +68,6 @@ import com.android.internal.os.RuntimeInit; import com.android.ravenwood.RavenwoodRuntimeNative; import com.android.ravenwood.RavenwoodRuntimeState; import com.android.ravenwood.common.RavenwoodCommonUtils; -import com.android.ravenwood.common.RavenwoodRuntimeException; import com.android.ravenwood.common.SneakyThrow; import com.android.server.LocalServices; import com.android.server.compat.PlatformCompat; @@ -74,8 +79,10 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Random; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -85,8 +92,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; /** - * Responsible for initializing and de-initializing the environment, according to a - * {@link RavenwoodConfig}. + * Responsible for initializing and the environment. */ public class RavenwoodRuntimeEnvironmentController { private static final String TAG = "RavenwoodRuntimeEnvironmentController"; @@ -113,8 +119,6 @@ public class RavenwoodRuntimeEnvironmentController { private static ScheduledFuture<?> sPendingTimeout; - private static long sOriginalIdentityToken = -1; - /** * When enabled, attempt to detect uncaught exceptions from background threads. */ @@ -147,6 +151,10 @@ public class RavenwoodRuntimeEnvironmentController { return res; } + /** Map from path -> resources. */ + private static final HashMap<File, Resources> sCachedResources = new HashMap<>(); + private static Set<String> sAdoptedPermissions = Collections.emptySet(); + private static final Object sInitializationLock = new Object(); @GuardedBy("sInitializationLock") @@ -155,15 +163,18 @@ public class RavenwoodRuntimeEnvironmentController { @GuardedBy("sInitializationLock") private static Throwable sExceptionFromGlobalInit; - private static RavenwoodAwareTestRunner sRunner; private static RavenwoodSystemProperties sProps; private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT; private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname"; + private static final int sMyPid = new Random().nextInt(100, 32768); private static int sTargetSdkLevel; private static String sTestPackageName; private static String sTargetPackageName; + private static Instrumentation sInstrumentation; + private static final long sCallingIdentity = + packBinderIdentityToken(false, FIRST_APPLICATION_UID, sMyPid); /** * Initialize the global environment. @@ -182,7 +193,7 @@ public class RavenwoodRuntimeEnvironmentController { Log.e(TAG, "globalInit() failed", th); sExceptionFromGlobalInit = th; - throw th; + SneakyThrow.sneakyThrow(th); } } else { // Subsequent calls. If the first call threw, just throw the same error, to prevent @@ -197,10 +208,13 @@ public class RavenwoodRuntimeEnvironmentController { } } - private static void globalInitInner() { + private static void globalInitInner() throws IOException { if (RAVENWOOD_VERBOSE_LOGGING) { Log.v(TAG, "globalInit() called here...", new RuntimeException("NOT A CRASH")); } + if (ENABLE_UNCAUGHT_EXCEPTION_DETECTION) { + Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler); + } // Some process-wide initialization. (maybe redirect stdout/stderr) RavenwoodCommonUtils.loadJniLibrary(LIBRAVENWOOD_INITIALIZER_NAME); @@ -251,82 +265,32 @@ public class RavenwoodRuntimeEnvironmentController { loadRavenwoodProperties(); assertMockitoVersion(); - } - - private static void loadRavenwoodProperties() { - var props = RavenwoodSystemProperties.readProperties("ravenwood.properties"); - - sTargetSdkLevel = withDefault( - parseNullableInt(props.get("targetSdkVersionInt")), DEFAULT_TARGET_SDK_LEVEL); - sTargetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME); - sTestPackageName = withDefault(props.get("instPackageName"), sTargetPackageName); - - // TODO(b/377765941) Read them from the manifest too? - } - - /** - * Initialize the environment. - */ - public static void init(RavenwoodAwareTestRunner runner) { - if (RAVENWOOD_VERBOSE_LOGGING) { - Log.v(TAG, "init() called here: " + runner, new RuntimeException("STACKTRACE")); - } - if (sRunner == runner) { - return; - } - if (sRunner != null) { - reset(); - } - sRunner = runner; - try { - initInner(runner.mState.getConfig()); - } catch (Exception th) { - Log.e(TAG, "init() failed", th); - - RavenwoodCommonUtils.runIgnoringException(()-> reset()); - - SneakyThrow.sneakyThrow(th); - } - } - - private static void initInner(RavenwoodConfig config) throws IOException { - if (ENABLE_UNCAUGHT_EXCEPTION_DETECTION) { - maybeThrowPendingUncaughtException(false); - Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler); - } - - config.mTargetPackageName = sTargetPackageName; - config.mTestPackageName = sTestPackageName; - config.mTargetSdkLevel = sTargetSdkLevel; Log.i(TAG, "TargetPackageName=" + sTargetPackageName); Log.i(TAG, "TestPackageName=" + sTestPackageName); Log.i(TAG, "TargetSdkLevel=" + sTargetSdkLevel); - RavenwoodRuntimeState.sUid = config.mUid; - RavenwoodRuntimeState.sPid = config.mPid; - RavenwoodRuntimeState.sTargetSdkLevel = config.mTargetSdkLevel; - sOriginalIdentityToken = Binder.clearCallingIdentity(); - reinit(); - setSystemProperties(config.mSystemProperties); + RavenwoodRuntimeState.sUid = FIRST_APPLICATION_UID; + RavenwoodRuntimeState.sPid = sMyPid; + RavenwoodRuntimeState.sTargetSdkLevel = sTargetSdkLevel; ServiceManager.init$ravenwood(); LocalServices.removeAllServicesForTest(); - ActivityManager.init$ravenwood(config.mCurrentUser); + ActivityManager.init$ravenwood(SYSTEM.getIdentifier()); final var main = new HandlerThread(MAIN_THREAD_NAME); main.start(); Looper.setMainLooperForTest(main.getLooper()); final boolean isSelfInstrumenting = - Objects.equals(config.mTestPackageName, config.mTargetPackageName); + Objects.equals(sTestPackageName, sTargetPackageName); // This will load the resources from the apk set to `resource_apk` in the build file. // This is supposed to be the "target app"'s resources. final Supplier<Resources> targetResourcesLoader = () -> { var file = new File(RAVENWOOD_RESOURCE_APK); - return config.mState.loadResources(file.exists() ? file : null); + return loadResources(file.exists() ? file : null); }; // Set up test context's (== instrumentation context's) resources. @@ -337,18 +301,17 @@ public class RavenwoodRuntimeEnvironmentController { } else { instResourcesLoader = () -> { var file = new File(RAVENWOOD_INST_RESOURCE_APK); - return config.mState.loadResources(file.exists() ? file : null); + return loadResources(file.exists() ? file : null); }; } var instContext = new RavenwoodContext( - config.mTestPackageName, main, instResourcesLoader); + sTestPackageName, main, instResourcesLoader); var targetContext = new RavenwoodContext( - config.mTargetPackageName, main, targetResourcesLoader); + sTargetPackageName, main, targetResourcesLoader); // Set up app context. - var appContext = new RavenwoodContext( - config.mTargetPackageName, main, targetResourcesLoader); + var appContext = new RavenwoodContext(sTargetPackageName, main, targetResourcesLoader); appContext.setApplicationContext(appContext); if (isSelfInstrumenting) { instContext.setApplicationContext(appContext); @@ -357,42 +320,65 @@ public class RavenwoodRuntimeEnvironmentController { // When instrumenting into another APK, the test context doesn't have an app context. targetContext.setApplicationContext(appContext); } - config.mInstContext = instContext; - config.mTargetContext = targetContext; - final Supplier<Resources> systemResourcesLoader = () -> config.mState.loadResources(null); + final Supplier<Resources> systemResourcesLoader = () -> loadResources(null); - config.mState.mSystemServerContext = + var systemServerContext = new RavenwoodContext(ANDROID_PACKAGE_NAME, main, systemResourcesLoader); - // Prepare other fields. - config.mInstrumentation = new Instrumentation(); - config.mInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation()); - InstrumentationRegistry.registerInstance(config.mInstrumentation, Bundle.EMPTY); + sInstrumentation = new Instrumentation(); + sInstrumentation.basicInit(instContext, targetContext, null); + InstrumentationRegistry.registerInstance(sInstrumentation, Bundle.EMPTY); + + RavenwoodSystemServer.init(systemServerContext); + + initializeCompatIds(); + } + + private static void loadRavenwoodProperties() { + var props = RavenwoodSystemProperties.readProperties("ravenwood.properties"); + + sTargetSdkLevel = withDefault( + parseNullableInt(props.get("targetSdkVersionInt")), DEFAULT_TARGET_SDK_LEVEL); + sTargetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME); + sTestPackageName = withDefault(props.get("instPackageName"), sTargetPackageName); + + // TODO(b/377765941) Read them from the manifest too? + } - RavenwoodSystemServer.init(config); + /** + * Partially reset and initialize before each test class invocation + */ + public static void initForRunner() { + var targetContext = sInstrumentation.getTargetContext(); + var instContext = sInstrumentation.getContext(); + // We need to recreate the mock UiAutomation for each test class, because sometimes tests + // will call Mockito.framework().clearInlineMocks() after execution. + sInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation()); - initializeCompatIds(config); + Process_ravenwood.reset(); + DeviceConfig_host.reset(); + Binder.restoreCallingIdentity(sCallingIdentity); if (ENABLE_TIMEOUT_STACKS) { sPendingTimeout = sTimeoutExecutor.schedule( RavenwoodRuntimeEnvironmentController::dumpStacks, TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } + if (ENABLE_UNCAUGHT_EXCEPTION_DETECTION) { + maybeThrowPendingUncaughtException(false); + } } /** - * Partially re-initialize after each test method invocation + * Partially reset and initialize before each test method invocation */ - public static void reinit() { - // sRunner could be null, if there was a failure in the initialization. - if (sRunner != null) { - var config = sRunner.mState.getConfig(); - Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid)); - } + public static void initForMethod() { + // TODO(b/375272444): this is a hacky workaround to ensure binder identity + Binder.restoreCallingIdentity(sCallingIdentity); } - private static void initializeCompatIds(RavenwoodConfig config) { + private static void initializeCompatIds() { // Set up compat-IDs for the app side. // TODO: Inside the system server, all the compat-IDs should be enabled, // Due to the `AppCompatCallbacks.install(new long[0], new long[0])` call in @@ -400,8 +386,8 @@ public class RavenwoodRuntimeEnvironmentController { // Compat framework only uses the package name and the target SDK level. ApplicationInfo appInfo = new ApplicationInfo(); - appInfo.packageName = config.mTargetPackageName; - appInfo.targetSdkVersion = config.mTargetSdkLevel; + appInfo.packageName = sTargetPackageName; + appInfo.targetSdkVersion = sTargetSdkLevel; PlatformCompat platformCompat = null; try { @@ -418,65 +404,42 @@ public class RavenwoodRuntimeEnvironmentController { } /** - * De-initialize. - * - * Note, we call this method when init() fails too, so this method should deal with - * any partially-initialized states. + * Load {@link Resources} from an APK, with cache. */ - public static void reset() { - if (RAVENWOOD_VERBOSE_LOGGING) { - Log.v(TAG, "reset() called here", new RuntimeException("STACKTRACE")); - } - if (sRunner == null) { - throw new RavenwoodRuntimeException("Internal error: reset() already called"); + private static Resources loadResources(@Nullable File apkPath) { + var cached = sCachedResources.get(apkPath); + if (cached != null) { + return cached; } - var config = sRunner.mState.getConfig(); - sRunner = null; - if (ENABLE_TIMEOUT_STACKS) { - sPendingTimeout.cancel(false); - } + var fileToLoad = apkPath != null ? apkPath : new File(RAVENWOOD_EMPTY_RESOURCES_APK); - RavenwoodSystemServer.reset(config); + assertTrue("File " + fileToLoad + " doesn't exist.", fileToLoad.isFile()); - InstrumentationRegistry.registerInstance(null, Bundle.EMPTY); - config.mInstrumentation = null; - if (config.mInstContext != null) { - ((RavenwoodContext) config.mInstContext).cleanUp(); - config.mInstContext = null; - } - if (config.mTargetContext != null) { - ((RavenwoodContext) config.mTargetContext).cleanUp(); - config.mTargetContext = null; - } - if (config.mState.mSystemServerContext != null) { - config.mState.mSystemServerContext.cleanUp(); - } + final String path = fileToLoad.getAbsolutePath(); + final var emptyPaths = new String[0]; - if (Looper.getMainLooper() != null) { - Looper.getMainLooper().quit(); - } - Looper.clearMainLooperForTest(); + ResourcesManager.getInstance().initializeApplicationPaths(path, emptyPaths); - ActivityManager.reset$ravenwood(); + final var ret = ResourcesManager.getInstance().getResources(null, path, + emptyPaths, emptyPaths, emptyPaths, + emptyPaths, null, null, + new DisplayAdjustments().getCompatibilityInfo(), + RavenwoodRuntimeEnvironmentController.class.getClassLoader(), null); - LocalServices.removeAllServicesForTest(); - ServiceManager.reset$ravenwood(); + assertNotNull(ret); - setSystemProperties(null); - if (sOriginalIdentityToken != -1) { - Binder.restoreCallingIdentity(sOriginalIdentityToken); - } - RavenwoodRuntimeState.reset(); - Process_ravenwood.reset(); - DeviceConfig_host.reset(); + sCachedResources.put(apkPath, ret); + return ret; + } - try { - ResourcesManager.setInstance(null); // Better structure needed. - } catch (Exception e) { - // AOSP-CHANGE: AOSP doesn't support resources yet. + /** + * A callback when a test class finishes its execution, mostly only for debugging. + */ + public static void exitTestClass() { + if (ENABLE_TIMEOUT_STACKS) { + sPendingTimeout.cancel(false); } - if (ENABLE_UNCAUGHT_EXCEPTION_DETECTION) { maybeThrowPendingUncaughtException(true); } @@ -524,7 +487,7 @@ public class RavenwoodRuntimeEnvironmentController { /** * Set the current configuration to the actual SystemProperties. */ - private static void setSystemProperties(@Nullable RavenwoodSystemProperties systemProperties) { + public static void setSystemProperties(@Nullable RavenwoodSystemProperties systemProperties) { SystemProperties.clearChangeCallbacksForTest(); RavenwoodRuntimeNative.clearSystemProperties(); if (systemProperties == null) systemProperties = new RavenwoodSystemProperties(); @@ -558,28 +521,28 @@ public class RavenwoodRuntimeEnvironmentController { // TODO: use the real UiAutomation class instead of a mock private static UiAutomation createMockUiAutomation() { - final Set[] adoptedPermission = { Collections.emptySet() }; + sAdoptedPermissions = Collections.emptySet(); var mock = mock(UiAutomation.class, inv -> { HostTestUtils.onThrowMethodCalled(); return null; }); doAnswer(inv -> { - adoptedPermission[0] = UiAutomation.ALL_PERMISSIONS; + sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS; return null; }).when(mock).adoptShellPermissionIdentity(); doAnswer(inv -> { if (inv.getArgument(0) == null) { - adoptedPermission[0] = UiAutomation.ALL_PERMISSIONS; + sAdoptedPermissions = UiAutomation.ALL_PERMISSIONS; } else { - adoptedPermission[0] = Set.of(inv.getArguments()); + sAdoptedPermissions = (Set) Set.of(inv.getArguments()); } return null; }).when(mock).adoptShellPermissionIdentity(any()); doAnswer(inv -> { - adoptedPermission[0] = Collections.emptySet(); + sAdoptedPermissions = Collections.emptySet(); return null; }).when(mock).dropShellPermissionIdentity(); - doAnswer(inv -> adoptedPermission[0]).when(mock).getAdoptedShellPermissions(); + doAnswer(inv -> sAdoptedPermissions).when(mock).getAdoptedShellPermissions(); return mock; } diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java index 438a2bfa7a14..3346635b7f7b 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java @@ -33,7 +33,7 @@ import com.android.server.compat.PlatformCompat; import com.android.server.compat.PlatformCompatNative; import com.android.server.utils.TimingsTraceAndSlog; -import java.util.List; +import java.util.Collection; import java.util.Set; public class RavenwoodSystemServer { @@ -68,27 +68,24 @@ public class RavenwoodSystemServer { private static TimingsTraceAndSlog sTimings; private static SystemServiceManager sServiceManager; - public static void init(RavenwoodConfig config) { + public static void init(Context systemServerContext) { // Always start PlatformCompat, regardless of the requested services. // PlatformCompat is not really a SystemService, so it won't receive boot phases / etc. // This initialization code is copied from SystemServer.java. - PlatformCompat platformCompat = new PlatformCompat(config.mState.mSystemServerContext); + PlatformCompat platformCompat = new PlatformCompat(systemServerContext); ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat); ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE, new PlatformCompatNative(platformCompat)); - // Avoid overhead if no services required - if (config.mServicesRequired.isEmpty()) return; - sStartedServices = new ArraySet<>(); sTimings = new TimingsTraceAndSlog(); - sServiceManager = new SystemServiceManager(config.mState.mSystemServerContext); + sServiceManager = new SystemServiceManager(systemServerContext); sServiceManager.setStartInfo(false, SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); LocalServices.addService(SystemServiceManager.class, sServiceManager); - startServices(config.mServicesRequired); + startServices(sKnownServices.keySet()); sServiceManager.sealStartedServices(); // TODO: expand to include additional boot phases when relevant @@ -96,7 +93,7 @@ public class RavenwoodSystemServer { sServiceManager.startBootPhase(sTimings, SystemService.PHASE_BOOT_COMPLETED); } - public static void reset(RavenwoodConfig config) { + public static void reset() { // TODO: consider introducing shutdown boot phases LocalServices.removeServiceForTest(SystemServiceManager.class); @@ -105,7 +102,7 @@ public class RavenwoodSystemServer { sStartedServices = null; } - private static void startServices(List<Class<?>> serviceClasses) { + private static void startServices(Collection<Class<?>> serviceClasses) { for (Class<?> serviceClass : serviceClasses) { // Quietly ignore duplicate requests if service already started if (sStartedServices.contains(serviceClass)) continue; |