Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5136a6d authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Clean up log initialization

- Make sure RuntimeInit.redirectLogStreams() is always called even
  without RavenwoodRule is used.

- In RuntimeInit.redirectLogStreams(), make sure the Log class is
  initialized properly before setting up the redirect. Otherwise,
  we'd end up trying to use the Log APIs before the Log native code
  is loaded, which would cause an UnsatisfiedLinkError.

- Use $RAVENWOOD_VERBOSE_LOGGING to force enable verbose logging.
  If it's not set, the normal $ANDROID_LOG_TAGS would be used.

Fix: 363315644
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Flag: EXEMPT host test change only

Change-Id: Ifa4e4859c39380ebb3500cfb6570dfb78f839c0a
parent 02aebb42
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -404,6 +404,17 @@ public class RuntimeInit {
    }

    public static void redirectLogStreams$ravenwood() {
        if (sOut$ravenwood != null && sErr$ravenwood != null) {
            return; // Already initialized.
        }

        // Make sure the Log class is loaded and the JNI methods are hooked up,
        // before redirecting System.out/err.
        // Otherwise, because ClassLoadHook tries to write to System.out, this would cause
        // a circular initialization problem and would cause a UnsatisfiedLinkError
        // on the JNI methods.
        Log.isLoggable("X", Log.VERBOSE);

        if (sOut$ravenwood == null) {
            sOut$ravenwood = System.out;
            System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ java_library {
    libs: [
        "framework-minus-apex.ravenwood",
        "ravenwood-junit",
        "ravenwood-helper-libcore-runtime",
    ],
    visibility: ["//visibility:private"],
}
+27 −8
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ import android.util.Log;

import androidx.test.platform.app.InstrumentationRegistry;

import com.android.internal.os.RuntimeInit;
import com.android.ravenwood.common.RavenwoodCommonUtils;

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runners.model.TestClass;
@@ -35,7 +38,7 @@ import org.junit.runners.model.TestClass;
 * Provide hook points created by {@link RavenwoodAwareTestRunner}.
 */
public class RavenwoodAwareTestRunnerHook {
    private static final String TAG = "RavenwoodAwareTestRunnerHook";
    private static final String TAG = RavenwoodAwareTestRunner.TAG;

    private RavenwoodAwareTestRunnerHook() {
    }
@@ -56,20 +59,36 @@ public class RavenwoodAwareTestRunnerHook {
     * Called when a runner starts, before the inner runner gets a chance to run.
     */
    public static void onRunnerInitializing(Runner runner, TestClass testClass) {
        // TODO: Move the initialization code to a better place.

        initOnce();

        // This log call also ensures the framework JNI is loaded.
        Log.i(TAG, "onRunnerInitializing: testClass=" + testClass.getJavaClass()
                + " runner=" + runner);

        // TODO: Move the initialization code to a better place.
        // This is needed to make AndroidJUnit4ClassRunner happy.
        InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
    }

    private static boolean sInitialized = false;

    private static void initOnce() {
        if (sInitialized) {
            return;
        }
        sInitialized = true;

        // We haven't initialized liblog yet, so directly write to System.out here.
        RavenwoodCommonUtils.log(TAG, "initOnce()");

        // Redirect stdout/stdin to liblog.
        RuntimeInit.redirectLogStreams();

        // This will let AndroidJUnit4 use the original runner.
        System.setProperty("android.junit.runner",
                "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner");
        System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1");


        // This is needed to make AndroidJUnit4ClassRunner happy.
        InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
    }

    /**
@@ -87,7 +106,7 @@ public class RavenwoodAwareTestRunnerHook {
     */
    public static boolean onBefore(RavenwoodAwareTestRunner runner, Description description,
            Scope scope, Order order) {
        Log.i(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
        Log.v(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);

        if (scope == Scope.Class && order == Order.First) {
            // Keep track of the current class.
@@ -113,7 +132,7 @@ public class RavenwoodAwareTestRunnerHook {
     */
    public static boolean onAfter(RavenwoodAwareTestRunner runner, Description description,
            Scope scope, Order order, Throwable th) {
        Log.i(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
        Log.v(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);

        if (scope == Scope.Instance && order == Order.First) {
            getStats().onTestFinished(sCurrentClassDescription, description,
+0 −3
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import android.view.DisplayAdjustments;

import androidx.test.platform.app.InstrumentationRegistry;

import com.android.internal.os.RuntimeInit;
import com.android.server.LocalServices;

import org.junit.runner.Description;
@@ -92,8 +91,6 @@ public class RavenwoodRuleImpl {
            Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
        }

        RuntimeInit.redirectLogStreams();

        android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
        android.os.Binder.init$ravenwood();
        setSystemProperties(rule.mSystemProperties);
+10 −20
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static java.lang.annotation.ElementType.TYPE;

import android.util.Log;

import com.android.ravenwood.common.RavenwoodCommonUtils;
import com.android.ravenwood.common.SneakyThrow;

import org.junit.Assume;
@@ -75,7 +74,7 @@ import java.lang.reflect.InvocationTargetException;
 * (no hooks, etc.)
 */
public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orderable {
    private static final String TAG = "RavenwoodAwareTestRunner";
    public static final String TAG = "Ravenwood";

    @Inherited
    @Target({TYPE})
@@ -142,16 +141,9 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
    private Description mDescription = null;
    private Throwable mExceptionInConstructor = null;

    /** Simple logging method. */
    private void log(String message) {
        RavenwoodCommonUtils.log(TAG, "[" + getTestClass().getJavaClass() + "  @" + this + "] "
                + message);
    }

    private Error logAndFail(String message, Throwable innerException) {
        log(message);
        log("    Exception=" + innerException);
        throw new AssertionError(message, innerException);
    private Error logAndFail(String message, Throwable exception) {
        Log.e(TAG, message, exception);
        throw new AssertionError(message, exception);
    }

    public TestClass getTestClass() {
@@ -165,6 +157,8 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        try {
            mTestClass = new TestClass(testClass);

            onRunnerInitializing();

            /*
             * If the class has @DisabledOnRavenwood, then we'll delegate to
             * ClassSkippingTestRunner, which simply skips it.
@@ -186,10 +180,8 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
                realRunnerClass = BlockJUnit4ClassRunner.class;
            }

            onRunnerInitializing();

            try {
                log("Initializing the inner runner: " + realRunnerClass);
                Log.i(TAG, "Initializing the inner runner: " + realRunnerClass);

                mRealRunner = instantiateRealRunner(realRunnerClass, testClass);
                mDescription = mRealRunner.getDescription();
@@ -201,8 +193,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        } catch (Throwable th) {
            // If we throw in the constructor, Tradefed may not report it and just ignore the class,
            // so record it and throw it when the test actually started.
            log("Fatal: Exception detected in constructor: " + th.getMessage() + "\n"
                    + Log.getStackTraceString(th));
            Log.e(TAG, "Fatal: Exception detected in constructor", th);
            mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
                    th);
            mDescription = Description.createTestDescription(testClass, "Constructor");
@@ -236,8 +227,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        if (!isOnRavenwood()) {
            return;
        }

        log("onRunnerInitializing");
        // DO NOT USE android.util.Log before calling onRunnerInitializing().

        RavenwoodAwareTestRunnerHook.onRunnerInitializing(this, mTestClass);

@@ -250,7 +240,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        if (!isOnRavenwood()) {
            return;
        }
        log("runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
        Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());

        for (var method : getTestClass().getAnnotatedMethods(annotationClass)) {
            ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
Loading