Support ANDROID_LOG_TAGS.
This is the dalvik-compatible solution to the "I don't want non-FATAL logging
in my test output" problem.
Change-Id: I51b7b883ce89604af4661696e7c7b041a0ef8211
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 6017ddb..47193e5 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -422,7 +422,7 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
};
-bool ParseInt(const char* in, int* out) {
+static bool ParseInt(const char* in, int* out) {
char* end;
int result = strtol(in, &end, 10);
if (in == end || *end != '\0') {
@@ -432,9 +432,9 @@
return true;
}
-void OpenDexFiles(const std::vector<const char*>& dex_filenames,
- const std::vector<const char*>& dex_locations,
- std::vector<const DexFile*>& dex_files) {
+static void OpenDexFiles(const std::vector<const char*>& dex_filenames,
+ const std::vector<const char*>& dex_locations,
+ std::vector<const DexFile*>& dex_files) {
for (size_t i = 0; i < dex_filenames.size(); i++) {
const char* dex_filename = dex_filenames[i];
const char* dex_location = dex_locations[i];
@@ -447,7 +447,9 @@
}
}
-int dex2oat(int argc, char** argv) {
+static int dex2oat(int argc, char** argv) {
+ InitLogging();
+
// Skip over argv[0].
argv++;
argc--;
diff --git a/src/logging.cc b/src/logging.cc
index b0f3055..7d176a2 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -24,12 +24,55 @@
LogVerbosity gLogVerbosity;
+static bool gInitLoggingCalled = false;
+static LogSeverity gMinimumLogSeverity = INFO;
+
static Mutex& GetLoggingLock() {
static Mutex logging_lock("LogMessage lock");
return logging_lock;
}
+// Configure logging based on ANDROID_LOG_TAGS environment variable.
+// We need to parse a string that looks like
+//
+// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
+//
+// The tag (or '*' for the global level) comes first, followed by a colon
+// and a letter indicating the minimum priority level we're expected to log.
+// This can be used to reveal or conceal logs with specific tags.
+void InitLogging() {
+ gInitLoggingCalled = true;
+ const char* tags = getenv("ANDROID_LOG_TAGS");
+ if (tags == NULL) {
+ return;
+ }
+
+ std::vector<std::string> specs;
+ Split(tags, ' ', specs);
+ for (size_t i = 0; i < specs.size(); ++i) {
+ // "tag-pattern:[vdiwefs]"
+ std::string spec(specs[i]);
+ if (spec.size() == 3 && StartsWith(spec, "*:")) {
+ switch (spec[2]) {
+ case 'v': gMinimumLogSeverity = VERBOSE; continue;
+ case 'd': gMinimumLogSeverity = DEBUG; continue;
+ case 'i': gMinimumLogSeverity = INFO; continue;
+ case 'w': gMinimumLogSeverity = WARNING; continue;
+ case 'e': gMinimumLogSeverity = ERROR; continue;
+ case 'f': gMinimumLogSeverity = FATAL; continue;
+ // liblog will even suppress FATAL if you say 's' for silent, but that's crazy!
+ case 's': gMinimumLogSeverity = FATAL; continue;
+ }
+ }
+ LOG(FATAL) << "unsupported '" << spec << "' in ANDROID_LOG_TAGS (" << tags << ")";
+ }
+}
+
LogMessage::~LogMessage() {
+ if (data_->severity < gMinimumLogSeverity) {
+ return; // No need to format something we're not going to output.
+ }
+
// Finish constructing the message.
if (data_->error != -1) {
data_->buffer << ": " << strerror(data_->error);
diff --git a/src/logging.h b/src/logging.h
index c1ea3ab..337f12e 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -262,18 +262,10 @@
bool startup;
bool third_party_jni; // Enabled with "-verbose:third-party-jni".
bool threads;
- std::ostream* logging_stream;
-
- void SetLoggingStream(std::ostream* new_logging_stream) {
- DCHECK(new_logging_stream->good());
- if (logging_stream != NULL) {
- delete logging_stream;
- }
- logging_stream = new_logging_stream;
- }
};
extern LogVerbosity gLogVerbosity;
+extern void InitLogging();
} // namespace art
diff --git a/src/logging_linux.cc b/src/logging_linux.cc
index 4e7c796..84a6843 100644
--- a/src/logging_linux.cc
+++ b/src/logging_linux.cc
@@ -34,11 +34,10 @@
}
void LogMessage::LogLine(const char* message) {
- std::ostream &out =
- (gLogVerbosity.logging_stream == NULL ? std::cerr : *gLogVerbosity.logging_stream);
- out << "VDIWEFF"[data_->severity] << ' '
- << StringPrintf("%5d %5d", getpid(), ::art::GetTid()) << ' '
- << data_->file << ':' << data_->line_number << "] " << message << std::endl;
+ std::ostream& os(std::cerr);
+ os << "VDIWEFF"[data_->severity] << ' '
+ << StringPrintf("%5d %5d", getpid(), ::art::GetTid()) << ' '
+ << data_->file << ':' << data_->line_number << "] " << message << std::endl;
}
} // namespace art
diff --git a/src/oatdump.cc b/src/oatdump.cc
index ea2e711..28126ae 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -1234,7 +1234,9 @@
DISALLOW_COPY_AND_ASSIGN(ImageDumper);
};
-int oatdump(int argc, char** argv) {
+static int oatdump(int argc, char** argv) {
+ InitLogging();
+
// Skip over argv[0].
argv++;
argc--;
diff --git a/src/oatexec.cc b/src/oatexec.cc
index 4f068db..d080560 100644
--- a/src/oatexec.cc
+++ b/src/oatexec.cc
@@ -105,7 +105,8 @@
// Parse arguments. Most of it just gets passed through to the runtime.
// The JNI spec defines a handful of standard arguments.
-int oatexec(int argc, char** argv) {
+static int oatexec(int argc, char** argv) {
+ InitLogging();
setvbuf(stdout, NULL, _IONBF, 0);
// Skip over argv[0].
diff --git a/src/runtime.cc b/src/runtime.cc
index 18d40f5..a94a93a 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -22,7 +22,6 @@
#include <cstdlib>
#include <limits>
#include <vector>
-#include <fstream>
#include "class_linker.h"
#include "class_loader.h"
@@ -432,15 +431,6 @@
gLogVerbosity.third_party_jni = true;
} else if (verbose_options[i] == "threads") {
gLogVerbosity.threads = true;
- } else if (StartsWith(verbose_options[i], "log-to=")) {
- std::string log_file_name(verbose_options[i].substr(strlen("log-to=")));
- std::ofstream* log_file = new std::ofstream(log_file_name.c_str());
- if (log_file->is_open() && log_file->good()) {
- gLogVerbosity.SetLoggingStream(log_file);
- } else {
- LOG(ERROR) << "Fail to open log file: \"" << log_file_name << "\","
- << " use default logging stream.";
- }
} else {
LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i];
}
diff --git a/test/etc/host-run-test-jar b/test/etc/host-run-test-jar
index b892ce9..30a6721 100755
--- a/test/etc/host-run-test-jar
+++ b/test/etc/host-run-test-jar
@@ -60,8 +60,6 @@
msg "------------------------------"
DATA_DIR=/tmp
-DEBUG_OPTS="-Xcheck:jni"
-
if [ ! -d $DATA_DIR/art-cache ]; then
mkdir -p $DATA_DIR/art-cache
[[ $? -ne 0 ]] && exit
@@ -82,11 +80,9 @@
if [ "$DEBUG" = "y" ]; then
PORT=8000
- msg "Waiting for debugger to connect on localhost:$PORT"
- # This is for jdb:
- DEX_DEBUG="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
- # Connect thus:
- # jdb -attach localhost:12345
+ msg "Waiting for jdb to connect:"
+ msg " jdb -attach localhost:$PORT"
+ DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
fi
if [ "$GDB" = "y" ]; then
@@ -94,7 +90,9 @@
gdbargs="--args $exe"
fi
+JNI_OPTS="-Xjnigreflimit:256 -Xcheck:jni"
+
cd $ANDROID_BUILD_TOP
$INVOKE_WITH $gdb $exe $gdbargs -Ximage:$ANDROID_ROOT/framework/core.art \
- $DEBUG_OPTS $DEX_DEBUG -verbose:log-to=$DEX_LOCATION/log.txt\
+ $JNI_OPTS $DEBUG_OPTS \
-cp $DEX_LOCATION/$TEST_NAME.jar Main "$@"
diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar
index c892309..31c368d 100755
--- a/test/etc/push-and-run-test-jar
+++ b/test/etc/push-and-run-test-jar
@@ -105,18 +105,21 @@
fi
if [ "$DEBUG" = "y" ]; then
- # This is for ddms:
- #DEX_DEBUG="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
- # Connect by running 'ddms'.
+ # Use this instead for ddms and connect by running 'ddms':
+ # DEBUG_OPTS="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
+ # TODO: add a separate --ddms option?
- # This is for jdb:
- DEX_DEBUG="-agentlib:jdwp=transport=dt_socket,address=12345,server=y,suspend=y"
- # Connect thus:
- # adb forward tcp:12345 tcp:12345
- # jdb -attach localhost:12345
+ PORT=12345
+ msg "Waiting for jdb to connect:"
+ msg " adb forward tcp:$PORT tcp:$PORT"
+ msg " jdb -attach localhost:$PORT"
+ DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
fi
-cmdline="cd /data; export DEX_LOCATION=$DEX_LOCATION; $INVOKE_WITH $OATEXEC $DEX_DEBUG $ZYGOTE -Xjnigreflimit:256 \
+JNI_OPTS="-Xjnigreflimit:256 -Xcheck:jni"
+
+cmdline="cd /data; export DEX_LOCATION=$DEX_LOCATION; $INVOKE_WITH $OATEXEC $ZYGOTE \
+ $JNI_OPTS $DEBUG_OPTS \
-Ximage:/data/art-test/core.art \
-cp /data/run-test/$TEST_NAME.jar \
Main"
diff --git a/test/etc/reference-run-test-classes b/test/etc/reference-run-test-classes
index b16d9ff..0294cc2 100755
--- a/test/etc/reference-run-test-classes
+++ b/test/etc/reference-run-test-classes
@@ -53,7 +53,8 @@
if [ "$DEBUG" = "y" ]; then
PORT=8000
- msg "Waiting for debugger to connect on localhost:$PORT"
+ msg "Waiting for jdb to connect:"
+ msg " jdb -attach localhost:$PORT"
DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
fi