Merge "fastboot: add UDP protocol."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 58ccd0a..cb54d04 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -883,8 +883,6 @@
fprintf(stderr, "ADB server didn't ACK\n" );
return -1;
}
-
- setsid();
}
#endif /* !defined(_WIN32) */
return 0;
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 6397c52..27b7109 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -127,10 +127,12 @@
setup_daemon_logging();
#if !defined(_WIN32)
- // Set the process group so that ctrl-c in the spawning process doesn't kill us.
- // Do this here instead of after the fork so that a ctrl-c between the "starting server" and
- // "done starting server" messages gets a chance to terminate the server.
- setpgrp();
+ // Start a new session for the daemon. Do this here instead of after the fork so
+ // that a ctrl-c between the "starting server" and "done starting server" messages
+ // gets a chance to terminate the server.
+ if (setsid() == -1) {
+ fatal("setsid() failed: %s", strerror(errno));
+ }
#endif
// Any error output written to stderr now goes to adb.log. We could
diff --git a/bootstat/Android.mk b/bootstat/Android.mk
index bbb903d..c6349c1 100644
--- a/bootstat/Android.mk
+++ b/bootstat/Android.mk
@@ -32,6 +32,7 @@
bootstat_shared_libs := \
libbase \
+ libcutils \
liblog
bootstat_cflags := \
diff --git a/bootstat/README.md b/bootstat/README.md
index 1b4bf7f..b3964ce 100644
--- a/bootstat/README.md
+++ b/bootstat/README.md
@@ -7,10 +7,11 @@
Usage: bootstat [options]
options include:
- -d Dump the boot event records to the console.
- -h Show this help.
- -l Log all metrics to logstorage.
- -r Record the relative time of a named boot event.
+ -h, --help Show this help
+ -l, --log Log all metrics to logstorage
+ -p, --print Dump the boot event records to the console
+ -r, --record Record the timestamp of a named boot event
+ --record_boot_reason Record the reason why the device booted
## Relative time ##
diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp
index 1bdcf2b..22a67bb 100644
--- a/bootstat/boot_event_record_store.cpp
+++ b/bootstat/boot_event_record_store.cpp
@@ -56,19 +56,31 @@
LOG(ERROR) << "Failed to read /proc/uptime";
}
+ // Cast intentionally rounds down.
+ int32_t uptime = static_cast<int32_t>(strtod(uptime_str.c_str(), NULL));
+ AddBootEventWithValue(name, uptime);
+}
+
+// The implementation of AddBootEventValue makes use of the mtime file
+// attribute to store the value associated with a boot event in order to
+// optimize on-disk size requirements and small-file thrashing.
+void BootEventRecordStore::AddBootEventWithValue(
+ const std::string& name, int32_t value) {
std::string record_path = GetBootEventPath(name);
if (creat(record_path.c_str(), S_IRUSR | S_IWUSR) == -1) {
PLOG(ERROR) << "Failed to create " << record_path;
}
+ // Fill out the stat structure for |record_path| in order to get the atime to
+ // set in the utime() call.
struct stat file_stat;
if (stat(record_path.c_str(), &file_stat) == -1) {
PLOG(ERROR) << "Failed to read " << record_path;
}
- // Cast intentionally rounds down.
- time_t uptime = static_cast<time_t>(strtod(uptime_str.c_str(), NULL));
- struct utimbuf times = {file_stat.st_atime, uptime};
+ // Set the |modtime| of the file to store the value of the boot event while
+ // preserving the |actime| (as read by stat).
+ struct utimbuf times = {/* actime */ file_stat.st_atime, /* modtime */ value};
if (utime(record_path.c_str(), ×) == -1) {
PLOG(ERROR) << "Failed to set mtime for " << record_path;
}
diff --git a/bootstat/boot_event_record_store.h b/bootstat/boot_event_record_store.h
index 77978ef..d1b7835 100644
--- a/bootstat/boot_event_record_store.h
+++ b/bootstat/boot_event_record_store.h
@@ -37,6 +37,10 @@
// Persists the boot event named |name| in the record store.
void AddBootEvent(const std::string& name);
+ // Persists the boot event named |name| with the associated |value| in the
+ // record store.
+ void AddBootEventWithValue(const std::string& name, int32_t value);
+
// Returns a list of all of the boot events persisted in the record store.
std::vector<BootEventRecord> GetAllBootEvents() const;
@@ -45,6 +49,7 @@
// more test-friendly path.
FRIEND_TEST(BootEventRecordStoreTest, AddSingleBootEvent);
FRIEND_TEST(BootEventRecordStoreTest, AddMultipleBootEvents);
+ FRIEND_TEST(BootEventRecordStoreTest, AddBootEventWithValue);
// Sets the filesystem path of the record store.
void SetStorePath(const std::string& path);
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index 384f84d..3e6d706 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -154,3 +154,15 @@
EXPECT_TRUE(FuzzUptimeEquals(uptime, *i));
}
}
+
+TEST_F(BootEventRecordStoreTest, AddBootEventWithValue) {
+ BootEventRecordStore store;
+ store.SetStorePath(GetStorePathForTesting());
+
+ store.AddBootEventWithValue("permian", 42);
+
+ auto events = store.GetAllBootEvents();
+ ASSERT_EQ(1U, events.size());
+ EXPECT_EQ("permian", events[0].first);
+ EXPECT_EQ(42, events[0].second);
+}
\ No newline at end of file
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index a83f8ad..31c84c7 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -18,14 +18,15 @@
// timestamp, dump the persisted events, and log all events to EventLog to be
// uploaded to Android log storage via Tron.
-//#define LOG_TAG "bootstat"
-
+#include <getopt.h>
#include <unistd.h>
#include <cstddef>
#include <cstdio>
+#include <map>
#include <memory>
#include <string>
#include <android-base/logging.h>
+#include <cutils/properties.h>
#include <log/log.h>
#include "boot_event_record_store.h"
#include "event_log_list_builder.h"
@@ -35,7 +36,7 @@
// Builds an EventLog buffer named |event| containing |data| and writes
// the log into the Tron histogram logs.
void LogBootEvent(const std::string& event, int32_t data) {
- LOG(INFO) << "Logging boot time: " << event << " " << data;
+ LOG(INFO) << "Logging boot metric: " << event << " " << data;
EventLogListBuilder log_builder;
log_builder.Append(event);
@@ -74,10 +75,11 @@
fprintf(stderr, "Usage: %s [options]\n", cmd);
fprintf(stderr,
"options include:\n"
- " -d Dump the boot event records to the console.\n"
- " -h Show this help.\n"
- " -l Log all metrics to logstorage.\n"
- " -r Record the timestamp of a named boot event.\n");
+ " -h, --help Show this help\n"
+ " -l, --log Log all metrics to logstorage\n"
+ " -p, --print Dump the boot event records to the console\n"
+ " -r, --record Record the timestamp of a named boot event\n"
+ " --record_boot_reason Record the reason why the device booted\n");
}
// Constructs a readable, printable string from the givencommand line
@@ -92,6 +94,61 @@
return cmd;
}
+// Convenience wrapper over the property API that returns an
+// std::string.
+std::string GetProperty(const char* key) {
+ std::vector<char> temp(PROPERTY_VALUE_MAX);
+ const int len = property_get(key, &temp[0], nullptr);
+ if (len < 0) {
+ return "";
+ }
+ return std::string(&temp[0], len);
+}
+
+// A mapping from boot reason string, as read from the ro.boot.bootreason
+// system property, to a unique integer ID. Viewers of log data dashboards for
+// the boot_reason metric may refer to this mapping to discern the histogram
+// values.
+const std::map<std::string, int> kBootReasonMap = {
+ {"normal", 0},
+ {"recovery", 1},
+ {"reboot", 2},
+ {"PowerKey", 3},
+ {"hard_reset", 4},
+ {"kernel_panic", 5},
+ {"rpm_err", 6},
+ {"hw_reset", 7},
+ {"tz_err", 8},
+ {"adsp_err", 9},
+ {"modem_err", 10},
+ {"mba_err", 11},
+ {"Watchdog", 12},
+ {"Panic", 13},
+};
+
+// Converts a string value representing the reason the system booted to an
+// integer representation. This is necessary for logging the boot_reason metric
+// via Tron, which does not accept non-integer buckets in histograms.
+int32_t BootReasonStrToEnum(const std::string& boot_reason) {
+ static const int32_t kUnknownBootReason = -1;
+
+ auto mapping = kBootReasonMap.find(boot_reason);
+ if (mapping != kBootReasonMap.end()) {
+ return mapping->second;
+ }
+
+ LOG(INFO) << "Unknown boot reason: " << boot_reason;
+ return kUnknownBootReason;
+}
+
+// Records the boot_reason metric by querying the ro.boot.bootreason system
+// property.
+void RecordBootReason() {
+ int32_t boot_reason = BootReasonStrToEnum(GetProperty("ro.boot.bootreason"));
+ BootEventRecordStore boot_event_store;
+ boot_event_store.AddBootEventWithValue("boot_reason", boot_reason);
+}
+
} // namespace
int main(int argc, char **argv) {
@@ -100,9 +157,31 @@
const std::string cmd_line = GetCommandLine(argc, argv);
LOG(INFO) << "Service started: " << cmd_line;
+ int option_index = 0;
+ static const char boot_reason_str[] = "record_boot_reason";
+ static const struct option long_options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "log", no_argument, NULL, 'l' },
+ { "print", no_argument, NULL, 'p' },
+ { "record", required_argument, NULL, 'r' },
+ { boot_reason_str, no_argument, NULL, 0 },
+ { NULL, 0, NULL, 0 }
+ };
+
int opt = 0;
- while ((opt = getopt(argc, argv, "hlpr:")) != -1) {
+ while ((opt = getopt_long(argc, argv, "hlpr:", long_options, &option_index)) != -1) {
switch (opt) {
+ // This case handles long options which have no single-character mapping.
+ case 0: {
+ const std::string option_name = long_options[option_index].name;
+ if (option_name == boot_reason_str) {
+ RecordBootReason();
+ } else {
+ LOG(ERROR) << "Invalid option: " << option_name;
+ }
+ break;
+ }
+
case 'h': {
ShowHelp(argv[0]);
break;
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index 2c37dd2..218b9f8 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -10,5 +10,8 @@
# Record boot_complete timing event.
exec - root root -- /system/bin/bootstat -r boot_complete
+ # Record the boot reason.
+ exec - root root -- /system/bin/bootstat --record_boot_reason
+
# Log all boot events.
exec - root root -- /system/bin/bootstat -l
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 8517c9f..8d9c5a3 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -224,7 +224,8 @@
msgBuf,
sizeof(msgBuf)));
fflush(stderr);
- EXPECT_EQ(31, android_log_printLogLine(logformat, fileno(stderr), &entry));
+ EXPECT_EQ((int)(19 + sizeof(buffer)),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
android_log_format_free(logformat);
}
}
@@ -272,7 +273,7 @@
}
int len = get4LE(eventData + 4 + 1);
- if (len == 0) {
+ if (len == (sizeof(buffer) - 1)) {
++count;
AndroidLogFormat *logformat = android_log_format_new();
@@ -285,7 +286,8 @@
msgBuf,
sizeof(msgBuf)));
fflush(stderr);
- EXPECT_EQ(20, android_log_printLogLine(logformat, fileno(stderr), &entry));
+ EXPECT_EQ((int)(19 + sizeof(buffer)),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
android_log_format_free(logformat);
}
}
@@ -295,6 +297,119 @@
android_logger_list_close(logger_list);
}
+TEST(liblog, __android_log_bswrite__newline_prefix) {
+ struct logger_list *logger_list;
+
+ pid_t pid = getpid();
+
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
+
+ static const char buffer[] = "\nHello World\n";
+ log_time ts(android_log_clockid());
+
+ ASSERT_LT(0, __android_log_bswrite(0, buffer));
+ usleep(1000000);
+
+ int count = 0;
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+ break;
+ }
+
+ ASSERT_EQ(log_msg.entry.pid, pid);
+
+ if ((log_msg.entry.sec < (ts.tv_sec - 1))
+ || ((ts.tv_sec + 1) < log_msg.entry.sec)
+ || (log_msg.entry.len != (4 + 1 + 4 + sizeof(buffer) - 1))
+ || (log_msg.id() != LOG_ID_EVENTS)) {
+ continue;
+ }
+
+ char *eventData = log_msg.msg();
+
+ if (eventData[4] != EVENT_TYPE_STRING) {
+ continue;
+ }
+
+ int len = get4LE(eventData + 4 + 1);
+ if (len == (sizeof(buffer) - 1)) {
+ ++count;
+
+ AndroidLogFormat *logformat = android_log_format_new();
+ EXPECT_TRUE(NULL != logformat);
+ AndroidLogEntry entry;
+ char msgBuf[1024];
+ EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
+ &entry,
+ NULL,
+ msgBuf,
+ sizeof(msgBuf)));
+ fflush(stderr);
+ EXPECT_EQ((int)(19 + 19 - 1 + sizeof(buffer)),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
+ android_log_format_free(logformat);
+ }
+ }
+
+ EXPECT_EQ(1, count);
+
+ android_logger_list_close(logger_list);
+}
+
+TEST(liblog, __android_log_buf_write__newline_prefix) {
+ struct logger_list *logger_list;
+
+ pid_t pid = getpid();
+
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
+
+ static const char tag[] = "TEST__android_log_buf_write";
+ static const char buffer[] = "\nHello World\n";
+ log_time ts(android_log_clockid());
+
+ EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
+ tag, buffer));
+ usleep(1000000);
+
+ int count = 0;
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+ break;
+ }
+
+ ASSERT_EQ(log_msg.entry.pid, pid);
+
+ if ((log_msg.entry.sec < (ts.tv_sec - 1))
+ || ((ts.tv_sec + 1) < log_msg.entry.sec)
+ || (log_msg.entry.len != (sizeof(tag) + sizeof(buffer) + 1))
+ || (log_msg.id() != LOG_ID_MAIN)) {
+ continue;
+ }
+
+ ++count;
+
+ AndroidLogFormat *logformat = android_log_format_new();
+ EXPECT_TRUE(NULL != logformat);
+ AndroidLogEntry entry;
+ EXPECT_EQ(0, android_log_processLogBuffer(&log_msg.entry_v1,
+ &entry));
+ fflush(stderr);
+ EXPECT_EQ((int)(11 + 11 + sizeof(tag) + sizeof(tag) + sizeof(buffer) - 3),
+ android_log_printLogLine(logformat, fileno(stderr), &entry));
+ android_log_format_free(logformat);
+ }
+
+ EXPECT_EQ(1, count);
+
+ android_logger_list_close(logger_list);
+}
+
TEST(liblog, __security) {
static const char persist_key[] = "persist.logd.security";
static const char readonly_key[] = "ro.device_owner";
@@ -609,7 +724,7 @@
EXPECT_GT(one_percent_ticks, user_ticks + system_ticks);
}
-static const char max_payload_tag[] = "TEST_max_payload_XXXX";
+static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
#define SIZEOF_MAX_PAYLOAD_BUF (LOGGER_ENTRY_MAX_PAYLOAD - \
sizeof(max_payload_tag) - 1)
static const char max_payload_buf[] = "LEONATO\n\
diff --git a/logcat/logpersist b/logcat/logpersist
index dab466d..8762ff1 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -1,8 +1,8 @@
#! /system/bin/sh
# logpersist cat start and stop handlers
progname="${0##*/}"
-case `getprop ro.build.type` in
-userdebug|eng) ;;
+case `getprop ro.debuggable` in
+1) ;;
*) echo "${progname} - Permission denied"
exit 1
;;
diff --git a/logd/README.property b/logd/README.property
index 22f86b9..6200d3e 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -8,7 +8,7 @@
ro.device_owner bool false Override persist.logd.security to false
ro.logd.kernel bool+ svelte+ Enable klogd daemon
ro.logd.statistics bool+ svelte+ Enable logcat -S statistics.
-ro.build.type string if user, logd.statistics &
+ro.debuggable number if not "1", logd.statistics &
ro.logd.kernel default false.
persist.logd.logpersistd string Enable logpersist daemon, "logcatd"
turns on logcat -f in logd context
@@ -46,10 +46,10 @@
NB:
- bool+ - "true", "false" and comma separated list of "eng" (forced false if
- ro.build.type is "user") or "svelte" (forced false if ro.config.low_ram is
+ ro.debuggable is not "1") or "svelte" (forced false if ro.config.low_ram is
true).
- svelte - see ro.config.low_ram for details.
-- svelte+ - see ro.config.low_ram and ro.build.type for details.
+- svelte+ - see ro.config.low_ram and ro.debuggable for details.
- ro - <base property> temporary override, ro.<base property> platform default.
- persist - <base property> override, persist.<base property> platform default.
- build - VERBOSE for native, DEBUG for jvm isLoggable, or developer option.
diff --git a/logd/main.cpp b/logd/main.cpp
index 9cec313..bef40c7 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -202,8 +202,8 @@
return false;
}
if (flag & BOOL_DEFAULT_FLAG_ENG) {
- property_get("ro.build.type", property, "");
- if (!strcmp(property, "user")) {
+ property_get("ro.debuggable", property, "");
+ if (strcmp(property, "1")) {
return false;
}
}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 52716e9..9ade759 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -80,10 +80,16 @@
$(LOCAL_PATH)/getevent.c: $(intermediates)/input.h-labels.h
+UAPI_INPUT_EVENT_CODES_H := bionic/libc/kernel/uapi/linux/input-event-codes.h
INPUT_H_LABELS_H := $(intermediates)/input.h-labels.h
$(INPUT_H_LABELS_H): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
-$(INPUT_H_LABELS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/generate-input.h-labels.py > $@
-$(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py
+# The PRIVATE_CUSTOM_TOOL line uses = to evaluate the output path late.
+# We copy the input path so it can't be accidentally modified later.
+$(INPUT_H_LABELS_H): PRIVATE_UAPI_INPUT_EVENT_CODES_H := $(UAPI_INPUT_EVENT_CODES_H)
+$(INPUT_H_LABELS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/generate-input.h-labels.py $(PRIVATE_UAPI_INPUT_EVENT_CODES_H) > $@
+# The dependency line though gets evaluated now, so the PRIVATE_ copy doesn't exist yet,
+# and the original can't yet have been modified, so this is both sufficient and necessary.
+$(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py $(UAPI_INPUT_EVENT_CODES_H)
$(INPUT_H_LABELS_H):
$(transform-generated-source)
diff --git a/toolbox/generate-input.h-labels.py b/toolbox/generate-input.h-labels.py
index ebb9588..30485a0 100755
--- a/toolbox/generate-input.h-labels.py
+++ b/toolbox/generate-input.h-labels.py
@@ -18,6 +18,7 @@
import os
import re
+import sys
input_prop_list = []
ev_list = []
@@ -36,7 +37,7 @@
r = re.compile(r'#define\s+(\S+)\s+((?:0x)?\d+)')
-with open('bionic/libc/kernel/uapi/linux/input.h', 'r') as f:
+with open(sys.argv[1], 'r') as f:
for line in f:
m = r.match(line)
if m: