Loading core/java/android/os/Environment_ravenwood.java +2 −9 Original line number Diff line number Diff line Loading @@ -15,12 +15,12 @@ */ package android.os; import android.platform.test.ravenwood.RavenwoodEnvironment; import android.util.Log; import com.android.ravenwood.common.RavenwoodInternalUtils; import java.io.File; import java.util.Objects; /** * Ravenwood redirect target class from {@link Environment}. Loading @@ -33,13 +33,6 @@ public class Environment_ravenwood { private Environment_ravenwood() { } private static volatile File sRootDir; /** Called by ravenwood to initialize it. */ public static void init(File rootDir) { sRootDir = Objects.requireNonNull(rootDir); } /** Redirected from the corresponding {@link Environment} method. */ static String getEnvPath(String variableName) { return System.getProperty("ravenwood.env." + variableName); Loading Loading @@ -68,7 +61,7 @@ public class Environment_ravenwood { throw new RuntimeException( "Path doesn't start with a '/'. Actual=" + path); } var root = Objects.requireNonNull(sRootDir); var root = RavenwoodEnvironment.getInstance().getRootDir(); if (path.startsWith(root.toString())) { if (VERBOSE) { Log.v(TAG, "translate: " + path + " is already translated"); Loading core/java/android/util/Log_ravenwood.java +4 −8 Original line number Diff line number Diff line Loading @@ -172,21 +172,17 @@ public class Log_ravenwood { } /** * PID. We need to use a JNI method to get it, but JNI isn't initially ready. * Call {@link #onRavenwoodRuntimeNativeReady} to signal when JNI is ready, at which point * we set this field. * (We don't want to call native methods that may not be fully initialized even with a * try-catch, because partially initialized JNI methods could crash the process.) * PID. Set from RavenwoodDriver */ private static volatile int sPid = 0; private static ThreadLocal<Integer> sTid = ThreadLocal.withInitial(Process::myTid); /** * Call it when {@link RavenwoodRuntimeNative} is usable. * Call it when PID is available. */ public static void onRavenwoodRuntimeNativeReady() { sPid = Process.myPid(); public static void setPid(int pid) { sPid = pid; } private static int getPid() { Loading ravenwood/common-src/com/android/ravenwood/common/RavenwoodInternalUtils.java +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ public class RavenwoodInternalUtils { private RavenwoodInternalUtils() { } public static final String ANDROID_PACKAGE_NAME = "android"; /** * If set to "1", we enable the verbose logging. * Loading ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodContext.java +3 −4 Original line number Diff line number Diff line Loading @@ -63,7 +63,6 @@ public class RavenwoodContext extends RavenwoodBaseContext { private final ArrayMap<Class<?>, String> mClassToName = new ArrayMap<>(); private final ArrayMap<String, Supplier<?>> mNameToFactory = new ArrayMap<>(); private final File mDataDir; private final Supplier<Resources> mResourcesSupplier; private Application mAppContext; Loading @@ -89,8 +88,6 @@ public class RavenwoodContext extends RavenwoodBaseContext { mMainThread = mainThread; mResourcesSupplier = resourcesSupplier; mDataDir = RavenwoodDriver.sAppDataDir; // Services provided by a typical shipping device registerService(ClipboardManager.class, Context.CLIPBOARD_SERVICE, memoize(() -> Loading Loading @@ -212,7 +209,9 @@ public class RavenwoodContext extends RavenwoodBaseContext { @Override public File getDataDir() { return mDataDir; // Create the dir lazily upon request. Note, "android" package doesn't have a // data dir. This would throw. return RavenwoodEnvironment.getInstance().getAppDataDir(mPackageName); } @Override Loading ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodDriver.java +46 −75 Original line number Diff line number Diff line Loading @@ -18,9 +18,9 @@ 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.modules.utils.ravenwood.RavenwoodHelper.RavenwoodInternal.RAVENWOOD_RUNTIME_PATH_JAVA_SYSPROP; import static com.android.ravenwood.common.RavenwoodInternalUtils.ANDROID_PACKAGE_NAME; import static com.android.ravenwood.common.RavenwoodInternalUtils.RAVENWOOD_EMPTY_RESOURCES_APK; import static com.android.ravenwood.common.RavenwoodInternalUtils.RAVENWOOD_INST_RESOURCE_APK; import static com.android.ravenwood.common.RavenwoodInternalUtils.RAVENWOOD_RESOURCE_APK; Loading Loading @@ -52,10 +52,8 @@ import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Environment_ravenwood; import android.os.HandlerThread; import android.os.Handler_ravenwood; import android.os.Looper; import android.os.Looper_ravenwood; import android.os.Message; import android.os.Process_ravenwood; Loading @@ -74,7 +72,6 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.RuntimeInit; import com.android.ravenwood.RavenwoodRuntimeNative; import com.android.ravenwood.RavenwoodRuntimeState; import com.android.ravenwood.common.RavenwoodInternalUtils; import com.android.ravenwood.common.SneakyThrow; import com.android.server.LocalServices; Loading @@ -85,9 +82,7 @@ import org.junit.internal.management.ManagementFactory; import org.junit.runner.Description; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; import java.util.Comparator; import java.util.HashMap; import java.util.Locale; Loading Loading @@ -117,7 +112,7 @@ public class RavenwoodDriver { private static final PrintStream sStdErr = System.err; private static final String MAIN_THREAD_NAME = "Ravenwood:Main"; private static final String TESTS_THREAD_NAME = "Ravenwood:Test"; private static final String TEST_THREAD_NAME = "Ravenwood:Test"; private static final String LIBRAVENWOOD_INITIALIZER_NAME = "ravenwood_initializer"; private static final String RAVENWOOD_NATIVE_RUNTIME_NAME = "ravenwood_runtime"; Loading Loading @@ -192,7 +187,7 @@ public class RavenwoodDriver { // TODO: expose packCallingIdentity function in libbinder and use it directly // See: packCallingIdentity in frameworks/native/libs/binder/IPCThreadState.cpp private static long packBinderIdentityToken( static long packBinderIdentityToken( boolean hasExplicitIdentity, int callingUid, int callingPid) { long res = ((long) callingUid << 32) | callingPid; if (hasExplicitIdentity) { Loading Loading @@ -221,32 +216,16 @@ public class RavenwoodDriver { private static final String DEFAULT_INSTRUMENTATION_CLASS = "androidx.test.runner.AndroidJUnitRunner"; static volatile Thread sTestThread; static volatile HandlerThread sMainThread; private static final int sMyPid = new Random().nextInt(100, 32768); private static int sTargetSdkLevel; private static String sTestPackageName; private static String sTargetPackageName; private static String sInstrumentationClass; static volatile RavenwoodContext sInstContext; static volatile RavenwoodContext sTargetContext; static volatile Application sTargetApplication; private static Instrumentation sInstrumentation; private static final long sCallingIdentity = packBinderIdentityToken(false, FIRST_APPLICATION_UID, sMyPid); static volatile File sRootDir; static volatile File sAppDataDir; /** * Initialize the global environment. */ public static void globalInitOnce() { sTestThread = Thread.currentThread(); Thread.currentThread().setName(TESTS_THREAD_NAME); Thread.currentThread().setName(TEST_THREAD_NAME); synchronized (sInitializationLock) { if (!sInitialized) { // globalInitOnce() is called from class initializer, which cause Loading Loading @@ -282,7 +261,7 @@ public class RavenwoodDriver { } } private static void globalInitInner() throws IOException { private static void globalInitInner() throws Exception { // We haven't initialized liblog yet, so directly write to System.out here. RavenwoodInternalUtils.log(TAG, "globalInitInner()"); Loading Loading @@ -313,7 +292,6 @@ public class RavenwoodDriver { System.load(RavenwoodInternalUtils.getJniLibraryPath(RAVENWOOD_NATIVE_RUNTIME_NAME)); Log_ravenwood.setLogLevels(getLogTags()); Log_ravenwood.onRavenwoodRuntimeNativeReady(); // Do the basic set up for the android sysprops. RavenwoodSystemProperties.initialize(); Loading Loading @@ -356,22 +334,12 @@ public class RavenwoodDriver { System.setProperty("android.junit.runner", "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner"); loadRavenwoodProperties(); assertMockitoVersion(); sRootDir = Files.createTempDirectory("ravenwood-root-dir-").toFile(); sAppDataDir = new File(sRootDir, "data/app/appdatadir/"); sAppDataDir.mkdirs(); Environment_ravenwood.init(sRootDir); Log.i(TAG, "TargetPackageName=" + sTargetPackageName); Log.i(TAG, "TestPackageName=" + sTestPackageName); Log.i(TAG, "TargetSdkLevel=" + sTargetSdkLevel); Looper_ravenwood.sDispatcher = RavenwoodDriver::dispatchMessage; RavenwoodRuntimeState.sUid = FIRST_APPLICATION_UID; RavenwoodRuntimeState.sPid = sMyPid; RavenwoodRuntimeState.sTargetSdkLevel = sTargetSdkLevel; var env = createEnvironment(); Log_ravenwood.setPid(env.getPid()); RavenwoodUtils.sPendingExceptionThrower = RavenwoodDriver::maybeThrowPendingRecoverableUncaughtExceptionNoClear; Loading @@ -380,11 +348,6 @@ public class RavenwoodDriver { return null; }; final var main = new HandlerThread(MAIN_THREAD_NAME); sMainThread = main; main.start(); Looper_ravenwood.sDispatcher = RavenwoodDriver::dispatchMessage; Looper.setMainLooperForTest(main.getLooper()); ServiceManager.init$ravenwood(); Loading @@ -392,8 +355,7 @@ public class RavenwoodDriver { ActivityManager.init$ravenwood(SYSTEM.getIdentifier()); final boolean isSelfInstrumenting = Objects.equals(sTestPackageName, sTargetPackageName); final boolean isSelfInstrumenting = env.isSelfInstrumenting(); // 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. Loading @@ -415,9 +377,9 @@ public class RavenwoodDriver { } sInstContext = new RavenwoodContext( sTestPackageName, main, instResourcesLoader); env.getInstPackageName(), env.getMainThread(), instResourcesLoader); sTargetContext = new RavenwoodContext( sTargetPackageName, main, targetResourcesLoader); env.getTargetPackageName(), env.getMainThread(), targetResourcesLoader); // Set up app context. App context is always created for the target app. var application = new Application(); Loading @@ -438,25 +400,18 @@ public class RavenwoodDriver { final Supplier<Resources> systemResourcesLoader = () -> loadResources(null); var systemServerContext = new RavenwoodContext(ANDROID_PACKAGE_NAME, main, systemResourcesLoader); var systemServerContext = new RavenwoodContext( ANDROID_PACKAGE_NAME, env.getMainThread(), systemResourcesLoader); var uiAutomation = new UiAutomation(sInstContext, new IUiAutomationConnection.Default()); var instArgs = Bundle.EMPTY; RavenwoodUtils.runOnMainThreadSync(() -> { var instClassName = withDefault(sInstrumentationClass, DEFAULT_INSTRUMENTATION_CLASS); try { var clazz = Class.forName(instClassName); var clazz = Class.forName(env.getInstrumentationClass()); sInstrumentation = (Instrumentation) clazz.getConstructor().newInstance(); } catch (ReflectiveOperationException e) { if (sInstrumentationClass != null) { // If the class is explicitly set, it is an error if the class is not found SneakyThrow.sneakyThrow(e); } else { // Fallback to the platform instrumentation sInstrumentation = new Instrumentation(); } } sInstrumentation.basicInit(sInstContext, sTargetContext, uiAutomation); Loading @@ -466,7 +421,7 @@ public class RavenwoodDriver { RavenwoodSystemServer.init(systemServerContext); initializeCompatIds(); initializeCompatIds(env); } /** Loading @@ -481,16 +436,29 @@ public class RavenwoodDriver { return logTags; } private static void loadRavenwoodProperties() { var props = RavenwoodSystemProperties.readProperties("ravenwood.properties"); private static RavenwoodEnvironment createEnvironment() throws Exception { final var props = RavenwoodSystemProperties.readProperties("ravenwood.properties"); sTargetSdkLevel = withDefault( // TODO(b/377765941) Read them from the manifest too? var targetSdkLevel = withDefault( parseNullableInt(props.get("targetSdkVersionInt")), DEFAULT_TARGET_SDK_LEVEL); sTargetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME); sTestPackageName = withDefault(props.get("instPackageName"), sTargetPackageName); sInstrumentationClass = props.get("instrumentationClass"); var targetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME); var testPackageName = withDefault(props.get("instPackageName"), targetPackageName); var instrumentationClass = withDefault(props.get("instrumentationClass"), DEFAULT_INSTRUMENTATION_CLASS); // TODO(b/377765941) Read them from the manifest too? // TODO: Why do we use a random PID? We can get the real PID via JNI. Why not use that? return RavenwoodEnvironment.init( FIRST_APPLICATION_UID, new Random().nextInt(100, 32768), targetSdkLevel, targetPackageName, testPackageName, instrumentationClass, Thread.currentThread(), // Test thread new HandlerThread(MAIN_THREAD_NAME) ); } private static void maybeThrowUnrecoverableUncaughtExceptionIfDetected() { Loading @@ -508,7 +476,8 @@ public class RavenwoodDriver { UiAutomation_ravenwood.reset(); Process_ravenwood.reset(); DeviceConfig_ravenwood.reset(); Binder.restoreCallingIdentity(sCallingIdentity); Binder.restoreCallingIdentity( RavenwoodEnvironment.getInstance().getDefaultCallingIdentity()); SystemProperties.clearChangeCallbacksForTest(); Loading @@ -527,7 +496,8 @@ public class RavenwoodDriver { maybeThrowUnrecoverableUncaughtExceptionIfDetected(); // TODO(b/375272444): this is a hacky workaround to ensure binder identity Binder.restoreCallingIdentity(sCallingIdentity); Binder.restoreCallingIdentity( RavenwoodEnvironment.getInstance().getDefaultCallingIdentity()); scheduleTimeout(); } Loading Loading @@ -562,7 +532,7 @@ public class RavenwoodDriver { } } private static void initializeCompatIds() { private static void initializeCompatIds(RavenwoodEnvironment env) { // 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 Loading @@ -570,8 +540,8 @@ public class RavenwoodDriver { // Compat framework only uses the package name and the target SDK level. ApplicationInfo appInfo = new ApplicationInfo(); appInfo.packageName = sTargetPackageName; appInfo.targetSdkVersion = sTargetSdkLevel; appInfo.packageName = env.getTargetPackageName(); appInfo.targetSdkVersion = env.getTargetSdkLevel(); PlatformCompat platformCompat = null; try { Loading Loading @@ -740,8 +710,9 @@ public class RavenwoodDriver { Comparator.comparingLong(Thread::getId)).collect(Collectors.toList()); // Put the test and the main thread at the top. var testThread = sTestThread; var mainThread = sMainThread; var env = RavenwoodEnvironment.getInstance(); var testThread = env.getTestThread(); var mainThread = env.getMainThread(); if (mainThread != null) { threads.remove(mainThread); threads.add(0, mainThread); Loading Loading
core/java/android/os/Environment_ravenwood.java +2 −9 Original line number Diff line number Diff line Loading @@ -15,12 +15,12 @@ */ package android.os; import android.platform.test.ravenwood.RavenwoodEnvironment; import android.util.Log; import com.android.ravenwood.common.RavenwoodInternalUtils; import java.io.File; import java.util.Objects; /** * Ravenwood redirect target class from {@link Environment}. Loading @@ -33,13 +33,6 @@ public class Environment_ravenwood { private Environment_ravenwood() { } private static volatile File sRootDir; /** Called by ravenwood to initialize it. */ public static void init(File rootDir) { sRootDir = Objects.requireNonNull(rootDir); } /** Redirected from the corresponding {@link Environment} method. */ static String getEnvPath(String variableName) { return System.getProperty("ravenwood.env." + variableName); Loading Loading @@ -68,7 +61,7 @@ public class Environment_ravenwood { throw new RuntimeException( "Path doesn't start with a '/'. Actual=" + path); } var root = Objects.requireNonNull(sRootDir); var root = RavenwoodEnvironment.getInstance().getRootDir(); if (path.startsWith(root.toString())) { if (VERBOSE) { Log.v(TAG, "translate: " + path + " is already translated"); Loading
core/java/android/util/Log_ravenwood.java +4 −8 Original line number Diff line number Diff line Loading @@ -172,21 +172,17 @@ public class Log_ravenwood { } /** * PID. We need to use a JNI method to get it, but JNI isn't initially ready. * Call {@link #onRavenwoodRuntimeNativeReady} to signal when JNI is ready, at which point * we set this field. * (We don't want to call native methods that may not be fully initialized even with a * try-catch, because partially initialized JNI methods could crash the process.) * PID. Set from RavenwoodDriver */ private static volatile int sPid = 0; private static ThreadLocal<Integer> sTid = ThreadLocal.withInitial(Process::myTid); /** * Call it when {@link RavenwoodRuntimeNative} is usable. * Call it when PID is available. */ public static void onRavenwoodRuntimeNativeReady() { sPid = Process.myPid(); public static void setPid(int pid) { sPid = pid; } private static int getPid() { Loading
ravenwood/common-src/com/android/ravenwood/common/RavenwoodInternalUtils.java +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ public class RavenwoodInternalUtils { private RavenwoodInternalUtils() { } public static final String ANDROID_PACKAGE_NAME = "android"; /** * If set to "1", we enable the verbose logging. * Loading
ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodContext.java +3 −4 Original line number Diff line number Diff line Loading @@ -63,7 +63,6 @@ public class RavenwoodContext extends RavenwoodBaseContext { private final ArrayMap<Class<?>, String> mClassToName = new ArrayMap<>(); private final ArrayMap<String, Supplier<?>> mNameToFactory = new ArrayMap<>(); private final File mDataDir; private final Supplier<Resources> mResourcesSupplier; private Application mAppContext; Loading @@ -89,8 +88,6 @@ public class RavenwoodContext extends RavenwoodBaseContext { mMainThread = mainThread; mResourcesSupplier = resourcesSupplier; mDataDir = RavenwoodDriver.sAppDataDir; // Services provided by a typical shipping device registerService(ClipboardManager.class, Context.CLIPBOARD_SERVICE, memoize(() -> Loading Loading @@ -212,7 +209,9 @@ public class RavenwoodContext extends RavenwoodBaseContext { @Override public File getDataDir() { return mDataDir; // Create the dir lazily upon request. Note, "android" package doesn't have a // data dir. This would throw. return RavenwoodEnvironment.getInstance().getAppDataDir(mPackageName); } @Override Loading
ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodDriver.java +46 −75 Original line number Diff line number Diff line Loading @@ -18,9 +18,9 @@ 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.modules.utils.ravenwood.RavenwoodHelper.RavenwoodInternal.RAVENWOOD_RUNTIME_PATH_JAVA_SYSPROP; import static com.android.ravenwood.common.RavenwoodInternalUtils.ANDROID_PACKAGE_NAME; import static com.android.ravenwood.common.RavenwoodInternalUtils.RAVENWOOD_EMPTY_RESOURCES_APK; import static com.android.ravenwood.common.RavenwoodInternalUtils.RAVENWOOD_INST_RESOURCE_APK; import static com.android.ravenwood.common.RavenwoodInternalUtils.RAVENWOOD_RESOURCE_APK; Loading Loading @@ -52,10 +52,8 @@ import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Environment_ravenwood; import android.os.HandlerThread; import android.os.Handler_ravenwood; import android.os.Looper; import android.os.Looper_ravenwood; import android.os.Message; import android.os.Process_ravenwood; Loading @@ -74,7 +72,6 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.RuntimeInit; import com.android.ravenwood.RavenwoodRuntimeNative; import com.android.ravenwood.RavenwoodRuntimeState; import com.android.ravenwood.common.RavenwoodInternalUtils; import com.android.ravenwood.common.SneakyThrow; import com.android.server.LocalServices; Loading @@ -85,9 +82,7 @@ import org.junit.internal.management.ManagementFactory; import org.junit.runner.Description; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; import java.util.Comparator; import java.util.HashMap; import java.util.Locale; Loading Loading @@ -117,7 +112,7 @@ public class RavenwoodDriver { private static final PrintStream sStdErr = System.err; private static final String MAIN_THREAD_NAME = "Ravenwood:Main"; private static final String TESTS_THREAD_NAME = "Ravenwood:Test"; private static final String TEST_THREAD_NAME = "Ravenwood:Test"; private static final String LIBRAVENWOOD_INITIALIZER_NAME = "ravenwood_initializer"; private static final String RAVENWOOD_NATIVE_RUNTIME_NAME = "ravenwood_runtime"; Loading Loading @@ -192,7 +187,7 @@ public class RavenwoodDriver { // TODO: expose packCallingIdentity function in libbinder and use it directly // See: packCallingIdentity in frameworks/native/libs/binder/IPCThreadState.cpp private static long packBinderIdentityToken( static long packBinderIdentityToken( boolean hasExplicitIdentity, int callingUid, int callingPid) { long res = ((long) callingUid << 32) | callingPid; if (hasExplicitIdentity) { Loading Loading @@ -221,32 +216,16 @@ public class RavenwoodDriver { private static final String DEFAULT_INSTRUMENTATION_CLASS = "androidx.test.runner.AndroidJUnitRunner"; static volatile Thread sTestThread; static volatile HandlerThread sMainThread; private static final int sMyPid = new Random().nextInt(100, 32768); private static int sTargetSdkLevel; private static String sTestPackageName; private static String sTargetPackageName; private static String sInstrumentationClass; static volatile RavenwoodContext sInstContext; static volatile RavenwoodContext sTargetContext; static volatile Application sTargetApplication; private static Instrumentation sInstrumentation; private static final long sCallingIdentity = packBinderIdentityToken(false, FIRST_APPLICATION_UID, sMyPid); static volatile File sRootDir; static volatile File sAppDataDir; /** * Initialize the global environment. */ public static void globalInitOnce() { sTestThread = Thread.currentThread(); Thread.currentThread().setName(TESTS_THREAD_NAME); Thread.currentThread().setName(TEST_THREAD_NAME); synchronized (sInitializationLock) { if (!sInitialized) { // globalInitOnce() is called from class initializer, which cause Loading Loading @@ -282,7 +261,7 @@ public class RavenwoodDriver { } } private static void globalInitInner() throws IOException { private static void globalInitInner() throws Exception { // We haven't initialized liblog yet, so directly write to System.out here. RavenwoodInternalUtils.log(TAG, "globalInitInner()"); Loading Loading @@ -313,7 +292,6 @@ public class RavenwoodDriver { System.load(RavenwoodInternalUtils.getJniLibraryPath(RAVENWOOD_NATIVE_RUNTIME_NAME)); Log_ravenwood.setLogLevels(getLogTags()); Log_ravenwood.onRavenwoodRuntimeNativeReady(); // Do the basic set up for the android sysprops. RavenwoodSystemProperties.initialize(); Loading Loading @@ -356,22 +334,12 @@ public class RavenwoodDriver { System.setProperty("android.junit.runner", "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner"); loadRavenwoodProperties(); assertMockitoVersion(); sRootDir = Files.createTempDirectory("ravenwood-root-dir-").toFile(); sAppDataDir = new File(sRootDir, "data/app/appdatadir/"); sAppDataDir.mkdirs(); Environment_ravenwood.init(sRootDir); Log.i(TAG, "TargetPackageName=" + sTargetPackageName); Log.i(TAG, "TestPackageName=" + sTestPackageName); Log.i(TAG, "TargetSdkLevel=" + sTargetSdkLevel); Looper_ravenwood.sDispatcher = RavenwoodDriver::dispatchMessage; RavenwoodRuntimeState.sUid = FIRST_APPLICATION_UID; RavenwoodRuntimeState.sPid = sMyPid; RavenwoodRuntimeState.sTargetSdkLevel = sTargetSdkLevel; var env = createEnvironment(); Log_ravenwood.setPid(env.getPid()); RavenwoodUtils.sPendingExceptionThrower = RavenwoodDriver::maybeThrowPendingRecoverableUncaughtExceptionNoClear; Loading @@ -380,11 +348,6 @@ public class RavenwoodDriver { return null; }; final var main = new HandlerThread(MAIN_THREAD_NAME); sMainThread = main; main.start(); Looper_ravenwood.sDispatcher = RavenwoodDriver::dispatchMessage; Looper.setMainLooperForTest(main.getLooper()); ServiceManager.init$ravenwood(); Loading @@ -392,8 +355,7 @@ public class RavenwoodDriver { ActivityManager.init$ravenwood(SYSTEM.getIdentifier()); final boolean isSelfInstrumenting = Objects.equals(sTestPackageName, sTargetPackageName); final boolean isSelfInstrumenting = env.isSelfInstrumenting(); // 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. Loading @@ -415,9 +377,9 @@ public class RavenwoodDriver { } sInstContext = new RavenwoodContext( sTestPackageName, main, instResourcesLoader); env.getInstPackageName(), env.getMainThread(), instResourcesLoader); sTargetContext = new RavenwoodContext( sTargetPackageName, main, targetResourcesLoader); env.getTargetPackageName(), env.getMainThread(), targetResourcesLoader); // Set up app context. App context is always created for the target app. var application = new Application(); Loading @@ -438,25 +400,18 @@ public class RavenwoodDriver { final Supplier<Resources> systemResourcesLoader = () -> loadResources(null); var systemServerContext = new RavenwoodContext(ANDROID_PACKAGE_NAME, main, systemResourcesLoader); var systemServerContext = new RavenwoodContext( ANDROID_PACKAGE_NAME, env.getMainThread(), systemResourcesLoader); var uiAutomation = new UiAutomation(sInstContext, new IUiAutomationConnection.Default()); var instArgs = Bundle.EMPTY; RavenwoodUtils.runOnMainThreadSync(() -> { var instClassName = withDefault(sInstrumentationClass, DEFAULT_INSTRUMENTATION_CLASS); try { var clazz = Class.forName(instClassName); var clazz = Class.forName(env.getInstrumentationClass()); sInstrumentation = (Instrumentation) clazz.getConstructor().newInstance(); } catch (ReflectiveOperationException e) { if (sInstrumentationClass != null) { // If the class is explicitly set, it is an error if the class is not found SneakyThrow.sneakyThrow(e); } else { // Fallback to the platform instrumentation sInstrumentation = new Instrumentation(); } } sInstrumentation.basicInit(sInstContext, sTargetContext, uiAutomation); Loading @@ -466,7 +421,7 @@ public class RavenwoodDriver { RavenwoodSystemServer.init(systemServerContext); initializeCompatIds(); initializeCompatIds(env); } /** Loading @@ -481,16 +436,29 @@ public class RavenwoodDriver { return logTags; } private static void loadRavenwoodProperties() { var props = RavenwoodSystemProperties.readProperties("ravenwood.properties"); private static RavenwoodEnvironment createEnvironment() throws Exception { final var props = RavenwoodSystemProperties.readProperties("ravenwood.properties"); sTargetSdkLevel = withDefault( // TODO(b/377765941) Read them from the manifest too? var targetSdkLevel = withDefault( parseNullableInt(props.get("targetSdkVersionInt")), DEFAULT_TARGET_SDK_LEVEL); sTargetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME); sTestPackageName = withDefault(props.get("instPackageName"), sTargetPackageName); sInstrumentationClass = props.get("instrumentationClass"); var targetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME); var testPackageName = withDefault(props.get("instPackageName"), targetPackageName); var instrumentationClass = withDefault(props.get("instrumentationClass"), DEFAULT_INSTRUMENTATION_CLASS); // TODO(b/377765941) Read them from the manifest too? // TODO: Why do we use a random PID? We can get the real PID via JNI. Why not use that? return RavenwoodEnvironment.init( FIRST_APPLICATION_UID, new Random().nextInt(100, 32768), targetSdkLevel, targetPackageName, testPackageName, instrumentationClass, Thread.currentThread(), // Test thread new HandlerThread(MAIN_THREAD_NAME) ); } private static void maybeThrowUnrecoverableUncaughtExceptionIfDetected() { Loading @@ -508,7 +476,8 @@ public class RavenwoodDriver { UiAutomation_ravenwood.reset(); Process_ravenwood.reset(); DeviceConfig_ravenwood.reset(); Binder.restoreCallingIdentity(sCallingIdentity); Binder.restoreCallingIdentity( RavenwoodEnvironment.getInstance().getDefaultCallingIdentity()); SystemProperties.clearChangeCallbacksForTest(); Loading @@ -527,7 +496,8 @@ public class RavenwoodDriver { maybeThrowUnrecoverableUncaughtExceptionIfDetected(); // TODO(b/375272444): this is a hacky workaround to ensure binder identity Binder.restoreCallingIdentity(sCallingIdentity); Binder.restoreCallingIdentity( RavenwoodEnvironment.getInstance().getDefaultCallingIdentity()); scheduleTimeout(); } Loading Loading @@ -562,7 +532,7 @@ public class RavenwoodDriver { } } private static void initializeCompatIds() { private static void initializeCompatIds(RavenwoodEnvironment env) { // 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 Loading @@ -570,8 +540,8 @@ public class RavenwoodDriver { // Compat framework only uses the package name and the target SDK level. ApplicationInfo appInfo = new ApplicationInfo(); appInfo.packageName = sTargetPackageName; appInfo.targetSdkVersion = sTargetSdkLevel; appInfo.packageName = env.getTargetPackageName(); appInfo.targetSdkVersion = env.getTargetSdkLevel(); PlatformCompat platformCompat = null; try { Loading Loading @@ -740,8 +710,9 @@ public class RavenwoodDriver { Comparator.comparingLong(Thread::getId)).collect(Collectors.toList()); // Put the test and the main thread at the top. var testThread = sTestThread; var mainThread = sMainThread; var env = RavenwoodEnvironment.getInstance(); var testThread = env.getTestThread(); var mainThread = env.getMainThread(); if (mainThread != null) { threads.remove(mainThread); threads.add(0, mainThread); Loading