| /* | |
| * 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"; | |
| #if defined(__ANDROID__) | |
| static android::base::LogdLogger gLogdLogger; | |
| #endif | |
| #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 defined(_WIN32) | |
| // stderr can be buffered on Windows (and setvbuf doesn't seem to work), so explicitly flush. | |
| fflush(stderr); | |
| #endif | |
| #if !ADB_HOST && defined(__ANDROID__) | |
| // 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(), 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); | |
| } |