summaryrefslogtreecommitdiff
path: root/ravenwood/junit-impl-src
diff options
context:
space:
mode:
author John Wu <topjohnwu@google.com> 2024-11-21 23:26:02 +0000
committer John Wu <topjohnwu@google.com> 2024-11-21 23:26:02 +0000
commitb870b936ca774ef624939cc06c4113421d065032 (patch)
tree118d2f330638d2fdc8b94c140427fbeec0159695 /ravenwood/junit-impl-src
parentbf99335670cabe787dacb208c79b583ae509c6ca (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')
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java3
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java85
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java32
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java251
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java17
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;