/* * Copyright (C) 2015 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. */ #include "sysdeps.h" #include "adb_trace.h" #include <string> #include <unordered_map> #include <vector> #include <android-base/logging.h> #include <android-base/strings.h> #include "adb.h" #if !ADB_HOST #include <android-base/properties.h> #endif #if !ADB_HOST const char* adb_device_banner = "device"; static android::base::LogdLogger gLogdLogger; #else const char* adb_device_banner = "host"; #endif void AdbLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag, const char* file, unsigned int line, const char* message) { android::base::StderrLogger(id, severity, tag, file, line, message); #if !ADB_HOST // Only print logs of INFO or higher to logcat, so that `adb logcat` with adbd tracing on // doesn't result in exponential logging. if (severity >= android::base::INFO) { gLogdLogger(id, severity, tag, file, line, message); } #endif } #if !ADB_HOST static std::string get_log_file_name() { struct tm now; time_t t; tzset(); time(&t); localtime_r(&t, &now); char timestamp[PATH_MAX]; strftime(timestamp, sizeof(timestamp), "%Y-%m-%d-%H-%M-%S", &now); return android::base::StringPrintf("/data/adb/adb-%s-%d", timestamp, getpid()); } void start_device_log(void) { int fd = unix_open(get_log_file_name().c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640); if (fd == -1) { return; } // Redirect stdout and stderr to the log file. dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid()); unix_close(fd); } #endif int adb_trace_mask; std::string get_trace_setting_from_env() { const char* setting = getenv("ADB_TRACE"); if (setting == nullptr) { setting = ""; } return std::string(setting); } std::string get_trace_setting() { #if ADB_HOST return get_trace_setting_from_env(); #else return android::base::GetProperty("persist.adb.trace_mask", ""); #endif } // Split the space separated list of tags from the trace setting and build the // trace mask from it. note that '1' and 'all' are special cases to enable all // tracing. // // adb's trace setting comes from the ADB_TRACE environment variable, whereas // adbd's comes from the system property persist.adb.trace_mask. static void setup_trace_mask() { const std::string trace_setting = get_trace_setting(); if (trace_setting.empty()) { return; } std::unordered_map<std::string, int> trace_flags = { {"1", -1}, {"all", -1}, {"adb", ADB}, {"sockets", SOCKETS}, {"packets", PACKETS}, {"rwx", RWX}, {"usb", USB}, {"sync", SYNC}, {"sysdeps", SYSDEPS}, {"transport", TRANSPORT}, {"jdwp", JDWP}, {"services", SERVICES}, {"auth", AUTH}, {"fdevent", FDEVENT}, {"shell", SHELL}}; std::vector<std::string> elements = android::base::Split(trace_setting, " "); for (const auto& elem : elements) { const auto& flag = trace_flags.find(elem); if (flag == trace_flags.end()) { LOG(ERROR) << "Unknown trace flag: " << elem; continue; } if (flag->second == -1) { // -1 is used for the special values "1" and "all" that enable all // tracing. adb_trace_mask = ~0; break; } else { adb_trace_mask |= 1 << flag->second; } } if (adb_trace_mask != 0) { android::base::SetMinimumLogSeverity(android::base::VERBOSE); } } void adb_trace_init(char** argv) { #if !ADB_HOST // Don't open log file if no tracing, since this will block // the crypto unmount of /data if (!get_trace_setting().empty()) { if (unix_isatty(STDOUT_FILENO) == 0) { start_device_log(); } } #endif #if ADB_HOST && !defined(_WIN32) // adb historically ignored $ANDROID_LOG_TAGS but passed it through to logcat. // If set, move it out of the way so that libbase logging doesn't try to parse it. std::string log_tags; char* ANDROID_LOG_TAGS = getenv("ANDROID_LOG_TAGS"); if (ANDROID_LOG_TAGS) { log_tags = ANDROID_LOG_TAGS; unsetenv("ANDROID_LOG_TAGS"); } #endif android::base::InitLogging(argv, &AdbLogger); #if ADB_HOST && !defined(_WIN32) // Put $ANDROID_LOG_TAGS back so we can pass it to logcat. if (!log_tags.empty()) setenv("ANDROID_LOG_TAGS", log_tags.c_str(), 1); #endif setup_trace_mask(); VLOG(ADB) << adb_version(); } void adb_trace_enable(AdbTrace trace_tag) { adb_trace_mask |= (1 << trace_tag); }