Skip to content
Snippets Groups Projects
Commit 587b3bec authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Ravenwood support for `wtf()`, wrap logging.

There are some tests triggering `wtf()` during the normal course of
operation, and we haven't been able to reproduce them yet.  This
change gives us a valid `wtf()` implementation to aid debugging.

It's also a bit jarring to have log-style messages interleaved with
raw `System.out`, so also add `redirectLogStreams()` to match the
logging behavior that developers observe on physical devices.

Bug: 322805216
Test: atest FrameworksCoreTestsRavenwood FrameworksUtilTestsRavenwood
Change-Id: I8ea2d12638cd998e3962aaa8af09a3335fcd0d51
parent a2d78978
No related branches found
No related tags found
No related merge requests found
......@@ -217,7 +217,6 @@ public final class Slog {
* @see Log#wtf(String, String)
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@android.ravenwood.annotation.RavenwoodThrow
public static int wtf(@Nullable String tag, @NonNull String msg) {
return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, false, true);
}
......@@ -263,7 +262,6 @@ public final class Slog {
*
* @see Log#wtf(String, Throwable)
*/
@android.ravenwood.annotation.RavenwoodThrow
public static int wtf(@Nullable String tag, @Nullable Throwable tr) {
return Log.wtf(Log.LOG_ID_SYSTEM, tag, tr.getMessage(), tr, false, true);
}
......@@ -284,7 +282,6 @@ public final class Slog {
* @see Log#wtf(String, String, Throwable)
*/
@UnsupportedAppUsage
@android.ravenwood.annotation.RavenwoodThrow
public static int wtf(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, tr, false, true);
}
......
......@@ -24,6 +24,7 @@ import android.util.Log;
*
* {@hide}
*/
@android.ravenwood.annotation.RavenwoodKeepWholeClass
class AndroidPrintStream extends LoggingPrintStream {
private final int priority;
......
......@@ -39,6 +39,7 @@ import dalvik.system.VMRuntime;
import libcore.content.type.MimeMap;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
......@@ -50,6 +51,7 @@ import java.util.logging.LogManager;
* public consumption.
* @hide
*/
@android.ravenwood.annotation.RavenwoodKeepPartialClass
public class RuntimeInit {
final static String TAG = "AndroidRuntime";
final static boolean DEBUG = false;
......@@ -67,7 +69,15 @@ public class RuntimeInit {
private static volatile ApplicationWtfHandler sDefaultApplicationWtfHandler;
/**
* Stored values of System.out and System.err before they've been replaced by
* redirectLogStreams(). Kept open here for other Ravenwood internals to use.
*/
public static PrintStream sOut$ravenwood;
public static PrintStream sErr$ravenwood;
private static final native void nativeFinishInit();
private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
private static int Clog_e(String tag, String msg, Throwable tr) {
......@@ -385,6 +395,7 @@ public class RuntimeInit {
/**
* Redirect System.out and System.err to the Android log.
*/
@android.ravenwood.annotation.RavenwoodReplace
public static void redirectLogStreams() {
System.out.close();
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
......@@ -392,6 +403,17 @@ public class RuntimeInit {
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
}
public static void redirectLogStreams$ravenwood() {
if (sOut$ravenwood == null) {
sOut$ravenwood = System.out;
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
}
if (sErr$ravenwood == null) {
sErr$ravenwood = System.err;
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
}
}
/**
* Report a serious error in the current process. May or may not cause
* the process to terminate (depends on system settings).
......@@ -399,6 +421,7 @@ public class RuntimeInit {
* @param tag to record with the error
* @param t exception describing the error site and conditions
*/
@android.ravenwood.annotation.RavenwoodReplace
public static void wtf(String tag, Throwable t, boolean system) {
try {
boolean exit = false;
......@@ -436,6 +459,11 @@ public class RuntimeInit {
}
}
public static void wtf$ravenwood(String tag, Throwable t, boolean system) {
// We've already emitted to logs, so there's nothing more to do here,
// as we don't have a DropBox pipeline configured
}
/**
* Set the default {@link ApplicationWtfHandler}, in case the ActivityManager is not ready yet.
*/
......
......@@ -36,6 +36,13 @@ public class LogTest {
private static final String PROPERTY_TAG = "log.tag.LogTest";
private static final String LOG_TAG = "LogTest";
@Test
public void testWtf() {
Log.wtf(LOG_TAG, "Message");
Log.wtf(LOG_TAG, "Message", new Throwable("Throwable"));
Log.wtf(LOG_TAG, new Throwable("Throwable"));
}
@Test
@Ignore
public void testIsLoggable() {
......
......@@ -44,4 +44,11 @@ public class SlogTest {
Slog.w(TAG, MSG, THROWABLE);
Slog.e(TAG, MSG, THROWABLE);
}
@Test
public void testWtf() {
Slog.wtf(TAG, MSG);
Slog.wtf(TAG, MSG, THROWABLE);
Slog.wtf(TAG, THROWABLE);
}
}
......@@ -24,6 +24,8 @@ import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.os.RuntimeInit;
import org.junit.runner.Description;
import java.io.PrintStream;
......@@ -53,6 +55,8 @@ public class RavenwoodRuleImpl {
}
public static void init(RavenwoodRule rule) {
RuntimeInit.redirectLogStreams();
android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
android.os.Binder.init$ravenwood();
android.os.SystemProperties.init$ravenwood(
......
......@@ -5,6 +5,7 @@ com.android.internal.util.ArrayUtils
com.android.internal.logging.MetricsLogger
com.android.internal.logging.testing.FakeMetricsLogger
com.android.internal.logging.testing.UiEventLoggerFake
com.android.internal.os.AndroidPrintStream
com.android.internal.os.BatteryStatsHistory
com.android.internal.os.BatteryStatsHistory$TraceDelegate
com.android.internal.os.BatteryStatsHistory$VarintParceler
......@@ -16,6 +17,7 @@ com.android.internal.os.MonotonicClock
com.android.internal.os.PowerProfile
com.android.internal.os.PowerStats
com.android.internal.os.PowerStats$Descriptor
com.android.internal.os.RuntimeInit
com.android.internal.power.ModemPowerProfile
android.util.AtomicFile
......
......@@ -15,9 +15,9 @@
*/
package com.android.hoststubgen.nativesubstitution;
import android.util.Log;
import android.util.Log.Level;
import com.android.internal.os.RuntimeInit;
import java.io.PrintStream;
import java.util.Collection;
public class EventLog_host {
......@@ -54,7 +54,7 @@ public class EventLog_host {
}
}
sb.append(']');
System.out.println(sb.toString());
getRealOut().println(sb.toString());
return sb.length();
}
......@@ -66,4 +66,16 @@ public class EventLog_host {
Collection<android.util.EventLog.Event> output) {
throw new UnsupportedOperationException();
}
/**
* Return the "real" {@code System.out} if it's been swapped by {@code RavenwoodRuleImpl}, so
* that we don't end up in a recursive loop.
*/
private static PrintStream getRealOut() {
if (RuntimeInit.sOut$ravenwood != null) {
return RuntimeInit.sOut$ravenwood;
} else {
return System.out;
}
}
}
......@@ -18,6 +18,8 @@ package com.android.hoststubgen.nativesubstitution;
import android.util.Log;
import android.util.Log.Level;
import com.android.internal.os.RuntimeInit;
import java.io.PrintStream;
public class Log_host {
......@@ -27,7 +29,6 @@ public class Log_host {
}
public static int println_native(int bufID, int priority, String tag, String msg) {
final PrintStream out = System.out;
final String buffer;
switch (bufID) {
case Log.LOG_ID_MAIN: buffer = "main"; break;
......@@ -50,7 +51,7 @@ public class Log_host {
};
for (String s : msg.split("\\n")) {
out.println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s));
getRealOut().println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s));
}
return msg.length();
}
......@@ -58,4 +59,16 @@ public class Log_host {
public static int logger_entry_max_payload_native() {
return 4068; // [ravenwood] This is what people use in various places.
}
/**
* Return the "real" {@code System.out} if it's been swapped by {@code RavenwoodRuleImpl}, so
* that we don't end up in a recursive loop.
*/
private static PrintStream getRealOut() {
if (RuntimeInit.sOut$ravenwood != null) {
return RuntimeInit.sOut$ravenwood;
} else {
return System.out;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment