adbd: add runtime-configurable logging.

Add some requested logging options that can be turned on at runtime
without having to restart adbd.

Bug: http://b/141959374
Test: manual
Change-Id: Ib97acc6d199e0b91238a6758e18b7cb75f8688d9
diff --git a/Android.bp b/Android.bp
index fea8c78..50e3727 100644
--- a/Android.bp
+++ b/Android.bp
@@ -375,6 +375,7 @@
     srcs: libadb_srcs + libadb_linux_srcs + libadb_posix_srcs + [
         "daemon/auth.cpp",
         "daemon/jdwp_service.cpp",
+        "daemon/logging.cpp",
         "daemon/adb_wifi.cpp",
     ],
 
diff --git a/adb.cpp b/adb.cpp
index 554a754..98db191 100644
--- a/adb.cpp
+++ b/adb.cpp
@@ -34,6 +34,7 @@
 #include <condition_variable>
 #include <mutex>
 #include <string>
+#include <string_view>
 #include <thread>
 #include <vector>
 
@@ -61,6 +62,8 @@
 #include <sys/mount.h>
 #include <android-base/properties.h>
 using namespace std::chrono_literals;
+
+#include "daemon/logging.h"
 #endif
 
 std::string adb_version() {
@@ -312,6 +315,9 @@
 #if ADB_HOST
     handle_online(t);
 #else
+    ADB_LOG(Connection) << "received CNXN: version=" << p->msg.arg0 << ", maxdata = " << p->msg.arg1
+                        << ", banner = '" << banner << "'";
+
     if (t->use_tls) {
         // We still handshake in TLS mode. If auth_required is disabled,
         // we'll just not verify the client's certificate. This should be the
diff --git a/daemon/logging.cpp b/daemon/logging.cpp
new file mode 100644
index 0000000..203c6c7
--- /dev/null
+++ b/daemon/logging.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 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 "daemon/logging.h"
+
+#include <mutex>
+#include <optional>
+#include <string_view>
+
+#include <android-base/no_destructor.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
+
+#if defined(__ANDROID__)
+struct LogStatus {
+    bool enabled[static_cast<size_t>(adb::LogType::COUNT)];
+
+    bool& operator[](adb::LogType type) { return enabled[static_cast<size_t>(type)]; }
+};
+
+using android::base::CachedProperty;
+using android::base::NoDestructor;
+
+static NoDestructor<std::mutex> log_mutex;
+static NoDestructor<CachedProperty> log_property GUARDED_BY(log_mutex)("debug.adbd.logging");
+static std::optional<LogStatus> cached_log_status GUARDED_BY(log_mutex);
+
+static NoDestructor<CachedProperty> persist_log_property
+        GUARDED_BY(log_mutex)("persist.debug.adbd.logging");
+static std::optional<LogStatus> cached_persist_log_status GUARDED_BY(log_mutex);
+
+static LogStatus ParseLogStatus(std::string_view str) {
+    LogStatus result = {};
+    for (const auto& part : android::base::Split(std::string(str), ",")) {
+        if (part == "cnxn") {
+            result[adb::LogType::Connection] = true;
+        } else if (part == "service") {
+            result[adb::LogType::Service] = true;
+        } else if (part == "shell") {
+            result[adb::LogType::Shell] = true;
+        } else if (part == "all") {
+            result[adb::LogType::Connection] = true;
+            result[adb::LogType::Service] = true;
+            result[adb::LogType::Shell] = true;
+        }
+    }
+    return result;
+}
+
+static LogStatus GetLogStatus(android::base::CachedProperty* property,
+                              std::optional<LogStatus>* cached_status) REQUIRES(log_mutex) {
+    bool changed;
+    const char* value = property->Get(&changed);
+    if (changed || !*cached_status) {
+        **cached_status = ParseLogStatus(value);
+    }
+    return **cached_status;
+}
+
+namespace adb {
+bool is_logging_enabled(LogType type) {
+    std::lock_guard<std::mutex> lock(*log_mutex);
+    return GetLogStatus(log_property.get(), &cached_log_status)[type] ||
+           GetLogStatus(persist_log_property.get(), &cached_persist_log_status)[type];
+}
+}  // namespace adb
+
+#else
+
+namespace adb {
+bool is_logging_enabled(LogType type) {
+    return false;
+}
+}  // namespace adb
+#endif
diff --git a/daemon/logging.h b/daemon/logging.h
new file mode 100644
index 0000000..3e28bef
--- /dev/null
+++ b/daemon/logging.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+
+namespace adb {
+enum class LogType {
+    Connection,
+    Service,
+    Shell,
+    COUNT,
+};
+
+bool is_logging_enabled(LogType type);
+
+#define ADB_LOG(type) ::adb::is_logging_enabled(::adb::LogType::type) && LOG(INFO)
+
+}  // namespace adb
diff --git a/daemon/services.cpp b/daemon/services.cpp
index 4ec90d2..6bbf66e 100644
--- a/daemon/services.cpp
+++ b/daemon/services.cpp
@@ -54,10 +54,10 @@
 
 #include "daemon/file_sync_service.h"
 #include "daemon/framebuffer_service.h"
+#include "daemon/logging.h"
 #include "daemon/restart_service.h"
 #include "daemon/shell_service.h"
 
-
 void reconnect_service(unique_fd fd, atransport* t) {
     WriteFdExactly(fd.get(), "done");
     kick_transport(t);
@@ -259,6 +259,8 @@
 }
 
 unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
+    ADB_LOG(Service) << "transport " << transport->serial_name() << " opening service " << name;
+
 #if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
     if (name.starts_with("abb:") || name.starts_with("abb_exec:")) {
         return execute_abb_command(name);
diff --git a/daemon/shell_service.cpp b/daemon/shell_service.cpp
index f62032d..fbfae1e 100644
--- a/daemon/shell_service.cpp
+++ b/daemon/shell_service.cpp
@@ -107,6 +107,7 @@
 #include "adb_trace.h"
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
+#include "daemon/logging.h"
 #include "security_log_tags.h"
 #include "shell_protocol.h"
 
@@ -760,14 +761,14 @@
             D("post waitpid (pid=%d) status=%04x", pid_, status);
             if (WIFSIGNALED(status)) {
                 exit_code = 0x80 | WTERMSIG(status);
-                D("subprocess killed by signal %d", WTERMSIG(status));
+                ADB_LOG(Shell) << "subprocess " << pid_ << " killed by signal " << WTERMSIG(status);
                 break;
             } else if (!WIFEXITED(status)) {
                 D("subprocess didn't exit");
                 break;
             } else if (WEXITSTATUS(status) >= 0) {
                 exit_code = WEXITSTATUS(status);
-                D("subprocess exit code = %d", WEXITSTATUS(status));
+                ADB_LOG(Shell) << "subprocess " << pid_ << " exited with status " << exit_code;
                 break;
             }
         }