Merge "crash_reporter: Fix unit tests"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index c39c178..c03d7db 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -33,10 +33,10 @@
#include <string>
#include <vector>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include "adb_auth.h"
#include "adb_io.h"
diff --git a/adb/adb.h b/adb/adb.h
index 5187c81..774215e 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -22,7 +22,7 @@
#include <string>
-#include <base/macros.h>
+#include <android-base/macros.h>
#include "adb_trace.h"
#include "fdevent.h"
@@ -214,18 +214,23 @@
void local_connect(int port);
int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
-/* usb host/client interface */
+// USB host/client interface.
void usb_init();
int usb_write(usb_handle *h, const void *data, int len);
int usb_read(usb_handle *h, void *data, int len);
int usb_close(usb_handle *h);
void usb_kick(usb_handle *h);
-/* used for USB device detection */
+// USB device detection.
#if ADB_HOST
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
#endif
+// USB permission error help text. The short version will be one line, long may be multi-line.
+// Returns a string message to print, or an empty string if no problems could be found.
+std::string UsbNoPermissionsShortHelpText();
+std::string UsbNoPermissionsLongHelpText();
+
int adb_commandline(int argc, const char **argv);
ConnectionState connection_state(atransport *t);
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index 463b496..c4ffc85 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -228,13 +228,13 @@
static void adb_auth_listener(int fd, unsigned events, void *data)
{
- struct sockaddr addr;
+ sockaddr_storage addr;
socklen_t alen;
int s;
alen = sizeof(addr);
- s = adb_socket_accept(fd, &addr, &alen);
+ s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
if (s < 0) {
D("Failed to accept: errno=%d", errno);
return;
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index e11bff0..facacef 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -43,7 +43,7 @@
#include "mincrypt/rsa.h"
#undef RSA_verify
-#include <base/strings.h>
+#include <android-base/strings.h>
#include <cutils/list.h>
#include <openssl/evp.h>
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index ddeb5f1..cb5e488 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -31,8 +31,8 @@
#include <string>
#include <vector>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <cutils/sockets.h>
#include "adb_io.h"
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index a37fbc0..176b7bd 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -20,7 +20,7 @@
#include <unistd.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include "adb_trace.h"
#include "adb_utils.h"
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 6928a90..21a82e8 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -27,8 +27,8 @@
#include <string>
-#include "base/file.h"
-#include "base/test_utils.h"
+#include <android-base/file.h>
+#include <android-base/test_utils.h>
// All of these tests fail on Windows because they use the C Runtime open(),
// but the adb_io APIs expect file descriptors from adb_open(). This could
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 1b75090..e8c2338 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -19,7 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/sockets.h>
#include "sysdeps.h"
@@ -34,9 +34,10 @@
static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
if (ev & FDE_READ) {
- struct sockaddr addr;
- socklen_t alen = sizeof(addr);
- int fd = adb_socket_accept(_fd, &addr, &alen);
+ sockaddr_storage ss;
+ sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
+ socklen_t alen = sizeof(ss);
+ int fd = adb_socket_accept(_fd, addrp, &alen);
if (fd < 0) return;
int rcv_buf_size = CHUNK_SIZE;
@@ -58,12 +59,13 @@
asocket *s;
if (ev & FDE_READ) {
- struct sockaddr addr;
+ sockaddr_storage ss;
+ sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
socklen_t alen;
int fd;
- alen = sizeof(addr);
- fd = adb_socket_accept(_fd, &addr, &alen);
+ alen = sizeof(ss);
+ fd = adb_socket_accept(_fd, addrp, &alen);
if (fd < 0) {
return;
}
@@ -79,7 +81,7 @@
}
}
-static void free_listener(alistener* l)
+static void free_listener(alistener* l)
{
if (l->next) {
l->next->prev = l->prev;
diff --git a/adb/adb_trace.cpp b/adb/adb_trace.cpp
index cf99df7..62900c0 100644
--- a/adb/adb_trace.cpp
+++ b/adb/adb_trace.cpp
@@ -21,8 +21,8 @@
#include <unordered_map>
#include <vector>
-#include <base/logging.h>
-#include <base/strings.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
#include "adb.h"
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index 78b2deb..d50f947 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -17,8 +17,8 @@
#ifndef __ADB_TRACE_H
#define __ADB_TRACE_H
-#include <base/logging.h>
-#include <base/stringprintf.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
/* IMPORTANT: if you change the following list, don't
* forget to update the corresponding 'tags' table in
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 42f1c7d..3ed2a7d 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -26,9 +26,9 @@
#include <algorithm>
-#include <base/logging.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include "adb_trace.h"
#include "sysdeps.h"
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index 93c20cb..4508bca 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -30,8 +30,8 @@
#include "sysdeps.h"
-#include <base/macros.h>
-#include <base/test_utils.h>
+#include <android-base/macros.h>
+#include <android-base/test_utils.h>
#ifdef _WIN32
static std::string subdir(const char* parent, const char* child) {
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 04b9882..3ce5242 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -27,9 +27,9 @@
#include <sched.h>
#endif
-#include "base/file.h"
-#include "base/logging.h"
-#include "base/stringprintf.h"
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "adb.h"
#include "adb_auth.h"
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index bd3813e..d244f7d 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -35,9 +35,9 @@
#include <string>
#include <vector>
-#include <base/logging.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#if !defined(_WIN32)
#include <signal.h>
diff --git a/adb/console.cpp b/adb/console.cpp
index 5a9c6ab..15c6abd 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -18,9 +18,9 @@
#include <stdio.h>
-#include <base/file.h>
-#include <base/logging.h>
-#include <base/strings.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <cutils/sockets.h>
#include "adb.h"
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index f4e054e3..10c5296 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -25,8 +25,8 @@
#include <getopt.h>
#include <sys/prctl.h>
-#include "base/logging.h"
-#include "base/stringprintf.h"
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "cutils/properties.h"
#include "private/android_filesystem_config.h"
#include "selinux/selinux.h"
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 46547b9..25e8376 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -31,8 +31,8 @@
#include <unordered_map>
#include <vector>
-#include <base/logging.h>
-#include <base/stringprintf.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "adb_io.h"
#include "adb_trace.h"
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 9ad7bad..463c1c0 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -41,9 +41,9 @@
#include "file_sync_service.h"
#include "line_printer.h"
-#include <base/file.h>
-#include <base/strings.h>
-#include <base/stringprintf.h>
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <android-base/stringprintf.h>
struct syncsendbuf {
unsigned id;
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 945fa5a..781968b 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -35,8 +35,8 @@
#include "adb_utils.h"
#include "private/android_filesystem_config.h"
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
static bool should_use_fs_config(const std::string& path) {
// TODO: use fs_config to configure permissions on /data.
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index cc2d44e..3c812cc 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -460,11 +460,11 @@
const char* sockname,
int socknamelen )
{
- struct sockaddr_un addr;
- socklen_t addrlen;
- int s;
- int maxpath = sizeof(addr.sun_path);
- int pathlen = socknamelen;
+ sockaddr_un addr;
+ socklen_t addrlen;
+ int s;
+ int maxpath = sizeof(addr.sun_path);
+ int pathlen = socknamelen;
if (pathlen >= maxpath) {
D( "vm debug control socket name too long (%d extra chars)",
@@ -485,7 +485,7 @@
addrlen = (pathlen + sizeof(addr.sun_family));
- if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {
+ if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
D( "could not bind vm debug control socket: %d: %s",
errno, strerror(errno) );
adb_close(s);
@@ -523,13 +523,14 @@
JdwpControl* control = (JdwpControl*) _control;
if (events & FDE_READ) {
- struct sockaddr addr;
- socklen_t addrlen = sizeof(addr);
- int s = -1;
- JdwpProcess* proc;
+ sockaddr_storage ss;
+ sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
+ socklen_t addrlen = sizeof(ss);
+ int s = -1;
+ JdwpProcess* proc;
do {
- s = adb_socket_accept( control->listen_socket, &addr, &addrlen );
+ s = adb_socket_accept(control->listen_socket, addrp, &addrlen);
if (s < 0) {
if (errno == EINTR)
continue;
diff --git a/adb/services.cpp b/adb/services.cpp
index 41da4b8..523353a 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -31,9 +31,9 @@
#include <unistd.h>
#endif
-#include <base/file.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <cutils/sockets.h>
#if !ADB_HOST
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index 2e41fe6..6c06669 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -89,8 +89,8 @@
#include <memory>
-#include <base/logging.h>
-#include <base/stringprintf.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <paths.h>
#include "adb.h"
@@ -289,7 +289,6 @@
// TODO: $HOSTNAME? Normally bash automatically sets that, but mksh doesn't.
passwd* pw = getpwuid(getuid());
if (pw != nullptr) {
- setenv("HOME", pw->pw_dir, 1);
setenv("LOGNAME", pw->pw_name, 1);
setenv("SHELL", pw->pw_shell, 1);
setenv("USER", pw->pw_name, 1);
@@ -298,6 +297,8 @@
setenv("TERM", terminal_type_.c_str(), 1);
}
+ setenv("HOME", "/data/local/tmp", 1);
+ chdir(getenv("HOME"));
if (is_interactive()) {
execl(_PATH_BSHELL, _PATH_BSHELL, "-", nullptr);
} else {
diff --git a/adb/shell_service.h b/adb/shell_service.h
index 6f8ea9b..e3d676a 100644
--- a/adb/shell_service.h
+++ b/adb/shell_service.h
@@ -27,7 +27,7 @@
#include <stdint.h>
-#include <base/macros.h>
+#include <android-base/macros.h>
#include "adb.h"
diff --git a/adb/shell_service_test.cpp b/adb/shell_service_test.cpp
index a012f3e..c85232b 100644
--- a/adb/shell_service_test.cpp
+++ b/adb/shell_service_test.cpp
@@ -23,7 +23,7 @@
#include <string>
#include <vector>
-#include <base/strings.h>
+#include <android-base/strings.h>
#include "adb.h"
#include "adb_io.h"
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 22c9b39..2190c61 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -29,7 +29,7 @@
#include <string>
// Include this before open/unlink are defined as macros below.
-#include <base/utf8.h>
+#include <android-base/utf8.h>
/*
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 81dcb41..0a2a8f6 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -32,10 +32,10 @@
#include <cutils/sockets.h>
-#include <base/logging.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
-#include <base/utf8.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/utf8.h>
#include "adb.h"
diff --git a/adb/sysdeps_win32_test.cpp b/adb/sysdeps_win32_test.cpp
index 55b5eb4..81923cb 100755
--- a/adb/sysdeps_win32_test.cpp
+++ b/adb/sysdeps_win32_test.cpp
@@ -18,7 +18,7 @@
#include "sysdeps.h"
-#include "base/test_utils.h"
+#include <android-base/test_utils.h>
TEST(sysdeps_win32, adb_getenv) {
// Insert all test env vars before first call to adb_getenv() which will
diff --git a/adb/test_track_devices.cpp b/adb/test_track_devices.cpp
index 6f658f6..b10f8ee 100644
--- a/adb/test_track_devices.cpp
+++ b/adb/test_track_devices.cpp
@@ -9,7 +9,7 @@
#include <sys/socket.h>
#include <unistd.h>
-#include <base/file.h>
+#include <android-base/file.h>
static void
panic( const char* msg )
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 2f18f20..d4f60ec 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -29,9 +29,9 @@
#include <algorithm>
#include <list>
-#include <base/logging.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include "adb.h"
#include "adb_utils.h"
@@ -674,7 +674,11 @@
adb_mutex_lock(&transport_lock);
for (const auto& t : transport_list) {
if (t->connection_state == kCsNoPerm) {
- *error_out = "insufficient permissions for device";
+ *error_out = UsbNoPermissionsLongHelpText();
+ // If we couldn't figure out a reasonable help message default to something generic.
+ if (error_out->empty()) {
+ *error_out = "insufficient permissions for device";
+ }
continue;
}
@@ -748,17 +752,20 @@
return result;
}
-const char* atransport::connection_state_name() const {
+const std::string atransport::connection_state_name() const {
switch (connection_state) {
- case kCsOffline: return "offline";
- case kCsBootloader: return "bootloader";
- case kCsDevice: return "device";
- case kCsHost: return "host";
- case kCsRecovery: return "recovery";
- case kCsNoPerm: return "no permissions";
- case kCsSideload: return "sideload";
- case kCsUnauthorized: return "unauthorized";
- default: return "unknown";
+ case kCsOffline: return "offline";
+ case kCsBootloader: return "bootloader";
+ case kCsDevice: return "device";
+ case kCsHost: return "host";
+ case kCsRecovery: return "recovery";
+ case kCsNoPerm: {
+ std::string message = UsbNoPermissionsShortHelpText();
+ return message.empty() ? "no permissions" : message;
+ }
+ case kCsSideload: return "sideload";
+ case kCsUnauthorized: return "unauthorized";
+ default: return "unknown";
}
}
@@ -866,7 +873,8 @@
*result += '\t';
*result += t->connection_state_name();
} else {
- android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
+ android::base::StringAppendF(result, "%-22s %s", serial,
+ t->connection_state_name().c_str());
append_transport_info(result, "", t->devpath, false);
append_transport_info(result, "product:", t->product, false);
diff --git a/adb/transport.h b/adb/transport.h
index d9845b6..76d6afa 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -90,7 +90,7 @@
fdevent auth_fde;
size_t failed_auth_attempts = 0;
- const char* connection_state_name() const;
+ const std::string connection_state_name() const;
void update_version(int version, size_t payload);
int get_protocol_version() const;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index bf0cc3c..d2a375a 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -25,7 +25,7 @@
#include <string.h>
#include <sys/types.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/sockets.h>
#if !ADB_HOST
@@ -143,7 +143,8 @@
static void *server_socket_thread(void * arg)
{
int serverfd, fd;
- struct sockaddr addr;
+ sockaddr_storage ss;
+ sockaddr *addrp = reinterpret_cast<sockaddr*>(&ss);
socklen_t alen;
int port = (int) (uintptr_t) arg;
@@ -162,9 +163,9 @@
close_on_exec(serverfd);
}
- alen = sizeof(addr);
+ alen = sizeof(ss);
D("server: trying to get new connection from %d", port);
- fd = adb_socket_accept(serverfd, &addr, &alen);
+ fd = adb_socket_accept(serverfd, addrp, &alen);
if(fd >= 0) {
D("server: new connection on fd %d", fd);
close_on_exec(fd);
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 0358b62..e887a94 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -22,6 +22,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <grp.h>
#include <linux/usb/ch9.h>
#include <linux/usbdevice_fs.h>
#include <linux/version.h>
@@ -39,9 +40,9 @@
#include <mutex>
#include <string>
-#include <base/file.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include "adb.h"
#include "transport.h"
@@ -595,3 +596,54 @@
fatal_errno("cannot create device_poll thread");
}
}
+
+static const char kPermissionsHelpUrl[] = "developer.android.com/tools/device.html";
+
+// Returns a message describing any potential problems we find with udev, or nullptr if we can't
+// find plugdev information (i.e. udev is not installed).
+static const char* GetUdevProblem() {
+ errno = 0;
+ group* plugdev_group = getgrnam("plugdev");
+
+ if (plugdev_group == nullptr) {
+ if (errno != 0) {
+ D("failed to read plugdev group info: %s", strerror(errno));
+ }
+ // We can't give any generally useful advice here, just let the caller print the help URL.
+ return nullptr;
+ }
+
+ // getgroups(2) indicates that the group_member() may not check the egid so we check it
+ // additionally just to be sure.
+ if (group_member(plugdev_group->gr_gid) || getegid() == plugdev_group->gr_gid) {
+ // The user is in plugdev so the problem is likely with the udev rules.
+ return "verify udev rules";
+ }
+ return "udev requires plugdev group membership";
+}
+
+// Short help text must be a single line, and will look something like:
+// no permissions (reason); see <URL>
+std::string UsbNoPermissionsShortHelpText() {
+ std::string help_text = "no permissions";
+
+ const char* problem = GetUdevProblem();
+ if (problem != nullptr) {
+ help_text += android::base::StringPrintf(" (%s)", problem);
+ }
+
+ return android::base::StringPrintf("%s; see [%s]", help_text.c_str(), kPermissionsHelpUrl);
+}
+
+// Long help text can span multiple lines and should provide more detailed information.
+std::string UsbNoPermissionsLongHelpText() {
+ std::string header = "USB permission failure";
+
+ const char* problem = GetUdevProblem();
+ if (problem != nullptr) {
+ header += android::base::StringPrintf(": %s", problem);
+ }
+
+ return android::base::StringPrintf("%s.\nSee [%s] for more information.",
+ header.c_str(), kPermissionsHelpUrl);
+}
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 3495a71..c5e7452 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -456,56 +456,40 @@
return 0;
}
-static int bulk_write(int bulk_in, const uint8_t* buf, size_t length)
-{
- size_t count = 0;
-
- while (count < length) {
- int ret = adb_write(bulk_in, buf + count, length - count);
- if (ret < 0) return -1;
- count += ret;
- }
-
- D("[ bulk_write done fd=%d ]", bulk_in);
- return count;
-}
-
-static int usb_ffs_write(usb_handle* h, const void* data, int len)
-{
+static int usb_ffs_write(usb_handle* h, const void* data, int len) {
D("about to write (fd=%d, len=%d)", h->bulk_in, len);
- int n = bulk_write(h->bulk_in, reinterpret_cast<const uint8_t*>(data), len);
- if (n != len) {
- D("ERROR: fd = %d, n = %d: %s", h->bulk_in, n, strerror(errno));
- return -1;
+
+ // Writes larger than 16k fail on some devices (seed with 3.10.49-g209ea2f in particular).
+ const char* buf = static_cast<const char*>(data);
+ while (len > 0) {
+ int write_len = (len > 16384) ? 16384 : len;
+ int n = adb_write(h->bulk_in, buf, write_len);
+ if (n < 0) {
+ D("ERROR: fd = %d, n = %d: %s", h->bulk_in, n, strerror(errno));
+ return -1;
+ }
+ buf += n;
+ len -= n;
}
+
D("[ done fd=%d ]", h->bulk_in);
return 0;
}
-static int bulk_read(int bulk_out, uint8_t* buf, size_t length)
-{
- size_t count = 0;
+static int usb_ffs_read(usb_handle* h, void* data, int len) {
+ D("about to read (fd=%d, len=%d)", h->bulk_out, len);
- while (count < length) {
- int ret = adb_read(bulk_out, buf + count, length - count);
- if (ret < 0) {
- D("[ bulk_read failed fd=%d length=%zu count=%zu ]", bulk_out, length, count);
+ char* buf = static_cast<char*>(data);
+ while (len > 0) {
+ int n = adb_read(h->bulk_out, buf, len);
+ if (n < 0) {
+ D("ERROR: fd = %d, n = %d: %s", h->bulk_out, n, strerror(errno));
return -1;
}
- count += ret;
+ buf += n;
+ len -= n;
}
- return count;
-}
-
-static int usb_ffs_read(usb_handle* h, void* data, int len)
-{
- D("about to read (fd=%d, len=%d)", h->bulk_out, len);
- int n = bulk_read(h->bulk_out, reinterpret_cast<uint8_t*>(data), len);
- if (n != len) {
- D("ERROR: fd = %d, n = %d: %s", h->bulk_out, n, strerror(errno));
- return -1;
- }
D("[ done fd=%d ]", h->bulk_out);
return 0;
}
@@ -587,3 +571,12 @@
{
h->kick(h);
}
+
+// kCsNoPerm is a host-side issue, we can just ignore it here.
+std::string UsbNoPermissionsShortHelpText() {
+ return "";
+}
+
+std::string UsbNoPermissionsLongHelpText() {
+ return "";
+}
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index e0dcc756..f494795 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -29,8 +29,8 @@
#include <inttypes.h>
#include <stdio.h>
-#include <base/logging.h>
-#include <base/stringprintf.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "adb.h"
#include "transport.h"
@@ -552,3 +552,12 @@
handle->interface = 0;
}
}
+
+// kCsNoPerm is Linux-only.
+std::string UsbNoPermissionsShortHelpText() {
+ return "";
+}
+
+std::string UsbNoPermissionsLongHelpText() {
+ return "";
+}
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index 8d3501e..9124685 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -659,3 +659,12 @@
}
adb_mutex_unlock(&usb_lock);
}
+
+// kCsNoPerm is Linux-only.
+std::string UsbNoPermissionsShortHelpText() {
+ return "";
+}
+
+std::string UsbNoPermissionsLongHelpText() {
+ return "";
+}
diff --git a/base/file.cpp b/base/file.cpp
index 7b5e7b1..f444c0c 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/file.h"
+#include "android-base/file.h"
#include <errno.h>
#include <fcntl.h>
@@ -23,8 +23,8 @@
#include <string>
-#include "base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
-#include "base/utf8.h"
+#include "android-base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
+#include "android-base/utf8.h"
#define LOG_TAG "base.file"
#include "cutils/log.h"
#include "utils/Compat.h"
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 77b9268..1bf83a4 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/file.h"
+#include "android-base/file.h"
#include <gtest/gtest.h>
@@ -24,7 +24,7 @@
#include <string>
-#include "base/test_utils.h"
+#include "android-base/test_utils.h"
TEST(file, ReadFileToString_ENOENT) {
std::string s("hello");
diff --git a/base/include/base/file.h b/base/include/android-base/file.h
similarity index 100%
rename from base/include/base/file.h
rename to base/include/android-base/file.h
diff --git a/base/include/base/logging.h b/base/include/android-base/logging.h
similarity index 99%
rename from base/include/base/logging.h
rename to base/include/android-base/logging.h
index 30f6906..cd526d0 100644
--- a/base/include/base/logging.h
+++ b/base/include/android-base/logging.h
@@ -29,7 +29,7 @@
#include <memory>
#include <ostream>
-#include "base/macros.h"
+#include "android-base/macros.h"
namespace android {
namespace base {
diff --git a/base/include/base/macros.h b/base/include/android-base/macros.h
similarity index 100%
rename from base/include/base/macros.h
rename to base/include/android-base/macros.h
diff --git a/base/include/base/memory.h b/base/include/android-base/memory.h
similarity index 100%
rename from base/include/base/memory.h
rename to base/include/android-base/memory.h
diff --git a/base/include/base/parseint.h b/base/include/android-base/parseint.h
similarity index 100%
rename from base/include/base/parseint.h
rename to base/include/android-base/parseint.h
diff --git a/base/include/base/stringprintf.h b/base/include/android-base/stringprintf.h
similarity index 100%
rename from base/include/base/stringprintf.h
rename to base/include/android-base/stringprintf.h
diff --git a/base/include/base/strings.h b/base/include/android-base/strings.h
similarity index 100%
rename from base/include/base/strings.h
rename to base/include/android-base/strings.h
diff --git a/base/include/base/test_utils.h b/base/include/android-base/test_utils.h
similarity index 96%
rename from base/include/base/test_utils.h
rename to base/include/android-base/test_utils.h
index 402e0a5..3f6872c 100644
--- a/base/include/base/test_utils.h
+++ b/base/include/android-base/test_utils.h
@@ -19,7 +19,7 @@
#include <string>
-#include <base/macros.h>
+#include <android-base/macros.h>
class TemporaryFile {
public:
diff --git a/base/include/base/unique_fd.h b/base/include/android-base/unique_fd.h
similarity index 97%
rename from base/include/base/unique_fd.h
rename to base/include/android-base/unique_fd.h
index 4117775..d3b27ca 100644
--- a/base/include/base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -19,7 +19,7 @@
#include <unistd.h>
-#include <base/macros.h>
+#include <android-base/macros.h>
/* Container for a file descriptor that automatically closes the descriptor as
* it goes out of scope.
diff --git a/base/include/base/utf8.h b/base/include/android-base/utf8.h
similarity index 100%
rename from base/include/base/utf8.h
rename to base/include/android-base/utf8.h
diff --git a/base/logging.cpp b/base/logging.cpp
index 85f8b3f..a385902 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -18,7 +18,7 @@
#include <windows.h>
#endif
-#include "base/logging.h"
+#include "android-base/logging.h"
#include <libgen.h>
@@ -40,8 +40,8 @@
#include <mutex>
#endif
-#include "base/macros.h"
-#include "base/strings.h"
+#include "android-base/macros.h"
+#include "android-base/strings.h"
#include "cutils/threads.h"
// Headers for LogMessage::LogLine.
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 70f9952..3de42b7 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/logging.h"
+#include "android-base/logging.h"
#include <libgen.h>
@@ -25,9 +25,9 @@
#include <regex>
#include <string>
-#include "base/file.h"
-#include "base/stringprintf.h"
-#include "base/test_utils.h"
+#include "android-base/file.h"
+#include "android-base/stringprintf.h"
+#include "android-base/test_utils.h"
#include <gtest/gtest.h>
diff --git a/base/parseint_test.cpp b/base/parseint_test.cpp
index 8a11d29..6a3ba31 100644
--- a/base/parseint_test.cpp
+++ b/base/parseint_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/parseint.h"
+#include "android-base/parseint.h"
#include <gtest/gtest.h>
diff --git a/base/stringprintf.cpp b/base/stringprintf.cpp
index d55ff52..78e1e8d 100644
--- a/base/stringprintf.cpp
+++ b/base/stringprintf.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/stringprintf.h"
+#include "android-base/stringprintf.h"
#include <stdio.h>
diff --git a/base/stringprintf_test.cpp b/base/stringprintf_test.cpp
index 5cc2086..fc009b1 100644
--- a/base/stringprintf_test.cpp
+++ b/base/stringprintf_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/stringprintf.h"
+#include "android-base/stringprintf.h"
#include <gtest/gtest.h>
diff --git a/base/strings.cpp b/base/strings.cpp
index d687e3c..b8775df 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/strings.h"
+#include "android-base/strings.h"
#include <stdlib.h>
#include <string.h>
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index 5f67575..30ae29e 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "base/strings.h"
+#include "android-base/strings.h"
#include <gtest/gtest.h>
diff --git a/base/test_main.cpp b/base/test_main.cpp
index 546923d..7fa6a84 100644
--- a/base/test_main.cpp
+++ b/base/test_main.cpp
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
-#include "base/logging.h"
+#include "android-base/logging.h"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 22641e7..337ba7c 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "base/logging.h"
-#include "base/test_utils.h"
+#include "android-base/logging.h"
+#include "android-base/test_utils.h"
#include "utils/Compat.h" // For OS_PATH_SEPARATOR.
#include <fcntl.h>
diff --git a/base/utf8.cpp b/base/utf8.cpp
index 99f0f54..3cca700 100755
--- a/base/utf8.cpp
+++ b/base/utf8.cpp
@@ -16,13 +16,13 @@
#include <windows.h>
-#include "base/utf8.h"
+#include "android-base/utf8.h"
#include <fcntl.h>
#include <string>
-#include "base/logging.h"
+#include "android-base/logging.h"
namespace android {
namespace base {
diff --git a/base/utf8_test.cpp b/base/utf8_test.cpp
index 13f6431..dde7490 100755
--- a/base/utf8_test.cpp
+++ b/base/utf8_test.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "base/utf8.h"
+#include "android-base/utf8.h"
#include <gtest/gtest.h>
-#include "base/macros.h"
+#include "android-base/macros.h"
namespace android {
namespace base {
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 884d4d5..0afa895 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -518,11 +518,12 @@
ALOGI("debuggerd: starting\n");
for (;;) {
- sockaddr addr;
- socklen_t alen = sizeof(addr);
+ sockaddr_storage ss;
+ sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
+ socklen_t alen = sizeof(ss);
ALOGV("waiting for connection\n");
- int fd = accept(s, &addr, &alen);
+ int fd = accept(s, addrp, &alen);
if (fd < 0) {
ALOGV("accept failed: %s\n", strerror(errno));
continue;
diff --git a/debuggerd/elf_utils.cpp b/debuggerd/elf_utils.cpp
index 5ea03e7..3f0dbde 100644
--- a/debuggerd/elf_utils.cpp
+++ b/debuggerd/elf_utils.cpp
@@ -24,7 +24,7 @@
#include <string>
#include <backtrace/Backtrace.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <log/log.h>
#include "elf_utils.h"
diff --git a/debuggerd/test/dump_memory_test.cpp b/debuggerd/test/dump_memory_test.cpp
index 75e7028..2addd5d 100644
--- a/debuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/test/dump_memory_test.cpp
@@ -20,7 +20,7 @@
#include <string>
#include <gtest/gtest.h>
-#include <base/file.h>
+#include <android-base/file.h>
#include "BacktraceMock.h"
#include "log_fake.h"
diff --git a/debuggerd/test/log_fake.cpp b/debuggerd/test/log_fake.cpp
index d584a5e..e27e9f6 100644
--- a/debuggerd/test/log_fake.cpp
+++ b/debuggerd/test/log_fake.cpp
@@ -19,7 +19,7 @@
#include <string>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <log/log.h>
#include <log/logger.h>
diff --git a/debuggerd/test/tombstone_test.cpp b/debuggerd/test/tombstone_test.cpp
index d945d27..96b3a7a 100644
--- a/debuggerd/test/tombstone_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -20,7 +20,7 @@
#include <string>
#include <gtest/gtest.h>
-#include <base/file.h>
+#include <android-base/file.h>
#include "utility.h"
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index e283923..5f422e3 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -37,7 +37,7 @@
#include <private/android_filesystem_config.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <log/logger.h>
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index f5d6ec1..ce214f9 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -25,9 +25,9 @@
#include <sys/ptrace.h>
#include <sys/wait.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <backtrace/Backtrace.h>
-#include <base/file.h>
-#include <base/stringprintf.h>
#include <log/log.h>
const int SLEEP_TIME_USEC = 50000; // 0.05 seconds
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index a16d7dd..cc9f06c 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -44,13 +44,13 @@
#include <unistd.h>
#include <functional>
-#include <base/parseint.h>
-#include <base/strings.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
#include <sparse/sparse.h>
#include <ziparchive/zip_archive.h>
-#include <base/strings.h>
-#include <base/parseint.h>
+#include <android-base/strings.h>
+#include <android-base/parseint.h>
#include "bootimg_utils.h"
#include "fastboot.h"
diff --git a/fastboot/transport.h b/fastboot/transport.h
index 55a5abb..67d01f9 100644
--- a/fastboot/transport.h
+++ b/fastboot/transport.h
@@ -17,7 +17,7 @@
#ifndef TRANSPORT_H_
#define TRANSPORT_H_
-#include <base/macros.h>
+#include <android-base/macros.h>
// General interface to allow the fastboot protocol to be used over different
// types of transports.
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 6983b72..928d56c 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -29,7 +29,7 @@
#include <libgen.h>
#include <time.h>
-#include <base/file.h>
+#include <android-base/file.h>
#include <private/android_filesystem_config.h>
#include <cutils/properties.h>
#include <logwrap/logwrap.h>
diff --git a/gatekeeperd/SoftGateKeeper.h b/gatekeeperd/SoftGateKeeper.h
index c8010ca..8b15d72 100644
--- a/gatekeeperd/SoftGateKeeper.h
+++ b/gatekeeperd/SoftGateKeeper.h
@@ -25,7 +25,7 @@
#include <crypto_scrypt.h>
}
-#include <base/memory.h>
+#include <android-base/memory.h>
#include <UniquePtr.h>
#include <gatekeeper/gatekeeper.h>
@@ -180,4 +180,3 @@
}
#endif // SOFT_GATEKEEPER_H_
-
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 63904b6..0085a07 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -39,6 +39,7 @@
#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
#define FAKE_BATTERY_CAPACITY 42
#define FAKE_BATTERY_TEMPERATURE 424
+#define ALWAYS_PLUGGED_CAPACITY 100
namespace android {
@@ -211,6 +212,15 @@
mBatteryFixedTemperature :
getIntField(mHealthdConfig->batteryTemperaturePath);
+ // For devices which do not have battery and are always plugged
+ // into power souce.
+ if (mAlwaysPluggedDevice) {
+ props.chargerAcOnline = true;
+ props.batteryPresent = true;
+ props.batteryStatus = BATTERY_STATUS_CHARGING;
+ props.batteryHealth = BATTERY_HEALTH_GOOD;
+ }
+
const int SIZE = 128;
char buf[SIZE];
String8 btech;
@@ -593,8 +603,15 @@
closedir(dir);
}
- if (!mChargerNames.size())
+ // This indicates that there is no charger driver registered.
+ // Typically the case for devices which do not have a battery and
+ // and are always plugged into AC mains.
+ if (!mChargerNames.size()) {
KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
+ mBatteryFixedCapacity = ALWAYS_PLUGGED_CAPACITY;
+ mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
+ mAlwaysPluggedDevice = true;
+ }
if (!mBatteryDevicePresent) {
KLOG_WARNING(LOG_TAG, "No battery devices found\n");
hc->periodic_chores_interval_fast = -1;
diff --git a/healthd/BatteryMonitor.h b/healthd/BatteryMonitor.h
index 3425f27..a61171f 100644
--- a/healthd/BatteryMonitor.h
+++ b/healthd/BatteryMonitor.h
@@ -46,6 +46,7 @@
struct healthd_config *mHealthdConfig;
Vector<String8> mChargerNames;
bool mBatteryDevicePresent;
+ bool mAlwaysPluggedDevice;
int mBatteryFixedCapacity;
int mBatteryFixedTemperature;
struct BatteryProperties props;
diff --git a/include/log/logger.h b/include/log/logger.h
index c795253..b3928a7 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -11,6 +11,10 @@
#define _LIBS_LOG_LOGGER_H
#include <stdint.h>
+#ifdef __linux__
+#include <time.h> /* clockid_t definition */
+#endif
+
#include <log/log.h>
#include <log/log_read.h>
@@ -159,6 +163,8 @@
#define ANDROID_LOG_RDWR O_RDWR
#define ANDROID_LOG_ACCMODE O_ACCMODE
#define ANDROID_LOG_NONBLOCK O_NONBLOCK
+#define ANDROID_LOG_WRAP 0x40000000 /* Block until buffer about to wrap */
+#define ANDROID_LOG_WRAP_DEFAULT_TIMEOUT 7200 /* 2 hour default */
#define ANDROID_LOG_PSTORE 0x80000000
struct logger_list *android_logger_list_alloc(int mode,
@@ -183,7 +189,9 @@
pid_t pid);
#define android_logger_list_close android_logger_list_free
-char android_log_timestamp();
+#ifdef __linux__
+clockid_t android_log_clockid();
+#endif
/*
* log_id_t helpers
diff --git a/include/nativeloader/native_loader.h b/include/nativeloader/native_loader.h
new file mode 100644
index 0000000..18b7ba4
--- /dev/null
+++ b/include/nativeloader/native_loader.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#ifndef NATIVE_LOADER_H_
+#define NATIVE_LOADER_H_
+
+#include "jni.h"
+#include <stdint.h>
+
+namespace android {
+
+__attribute__((visibility("default")))
+void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
+ jobject class_loader, jstring library_path);
+
+}; // namespace android
+
+#endif // NATIVE_BRIDGE_H_
diff --git a/include/ziparchive/zip_writer.h b/include/ziparchive/zip_writer.h
index d996c4a..0efade8 100644
--- a/include/ziparchive/zip_writer.h
+++ b/include/ziparchive/zip_writer.h
@@ -17,7 +17,7 @@
#ifndef LIBZIPARCHIVE_ZIPWRITER_H_
#define LIBZIPARCHIVE_ZIPWRITER_H_
-#include "base/macros.h"
+#include "android-base/macros.h"
#include <utils/Compat.h>
#include <cstdio>
diff --git a/init/action.cpp b/init/action.cpp
index c6cbc2e..510ea89 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -18,8 +18,8 @@
#include <errno.h>
-#include <base/strings.h>
-#include <base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/stringprintf.h>
#include "builtins.h"
#include "error.h"
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index e1e0c48..5704d28 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -33,7 +33,7 @@
#include <string>
#include <vector>
-#include <base/file.h>
+#include <android-base/file.h>
#define LOG_ROOT "/data/bootchart"
#define LOG_STAT LOG_ROOT"/proc_stat.log"
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 36ecbb8..58dbce1 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -39,7 +39,7 @@
#include <selinux/label.h>
#include <fs_mgr.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/partition_utils.h>
#include <cutils/android_reboot.h>
#include <logwrap/logwrap.h>
diff --git a/init/init.cpp b/init/init.cpp
index 86aed9a..9f4f625 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -40,9 +40,9 @@
#include <selinux/label.h>
#include <selinux/android.h>
-#include <base/file.h>
-#include <base/stringprintf.h>
-#include <base/strings.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <cutils/android_reboot.h>
#include <cutils/fs.h>
#include <cutils/iosched_policy.h>
@@ -602,6 +602,7 @@
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
+ restorecon("/property_contexts");
restorecon_recursive("/sys");
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 5b8e27b..b44ca59 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -25,7 +25,7 @@
#include "service.h"
#include "util.h"
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
Parser::Parser() {
}
diff --git a/init/keyword_map.h b/init/keyword_map.h
index dc2357b..693d82a 100644
--- a/init/keyword_map.h
+++ b/init/keyword_map.h
@@ -20,7 +20,7 @@
#include <map>
#include <string>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
template <typename Function>
class KeywordMap {
diff --git a/init/log.cpp b/init/log.cpp
index eb5ec42..a72906b 100644
--- a/init/log.cpp
+++ b/init/log.cpp
@@ -22,7 +22,7 @@
#include <selinux/selinux.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
static void init_klog_vwrite(int level, const char* fmt, va_list ap) {
static const char* tag = basename(getprogname());
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 96b4a37..806608e 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -47,7 +47,7 @@
#include <selinux/label.h>
#include <fs_mgr.h>
-#include <base/file.h>
+#include <android-base/file.h>
#include "bootimg.h"
#include "property_service.h"
@@ -60,33 +60,13 @@
#define RECOVERY_MOUNT_POINT "/recovery"
static int persistent_properties_loaded = 0;
-static bool property_area_initialized = false;
static int property_set_fd = -1;
-struct workspace {
- size_t size;
- int fd;
-};
-
-static workspace pa_workspace;
-
void property_init() {
- if (property_area_initialized) {
- return;
- }
-
- property_area_initialized = true;
-
if (__system_property_area_init()) {
- return;
- }
-
- pa_workspace.size = 0;
- pa_workspace.fd = open(PROP_FILENAME, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
- if (pa_workspace.fd == -1) {
- ERROR("Failed to open %s: %s\n", PROP_FILENAME, strerror(errno));
- return;
+ ERROR("Failed to initialize property area\n");
+ exit(1);
}
}
@@ -353,12 +333,6 @@
}
}
-void get_property_workspace(int *fd, int *sz)
-{
- *fd = pa_workspace.fd;
- *sz = pa_workspace.size;
-}
-
static void load_properties_from_file(const char *, const char *);
/*
@@ -497,10 +471,6 @@
load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT, NULL);
}
-bool properties_initialized() {
- return property_area_initialized;
-}
-
static void load_override_properties() {
if (ALLOW_LOCAL_PROP_OVERRIDE) {
std::string debuggable = property_get("ro.debuggable");
diff --git a/init/property_service.h b/init/property_service.h
index 8b76d2b..dbaed34 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -32,10 +32,8 @@
extern void load_persist_props(void);
extern void load_system_props(void);
extern void start_property_service(void);
-void get_property_workspace(int *fd, int *sz);
std::string property_get(const char* name);
extern int property_set(const char *name, const char *value);
-extern bool properties_initialized();
-#endif /* _INIT_PROPERTY_H */
+#endif /* _INIT_PROPERTY_H */
diff --git a/init/service.cpp b/init/service.cpp
index a3c5ca4..40a4bc7 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -24,8 +24,8 @@
#include <selinux/selinux.h>
-#include <base/file.h>
-#include <base/stringprintf.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <cutils/android_reboot.h>
#include <cutils/sockets.h>
@@ -76,11 +76,6 @@
}
void Service::NotifyStateChange(const std::string& new_state) const {
- if (!properties_initialized()) {
- // If properties aren't available yet, we can't set them.
- return;
- }
-
if ((flags_ & SVC_EXEC) != 0) {
// 'exec' commands don't have properties tracking their state.
return;
@@ -400,14 +395,7 @@
pid_t pid = fork();
if (pid == 0) {
- int fd, sz;
-
umask(077);
- if (properties_initialized()) {
- get_property_workspace(&fd, &sz);
- std::string tmp = StringPrintf("%d,%d", dup(fd), sz);
- add_environment("ANDROID_PROPERTY_WORKSPACE", tmp.c_str());
- }
for (const auto& ei : envvars_) {
add_environment(ei.name.c_str(), ei.value.c_str());
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp
index 867abbc..e7d42cb 100644
--- a/init/signal_handler.cpp
+++ b/init/signal_handler.cpp
@@ -23,7 +23,7 @@
#include <sys/wait.h>
#include <unistd.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/android_reboot.h>
#include <cutils/list.h>
#include <cutils/sockets.h>
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 75924cb..249739b 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -22,7 +22,7 @@
#include <stdlib.h>
#include <string.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <private/android_filesystem_config.h>
#include <selinux/selinux.h>
diff --git a/init/util.cpp b/init/util.cpp
index c7d0314..aefdf8f 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -32,12 +32,12 @@
#include <sys/socket.h>
#include <sys/un.h>
-#include <base/file.h>
-#include <base/strings.h>
+#include <android-base/file.h>
+#include <android-base/strings.h>
/* for ANDROID_SOCKET_* */
#include <cutils/sockets.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <private/android_filesystem_config.h>
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 9c6742e..5d3dd86 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -68,6 +68,7 @@
# Use static llvm libraries on host to remove dependency on 32-bit llvm shared library
# which is not included in the prebuilt.
libbacktrace_static_libraries_host := \
+ libcutils \
libLLVMObject \
libLLVMBitReader \
libLLVMMC \
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 555e8cf..3c8f879 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -22,13 +22,11 @@
#include <string>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
-#include <cutils/threads.h>
-
#include "BacktraceLog.h"
#include "BacktraceOffline.h"
#include "thread_utils.h"
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index d339550..8e22366 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -29,8 +29,6 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
-#include <cutils/threads.h>
-
#include "BacktraceCurrent.h"
#include "BacktraceLog.h"
#include "ThreadEntry.h"
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index ce04817..23636db 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -42,7 +42,7 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/atomic.h>
#include <cutils/threads.h>
@@ -1461,4 +1461,3 @@
ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
}
#endif
-
diff --git a/libbacktrace/thread_utils.h b/libbacktrace/thread_utils.h
index df83581..9590657 100644
--- a/libbacktrace/thread_utils.h
+++ b/libbacktrace/thread_utils.h
@@ -19,6 +19,10 @@
#include <unistd.h>
+#if !defined(__ANDROID__)
+#include <cutils/threads.h>
+#endif
+
__BEGIN_DECLS
int tgkill(int tgid, int tid, int sig);
diff --git a/libcutils/socket_inaddr_any_server.c b/libcutils/socket_inaddr_any_server.c
index 7f0ccb8..e1b7d84 100644
--- a/libcutils/socket_inaddr_any_server.c
+++ b/libcutils/socket_inaddr_any_server.c
@@ -34,21 +34,21 @@
/* open listen() port on any interface */
int socket_inaddr_any_server(int port, int type)
{
- struct sockaddr_in addr;
+ struct sockaddr_in6 addr;
int s, n;
memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = htons(port);
+ addr.sin6_addr = in6addr_any;
- s = socket(AF_INET, type, 0);
- if(s < 0) return -1;
+ s = socket(AF_INET6, type, 0);
+ if (s < 0) return -1;
n = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n));
- if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
return -1;
}
diff --git a/liblog/README b/liblog/README
index f29ac04..df1e68c 100644
--- a/liblog/README
+++ b/liblog/README
@@ -116,6 +116,10 @@
code, otherwise the android_logger_list_read call will block for new
entries.
+ The ANDROID_LOG_WRAP mode flag to the android_logger_list_alloc_time
+ signals logd to quiesce the reader until the buffer is about to prune
+ at the start time then proceed to dumping content.
+
The ANDROID_LOG_PSTORE mode flag to the android_logger_open is used to
switch from the active logs to the persistent logs from before the last
reboot.
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index e128edb..7fc01d9 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -196,18 +196,18 @@
* rare, we can accept a trylock failure gracefully. Use a separate
* lock from is_loggable to keep contention down b/25563384.
*/
-static pthread_mutex_t lock_timestamp = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lock_clockid = PTHREAD_MUTEX_INITIALIZER;
-char android_log_timestamp()
+clockid_t android_log_clockid()
{
static struct cache r_time_cache = { NULL, -1, 0 };
static struct cache p_time_cache = { NULL, -1, 0 };
- char retval;
+ char c;
- if (pthread_mutex_trylock(&lock_timestamp)) {
+ if (pthread_mutex_trylock(&lock_clockid)) {
/* We are willing to accept some race in this context */
- if (!(retval = p_time_cache.c)) {
- retval = r_time_cache.c;
+ if (!(c = p_time_cache.c)) {
+ c = r_time_cache.c;
}
} else {
static uint32_t serial;
@@ -217,12 +217,12 @@
refresh_cache(&p_time_cache, "persist.logd.timestamp");
serial = current_serial;
}
- if (!(retval = p_time_cache.c)) {
- retval = r_time_cache.c;
+ if (!(c = p_time_cache.c)) {
+ c = r_time_cache.c;
}
- pthread_mutex_unlock(&lock_timestamp);
+ pthread_mutex_unlock(&lock_clockid);
}
- return tolower(retval ?: 'r');
+ return (tolower(c) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
}
diff --git a/liblog/log_read.c b/liblog/log_read.c
index cfc8a7a..fb86757 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -797,6 +797,14 @@
}
if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
+ if (logger_list->mode & ANDROID_LOG_WRAP) {
+ // ToDo: alternate API to allow timeout to be adjusted.
+ ret = snprintf(cp, remaining, " timeout=%u",
+ ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
+ ret = min(ret, remaining);
+ remaining -= ret;
+ cp += ret;
+ }
ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
logger_list->start.tv_sec,
logger_list->start.tv_nsec);
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 83c6dc2..11c6d9c 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -212,11 +212,7 @@
* };
*/
- if (android_log_timestamp() == 'm') {
- clock_gettime(CLOCK_MONOTONIC, &ts);
- } else {
- clock_gettime(CLOCK_REALTIME, &ts);
- }
+ clock_gettime(android_log_clockid(), &ts);
pmsg_header.magic = LOGGER_MAGIC;
pmsg_header.len = sizeof(pmsg_header) + sizeof(header);
diff --git a/liblog/logprint.c b/liblog/logprint.c
index ebf9786..40e13f4 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -203,7 +203,7 @@
p_ret->year_output = false;
p_ret->zone_output = false;
p_ret->epoch_output = false;
- p_ret->monotonic_output = android_log_timestamp() == 'm';
+ p_ret->monotonic_output = android_log_clockid() == CLOCK_MONOTONIC;
return p_ret;
}
@@ -500,14 +500,14 @@
}
if (msgEnd == -1) {
/* incoming message not null-terminated; force it */
- msgEnd = buf->len - 1;
+ msgEnd = buf->len - 1; /* may result in msgEnd < msgStart */
msg[msgEnd] = '\0';
}
entry->priority = msg[0];
entry->tag = msg + 1;
entry->message = msg + msgStart;
- entry->messageLen = msgEnd - msgStart;
+ entry->messageLen = (msgEnd < msgStart) ? 0 : (msgEnd - msgStart);
return 0;
}
@@ -1262,7 +1262,7 @@
nsec = entry->tv_nsec;
if (p_format->monotonic_output) {
// prevent convertMonotonic from being called if logd is monotonic
- if (android_log_timestamp() != 'm') {
+ if (android_log_clockid() != CLOCK_MONOTONIC) {
struct timespec time;
convertMonotonic(&time, entry);
now = time.tv_sec;
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index c987041..110f1eb 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -611,11 +611,11 @@
struct logger * logger;
EXPECT_TRUE(NULL != (logger = android_logger_open(logger_list, id)));
EXPECT_EQ(id, android_logger_get_id(logger));
+ EXPECT_LT(0, android_logger_get_log_size(logger));
/* crash buffer is allowed to be empty, that is actually healthy! */
- if (android_logger_get_log_size(logger) || strcmp("crash", name)) {
- EXPECT_LT(0, android_logger_get_log_size(logger));
+ if (android_logger_get_log_readable_size(logger) || strcmp("crash", name)) {
+ EXPECT_LT(0, android_logger_get_log_readable_size(logger));
}
- EXPECT_LT(0, android_logger_get_log_readable_size(logger));
EXPECT_LT(0, android_logger_get_log_version(logger));
}
diff --git a/libnativeloader/Android.mk b/libnativeloader/Android.mk
new file mode 100644
index 0000000..5e65c4c
--- /dev/null
+++ b/libnativeloader/Android.mk
@@ -0,0 +1,54 @@
+LOCAL_PATH:= $(call my-dir)
+
+NATIVE_LOADER_COMMON_SRC_FILES := \
+ native_loader.cpp
+
+# Shared library for target
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libnativeloader
+
+LOCAL_SRC_FILES:= $(NATIVE_LOADER_COMMON_SRC_FILES)
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libcutils
+LOCAL_STATIC_LIBRARIES := libbase
+LOCAL_CLANG := true
+LOCAL_CFLAGS += -Werror -Wall
+LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
+LOCAL_LDFLAGS := -ldl
+LOCAL_MULTILIB := both
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Shared library for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libnativeloader
+
+LOCAL_SRC_FILES:= $(NATIVE_LOADER_COMMON_SRC_FILES)
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libcutils
+LOCAL_STATIC_LIBRARIES := libbase
+LOCAL_CLANG := true
+LOCAL_CFLAGS += -Werror -Wall
+LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
+LOCAL_LDFLAGS := -ldl
+LOCAL_MULTILIB := both
+
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+# Static library for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libnativeloader
+
+LOCAL_SRC_FILES:= $(NATIVE_LOADER_COMMON_SRC_FILES)
+LOCAL_STATIC_LIBRARIES := libnativehelper libcutils liblog libbase
+LOCAL_CLANG := true
+LOCAL_CFLAGS += -Werror -Wall
+LOCAL_CPPFLAGS := -std=gnu++14 -fvisibility=hidden
+LOCAL_LDFLAGS := -ldl
+LOCAL_MULTILIB := both
+
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
new file mode 100644
index 0000000..654bcb8
--- /dev/null
+++ b/libnativeloader/native_loader.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 "nativeloader/native_loader.h"
+#include "ScopedUtfChars.h"
+
+#include <dlfcn.h>
+#ifdef __ANDROID__
+#include <android/dlext.h>
+#include "cutils/properties.h"
+#endif
+
+#include <algorithm>
+#include <vector>
+#include <string>
+#include <mutex>
+
+#include "android-base/macros.h"
+#include "android-base/strings.h"
+
+namespace android {
+
+#ifdef __ANDROID__
+// TODO(dimitry): move this to system properties.
+static const char* kPublicNativeLibraries = "libandroid.so:"
+ "libc.so:"
+ "libdl.so:"
+ "libEGL.so:"
+ "libGLESv1_CM.so:"
+ "libGLESv2.so:"
+ "libGLESv3.so:"
+ "libjnigraphics.so:"
+ "liblog.so:"
+ "libmediandk.so:"
+ "libm.so:"
+ "libOpenMAXAL.so:"
+ "libOpenSLES.so:"
+ "libstdc++.so:"
+ "libz.so";
+
+class LibraryNamespaces {
+ public:
+ LibraryNamespaces() : initialized_(false) { }
+
+ android_namespace_t* GetOrCreate(JNIEnv* env, jobject class_loader, jstring library_path) {
+ ScopedUtfChars libraryPath(env, library_path);
+
+ if (!initialized_ && !InitPublicNamespace(libraryPath.c_str())) {
+ return nullptr;
+ }
+
+ std::lock_guard<std::mutex> guard(mutex_);
+
+ auto it = FindNamespaceByClassLoader(env, class_loader);
+
+ if (it != namespaces_.end()) {
+ return it->second;
+ }
+
+ android_namespace_t* ns =
+ android_create_namespace("classloader-namespace",
+ nullptr,
+ libraryPath.c_str(),
+ true);
+
+ namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns));
+
+ return ns;
+ }
+
+ private:
+ bool InitPublicNamespace(const char* library_path) {
+ // Make sure all the public libraries are loaded
+ std::vector<std::string> sonames = android::base::Split(kPublicNativeLibraries, ":");
+ for (const auto& soname : sonames) {
+ if (dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr) {
+ return false;
+ }
+ }
+
+ // Some apps call dlopen from generated code unknown to linker in which
+ // case linker uses anonymous namespace. See b/25844435 for details.
+ initialized_ = android_init_namespaces(kPublicNativeLibraries, library_path);
+
+ return initialized_;
+ }
+
+ std::vector<std::pair<jweak, android_namespace_t*>>::const_iterator
+ FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
+ return std::find_if(namespaces_.begin(), namespaces_.end(),
+ [&](const std::pair<jweak, android_namespace_t*>& value) {
+ return env->IsSameObject(value.first, class_loader);
+ });
+ }
+
+ bool initialized_;
+ std::mutex mutex_;
+ std::vector<std::pair<jweak, android_namespace_t*>> namespaces_;
+
+ DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces);
+};
+
+static LibraryNamespaces* g_namespaces = new LibraryNamespaces;
+#endif
+
+
+void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
+ jobject class_loader, jstring library_path) {
+#if defined(__ANDROID__)
+ if (target_sdk_version == 0 || class_loader == nullptr) {
+ return dlopen(path, RTLD_NOW);
+ }
+
+ android_namespace_t* ns = g_namespaces->GetOrCreate(env, class_loader, library_path);
+
+ if (ns == nullptr) {
+ return nullptr;
+ }
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_namespace = ns;
+
+ return android_dlopen_ext(path, RTLD_NOW, &extinfo);
+#else
+ UNUSED(env, target_sdk_version, class_loader, library_path);
+ return dlopen(path, RTLD_NOW);
+#endif
+}
+
+}; // android namespace
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 3011ed7..168899c 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -199,13 +199,14 @@
continue;
}
if (mListen && FD_ISSET(mSock, &read_fds)) {
- struct sockaddr addr;
+ sockaddr_storage ss;
+ sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
socklen_t alen;
int c;
do {
- alen = sizeof(addr);
- c = accept(mSock, &addr, &alen);
+ alen = sizeof(ss);
+ c = accept(mSock, addrp, &alen);
SLOGV("%s got %d from accept", mSocketName, c);
} while (c < 0 && errno == EINTR);
if (c < 0) {
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 3d18f7c..07ef6cd 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -30,9 +30,9 @@
#include <memory>
#include <vector>
-#include "base/file.h"
-#include "base/macros.h" // TEMP_FAILURE_RETRY may or may not be in unistd
-#include "base/memory.h"
+#include "android-base/file.h"
+#include "android-base/macros.h" // TEMP_FAILURE_RETRY may or may not be in unistd
+#include "android-base/memory.h"
#include "log/log.h"
#include "utils/Compat.h"
#include "utils/FileMap.h"
diff --git a/libziparchive/zip_archive_common.h b/libziparchive/zip_archive_common.h
index 7f20d51..ca42509 100644
--- a/libziparchive/zip_archive_common.h
+++ b/libziparchive/zip_archive_common.h
@@ -17,7 +17,7 @@
#ifndef LIBZIPARCHIVE_ZIPARCHIVECOMMON_H_
#define LIBZIPARCHIVE_ZIPARCHIVECOMMON_H_
-#include "base/macros.h"
+#include "android-base/macros.h"
#include <inttypes.h>
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 32b1a38..cb0f410 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -23,7 +23,7 @@
#include <unistd.h>
#include <vector>
-#include <base/file.h>
+#include <android-base/file.h>
#include <gtest/gtest.h>
static std::string test_data_dir;
diff --git a/libziparchive/zip_writer_test.cc b/libziparchive/zip_writer_test.cc
index f752b7e..b7d1458 100644
--- a/libziparchive/zip_writer_test.cc
+++ b/libziparchive/zip_writer_test.cc
@@ -17,7 +17,7 @@
#include "ziparchive/zip_archive.h"
#include "ziparchive/zip_writer.h"
-#include <base/test_utils.h>
+#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <memory>
#include <vector>
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 7bbc811..50bf6a4 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -410,7 +410,8 @@
}
static void ctrl_connect_handler(uint32_t events __unused) {
- struct sockaddr addr;
+ struct sockaddr_storage ss;
+ struct sockaddr *addrp = (struct sockaddr *)&ss;
socklen_t alen;
struct epoll_event epev;
@@ -419,8 +420,8 @@
ctrl_dfd_reopened = 1;
}
- alen = sizeof(addr);
- ctrl_dfd = accept(ctrl_lfd, &addr, &alen);
+ alen = sizeof(ss);
+ ctrl_dfd = accept(ctrl_lfd, addrp, &alen);
if (ctrl_dfd < 0) {
ALOGE("lmkd control socket accept failed; errno=%d", errno);
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 4d7adf1..059916e 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -6,6 +6,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <math.h>
#include <sched.h>
#include <signal.h>
@@ -24,8 +25,8 @@
#include <memory>
#include <string>
-#include <base/file.h>
-#include <base/strings.h>
+#include <android-base/file.h>
+#include <android-base/strings.h>
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
@@ -256,13 +257,19 @@
" -s Set default filter to silent.\n"
" Like specifying filterspec '*:S'\n"
" -f <filename> Log to file. Default is stdout\n"
+ " --file=<filename>\n"
" -r <kbytes> Rotate log every kbytes. Requires -f\n"
+ " --rotate_kbytes=<kbytes>\n"
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
- " -v <format> Sets the log print format, where <format> is:\n\n"
+ " --rotate_count=<count>\n"
+ " -v <format> Sets the log print format, where <format> is:\n"
+ " --format=<format>\n"
" brief color epoch long monotonic printable process raw\n"
" tag thread threadtime time usec UTC year zone\n\n"
" -D print dividers between each log buffer\n"
+ " --dividers\n"
" -c clear (flush) the entire log and exit\n"
+ " --clear\n"
" -d dump the log and then exit (don't block)\n"
" -t <count> print only the most recent <count> lines (implies -d)\n"
" -t '<time>' print most recent lines since specified time (implies -d)\n"
@@ -271,22 +278,32 @@
" count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n"
" 'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format\n"
" -g get the size of the log's ring buffer and exit\n"
+ " --buffer_size\n"
+ " -G <size> set size of log ring buffer, may suffix with K or M.\n"
+ " --buffer_size=<size>\n"
" -L dump logs from prior to last reboot\n"
+ " --last\n"
" -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
- " 'events', 'crash' or 'all'. Multiple -b parameters are\n"
+ " --buffer=<buffer> 'events', 'crash' or 'all'. Multiple -b parameters are\n"
" allowed and results are interleaved. The default is\n"
" -b main -b system -b crash.\n"
" -B output the log in binary.\n"
+ " --binary\n"
" -S output statistics.\n"
- " -G <size> set size of log ring buffer, may suffix with K or M.\n"
+ " --statistics\n"
" -p print prune white and ~black list. Service is specified as\n"
- " UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n"
+ " --prune UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n"
" with ~, otherwise weighed for longevity if unadorned. All\n"
" other pruning activity is oldest first. Special case ~!\n"
" represents an automatic quicker pruning for the noisiest\n"
" UID as determined by the current statistics.\n"
" -P '<list> ...' set prune white and ~black list, using same format as\n"
- " printed above. Must be quoted.\n");
+ " --prune='<list> ...' printed above. Must be quoted.\n"
+ " --pid=<pid> Only prints logs from the given pid.\n"
+ // Check ANDROID_LOG_WRAP_DEFAULT_TIMEOUT value
+ " --wrap Sleep for 2 hours or when buffer about to wrap whichever\n"
+ " comes first. Improves efficiency of polling by providing\n"
+ " an about-to-wrap wakeup.\n");
fprintf(stderr,"\nfilterspecs are a series of \n"
" <tag>[:priority]\n\n"
@@ -348,15 +365,19 @@
static bool getSizeTArg(char *ptr, size_t *val, size_t min = 0,
size_t max = SIZE_MAX)
{
- char *endp;
- errno = 0;
- size_t ret = (size_t) strtoll(ptr, &endp, 0);
-
- if (endp[0] != '\0' || errno != 0 ) {
+ if (!ptr) {
return false;
}
- if (ret > max || ret < min) {
+ char *endp;
+ errno = 0;
+ size_t ret = (size_t)strtoll(ptr, &endp, 0);
+
+ if (endp[0] || errno) {
+ return false;
+ }
+
+ if ((ret > max) || (ret < min)) {
return false;
}
@@ -398,11 +419,9 @@
return retval;
}
- log_time now(CLOCK_REALTIME);
- bool monotonic = android_log_timestamp() == 'm';
- if (monotonic) {
- now = log_time(CLOCK_MONOTONIC);
- }
+ clockid_t clock_type = android_log_clockid();
+ log_time now(clock_type);
+ bool monotonic = clock_type == CLOCK_MONOTONIC;
std::string directory;
char *file = strrchr(outputFileName, '/');
@@ -499,6 +518,7 @@
struct logger_list *logger_list;
size_t tail_lines = 0;
log_time tail_time(log_time::EPOCH);
+ size_t pid = 0;
signal(SIGPIPE, exit);
@@ -512,13 +532,66 @@
for (;;) {
int ret;
- ret = getopt(argc, argv, ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:");
+ int option_index = 0;
+ static const char pid_str[] = "pid";
+ static const char wrap_str[] = "wrap";
+ static const struct option long_options[] = {
+ { "binary", no_argument, NULL, 'B' },
+ { "buffer", required_argument, NULL, 'b' },
+ { "buffer_size", optional_argument, NULL, 'g' },
+ { "clear", no_argument, NULL, 'c' },
+ { "dividers", no_argument, NULL, 'D' },
+ { "file", required_argument, NULL, 'f' },
+ { "format", required_argument, NULL, 'v' },
+ { "last", no_argument, NULL, 'L' },
+ { pid_str, required_argument, NULL, 0 },
+ { "prune", optional_argument, NULL, 'p' },
+ { "rotate_count", required_argument, NULL, 'n' },
+ { "rotate_kbytes", required_argument, NULL, 'r' },
+ { "statistics", no_argument, NULL, 'S' },
+ // support, but ignore and do not document, the optional argument
+ { wrap_str, optional_argument, NULL, 0 },
+ { NULL, 0, NULL, 0 }
+ };
+
+ ret = getopt_long(argc, argv, ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:",
+ long_options, &option_index);
if (ret < 0) {
break;
}
- switch(ret) {
+ switch (ret) {
+ case 0:
+ // One of the long options
+ if (long_options[option_index].name == pid_str) {
+ // ToDo: determine runtime PID_MAX?
+ if (!getSizeTArg(optarg, &pid, 1)) {
+ logcat_panic(true, "%s %s out of range\n",
+ long_options[option_index].name, optarg);
+ }
+ break;
+ }
+ if (long_options[option_index].name == wrap_str) {
+ mode |= ANDROID_LOG_WRAP |
+ ANDROID_LOG_RDONLY |
+ ANDROID_LOG_NONBLOCK;
+ // ToDo: implement API that supports setting a wrap timeout
+ size_t dummy = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
+ if (optarg && !getSizeTArg(optarg, &dummy, 1)) {
+ logcat_panic(true, "%s %s out of range\n",
+ long_options[option_index].name, optarg);
+ }
+ if (dummy != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) {
+ fprintf(stderr,
+ "WARNING: %s %u seconds, ignoring %zu\n",
+ long_options[option_index].name,
+ ANDROID_LOG_WRAP_DEFAULT_TIMEOUT, dummy);
+ }
+ break;
+ }
+ break;
+
case 's':
// default to all silent
android_log_addFilterRule(g_logformat, "*:s");
@@ -570,8 +643,11 @@
break;
case 'g':
- getLogSize = 1;
- break;
+ if (!optarg) {
+ getLogSize = 1;
+ break;
+ }
+ // FALLTHRU
case 'G': {
char *cp;
@@ -609,8 +685,11 @@
break;
case 'p':
- getPruneList = 1;
- break;
+ if (!optarg) {
+ getPruneList = 1;
+ break;
+ }
+ // FALLTHRU
case 'P':
setPruneList = optarg;
@@ -840,9 +919,9 @@
dev = devices;
if (tail_time != log_time::EPOCH) {
- logger_list = android_logger_list_alloc_time(mode, tail_time, 0);
+ logger_list = android_logger_list_alloc_time(mode, tail_time, pid);
} else {
- logger_list = android_logger_list_alloc(mode, tail_lines, 0);
+ logger_list = android_logger_list_alloc(mode, tail_lines, pid);
}
const char *openDeviceFail = NULL;
const char *clearFail = NULL;
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 153a3fd..61b020c 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -76,7 +76,7 @@
TEST(logcat, year) {
- if (android_log_timestamp() == 'm') {
+ if (android_log_clockid() == CLOCK_MONOTONIC) {
fprintf(stderr, "Skipping test, logd is monotonic time\n");
return;
}
@@ -147,7 +147,7 @@
TEST(logcat, tz) {
- if (android_log_timestamp() == 'm') {
+ if (android_log_clockid() == CLOCK_MONOTONIC) {
fprintf(stderr, "Skipping test, logd is monotonic time\n");
return;
}
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index eafa28f..c45111a 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -27,7 +27,7 @@
#include <string>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
#include <sysutils/SocketClient.h>
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index 823a842..bf650cd 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -27,13 +27,15 @@
unsigned long tail,
unsigned int logMask,
pid_t pid,
- uint64_t start) :
+ uint64_t start,
+ uint64_t timeout) :
mReader(reader),
mNonBlock(nonBlock),
mTail(tail),
mLogMask(logMask),
mPid(pid),
- mStart(start) {
+ mStart(start),
+ mTimeout(timeout) {
}
// runSocketCommand is called once for every open client on the
@@ -54,6 +56,10 @@
while(it != times.end()) {
entry = (*it);
if (entry->mClient == client) {
+ if (entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec) {
+ LogTimeEntry::unlock();
+ return;
+ }
entry->triggerReader_Locked();
if (entry->runningReader_Locked()) {
LogTimeEntry::unlock();
@@ -71,7 +77,8 @@
LogTimeEntry::unlock();
return;
}
- entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart);
+ entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask,
+ mPid, mStart, mTimeout);
times.push_front(entry);
}
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index 61c6858..e0f2212 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -32,6 +32,7 @@
unsigned int mLogMask;
pid_t mPid;
uint64_t mStart;
+ uint64_t mTimeout;
public:
FlushCommand(LogReader &mReader,
@@ -39,7 +40,8 @@
unsigned long tail = -1,
unsigned int logMask = -1,
pid_t pid = 0,
- uint64_t start = 1);
+ uint64_t start = 1,
+ uint64_t timeout = 0);
virtual void runSocketCommand(SocketClient *client);
static bool hasReadLogs(SocketClient *client);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index fd5c066..6770bb7 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -128,46 +128,62 @@
}
}
bool lastMonotonic = monotonic;
- monotonic = android_log_timestamp() == 'm';
- if (lastMonotonic == monotonic) {
- return;
+ monotonic = android_log_clockid() == CLOCK_MONOTONIC;
+ if (lastMonotonic != monotonic) {
+ //
+ // Fixup all timestamps, may not be 100% accurate, but better than
+ // throwing what we have away when we get 'surprised' by a change.
+ // In-place element fixup so no need to check reader-lock. Entries
+ // should already be in timestamp order, but we could end up with a
+ // few out-of-order entries if new monotonics come in before we
+ // are notified of the reinit change in status. A Typical example would
+ // be:
+ // --------- beginning of system
+ // 10.494082 184 201 D Cryptfs : Just triggered post_fs_data
+ // --------- beginning of kernel
+ // 0.000000 0 0 I : Initializing cgroup subsys
+ // as the act of mounting /data would trigger persist.logd.timestamp to
+ // be corrected. 1/30 corner case YMMV.
+ //
+ pthread_mutex_lock(&mLogElementsLock);
+ LogBufferElementCollection::iterator it = mLogElements.begin();
+ while((it != mLogElements.end())) {
+ LogBufferElement *e = *it;
+ if (monotonic) {
+ if (!android::isMonotonic(e->mRealTime)) {
+ LogKlog::convertRealToMonotonic(e->mRealTime);
+ }
+ } else {
+ if (android::isMonotonic(e->mRealTime)) {
+ LogKlog::convertMonotonicToReal(e->mRealTime);
+ }
+ }
+ ++it;
+ }
+ pthread_mutex_unlock(&mLogElementsLock);
}
+ // We may have been triggered by a SIGHUP. Release any sleeping reader
+ // threads to dump their current content.
//
- // Fixup all timestamps, may not be 100% accurate, but better than
- // throwing what we have away when we get 'surprised' by a change.
- // In-place element fixup so no need to check reader-lock. Entries
- // should already be in timestamp order, but we could end up with a
- // few out-of-order entries if new monotonics come in before we
- // are notified of the reinit change in status. A Typical example would
- // be:
- // --------- beginning of system
- // 10.494082 184 201 D Cryptfs : Just triggered post_fs_data
- // --------- beginning of kernel
- // 0.000000 0 0 I : Initializing cgroup subsys cpuacct
- // as the act of mounting /data would trigger persist.logd.timestamp to
- // be corrected. 1/30 corner case YMMV.
- //
- pthread_mutex_lock(&mLogElementsLock);
- LogBufferElementCollection::iterator it = mLogElements.begin();
- while((it != mLogElements.end())) {
- LogBufferElement *e = *it;
- if (monotonic) {
- if (!android::isMonotonic(e->mRealTime)) {
- LogKlog::convertRealToMonotonic(e->mRealTime);
- }
- } else {
- if (android::isMonotonic(e->mRealTime)) {
- LogKlog::convertMonotonicToReal(e->mRealTime);
- }
+ // NB: this is _not_ performed in the context of a SIGHUP, it is
+ // performed during startup, and in context of reinit administrative thread
+ LogTimeEntry::lock();
+
+ LastLogTimes::iterator times = mTimes.begin();
+ while(times != mTimes.end()) {
+ LogTimeEntry *entry = (*times);
+ if (entry->owned_Locked()) {
+ entry->triggerReader_Locked();
}
- ++it;
+ times++;
}
- pthread_mutex_unlock(&mLogElementsLock);
+
+ LogTimeEntry::unlock();
}
LogBuffer::LogBuffer(LastLogTimes *times):
- monotonic(android_log_timestamp() == 'm'),
+ monotonic(android_log_clockid() == CLOCK_MONOTONIC),
mTimes(*times) {
pthread_mutex_init(&mLogElementsLock, NULL);
@@ -429,7 +445,10 @@
while(t != mTimes.end()) {
LogTimeEntry *entry = (*t);
if (entry->owned_Locked() && entry->isWatching(id)
- && (!oldest || (oldest->mStart > entry->mStart))) {
+ && (!oldest ||
+ (oldest->mStart > entry->mStart) ||
+ ((oldest->mStart == entry->mStart) &&
+ (entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec)))) {
oldest = entry;
}
t++;
@@ -448,8 +467,12 @@
}
if (oldest && (oldest->mStart <= e->getSequence())) {
- oldest->triggerSkip_Locked(id, pruneRows);
busy = true;
+ if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
+ oldest->triggerReader_Locked();
+ } else {
+ oldest->triggerSkip_Locked(id, pruneRows);
+ }
break;
}
@@ -523,6 +546,9 @@
if (oldest && (oldest->mStart <= e->getSequence())) {
busy = true;
+ if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
+ oldest->triggerReader_Locked();
+ }
break;
}
@@ -648,6 +674,8 @@
if (stats.sizes(id) > (2 * log_buffer_size(id))) {
// kick a misbehaving log reader client off the island
oldest->release_Locked();
+ } else if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
+ oldest->triggerReader_Locked();
} else {
oldest->triggerSkip_Locked(id, pruneRows);
}
@@ -680,6 +708,8 @@
if (stats.sizes(id) > (2 * log_buffer_size(id))) {
// kick a misbehaving log reader client off the island
oldest->release_Locked();
+ } else if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
+ oldest->triggerReader_Locked();
} else {
oldest->triggerSkip_Locked(id, pruneRows);
}
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 06135dd..c2d65b6 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -67,6 +67,14 @@
start.strptime(cp + sizeof(_start) - 1, "%s.%q");
}
+ uint64_t timeout = 0;
+ static const char _timeout[] = " timeout=";
+ cp = strstr(buffer, _timeout);
+ if (cp) {
+ timeout = atol(cp + sizeof(_timeout) - 1) * NS_PER_SEC +
+ log_time(CLOCK_REALTIME).nsec();
+ }
+
unsigned int logMask = -1;
static const char _logIds[] = " lids=";
cp = strstr(buffer, _logIds);
@@ -166,7 +174,7 @@
}
}
- FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence);
+ FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence, timeout);
command.runSocketCommand(cli);
return true;
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 41f8b95..28810d9 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -25,7 +25,7 @@
#include <string> // std::string
#include <unordered_map>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index 229be3c..b4c97a9 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <errno.h>
#include <sys/prctl.h>
#include "FlushCommand.h"
@@ -26,7 +27,7 @@
LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client,
bool nonBlock, unsigned long tail,
unsigned int logMask, pid_t pid,
- uint64_t start) :
+ uint64_t start, uint64_t timeout) :
mRefCount(1),
mRelease(false),
mError(false),
@@ -42,6 +43,8 @@
mStart(start),
mNonBlock(nonBlock),
mEnd(LogBufferElement::getCurrentSequence()) {
+ mTimeout.tv_sec = timeout / NS_PER_SEC;
+ mTimeout.tv_nsec = timeout % NS_PER_SEC;
pthread_cond_init(&threadTriggeredCondition, NULL);
cleanSkip_Locked();
}
@@ -131,6 +134,19 @@
uint64_t start = me->mStart;
while (me->threadRunning && !me->isError_Locked()) {
+
+ if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
+ if (pthread_cond_timedwait(&me->threadTriggeredCondition,
+ ×Lock,
+ &me->mTimeout) == ETIMEDOUT) {
+ me->mTimeout.tv_sec = 0;
+ me->mTimeout.tv_nsec = 0;
+ }
+ if (!me->threadRunning || me->isError_Locked()) {
+ break;
+ }
+ }
+
unlock();
if (me->mTail) {
@@ -154,7 +170,9 @@
me->cleanSkip_Locked();
- pthread_cond_wait(&me->threadTriggeredCondition, ×Lock);
+ if (!me->mTimeout.tv_sec && !me->mTimeout.tv_nsec) {
+ pthread_cond_wait(&me->threadTriggeredCondition, ×Lock);
+ }
}
unlock();
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 39bcdd4..1117088 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -50,10 +50,11 @@
public:
LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock,
unsigned long tail, unsigned int logMask, pid_t pid,
- uint64_t start);
+ uint64_t start, uint64_t timeout);
SocketClient *mClient;
uint64_t mStart;
+ struct timespec mTimeout;
const bool mNonBlock;
const uint64_t mEnd; // only relevant if mNonBlock
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index c71beb5..29e637e 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -16,7 +16,7 @@
#include <ctype.h>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include "LogWhiteBlackList.h"
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 44fa95c..4472c1d 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -112,18 +112,38 @@
++cp;
}
benchmark = cp;
+#ifdef DEBUG
+ char *end = strstr(benchmark, "\n");
+ if (end == NULL) {
+ end = benchmark + strlen(benchmark);
+ }
+ fprintf(stderr, "parse for spam counter in \"%.*s\"\n",
+ (int)(end - benchmark), benchmark);
+#endif
+ // content
while (isdigit(*cp)) {
++cp;
}
while (isspace(*cp)) {
++cp;
}
+ // optional +/- field?
+ if ((*cp == '-') || (*cp == '+')) {
+ while (isdigit(*++cp) ||
+ (*cp == '.') || (*cp == '%') || (*cp == 'X')) {
+ ;
+ }
+ while (isspace(*cp)) {
+ ++cp;
+ }
+ }
+ // number of entries pruned
unsigned long value = 0;
while (isdigit(*cp)) {
value = value * 10ULL + *cp - '0';
++cp;
}
- if (value > 100000UL) {
+ if (value > 10UL) {
break;
}
benchmark = NULL;
@@ -223,6 +243,12 @@
case 3:
fprintf(stderr, "lid=system ");
break;
+ case 4:
+ fprintf(stderr, "lid=crash ");
+ break;
+ case 5:
+ fprintf(stderr, "lid=kernel ");
+ break;
default:
if (lid >= 0) {
fprintf(stderr, "lid=%d ", lid);
@@ -419,7 +445,7 @@
EXPECT_GE(250000UL, ns[log_overhead]); // 126886 user
- EXPECT_GE(10000UL, ns[log_latency]); // 5669 user space
+ EXPECT_GE(10000000UL, ns[log_latency]); // 1453559 user space (background cgroup)
EXPECT_GE(20000000UL, ns[log_delay]); // 10500289 user
@@ -499,3 +525,68 @@
// 50% threshold for SPAM filter (<20% typical, lots of engineering margin)
ASSERT_GT(totalSize, nowSpamSize * 2);
}
+
+TEST(logd, timeout) {
+ log_msg msg_wrap, msg_timeout;
+ bool content_wrap = false, content_timeout = false, written = false;
+ unsigned int alarm_wrap = 0, alarm_timeout = 0;
+ // A few tries to get it right just in case wrap kicks in due to
+ // content providers being active during the test.
+ int i = 3;
+
+ while (--i) {
+ int fd = socket_local_client("logdr",
+ ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_SEQPACKET);
+ ASSERT_LT(0, fd);
+
+ struct sigaction ignore, old_sigaction;
+ memset(&ignore, 0, sizeof(ignore));
+ ignore.sa_handler = caught_signal;
+ sigemptyset(&ignore.sa_mask);
+ sigaction(SIGALRM, &ignore, &old_sigaction);
+ unsigned int old_alarm = alarm(3);
+
+ static const char ask[] = "dumpAndClose lids=0,1,2,3,4,5 timeout=6";
+ written = write(fd, ask, sizeof(ask)) == sizeof(ask);
+ if (!written) {
+ alarm(old_alarm);
+ sigaction(SIGALRM, &old_sigaction, NULL);
+ close(fd);
+ continue;
+ }
+
+ content_wrap = recv(fd, msg_wrap.buf, sizeof(msg_wrap), 0) > 0;
+
+ alarm_wrap = alarm(5);
+
+ content_timeout = recv(fd, msg_timeout.buf, sizeof(msg_timeout), 0) > 0;
+
+ alarm_timeout = alarm((old_alarm <= 0)
+ ? old_alarm
+ : (old_alarm > (1 + 3 - alarm_wrap))
+ ? old_alarm - 3 + alarm_wrap
+ : 2);
+ sigaction(SIGALRM, &old_sigaction, NULL);
+
+ close(fd);
+
+ if (!content_wrap && !alarm_wrap && content_timeout && !alarm_timeout) {
+ break;
+ }
+ }
+
+ if (content_wrap) {
+ dump_log_msg("wrap", &msg_wrap, 3, -1);
+ }
+
+ if (content_timeout) {
+ dump_log_msg("timeout", &msg_timeout, 3, -1);
+ }
+
+ EXPECT_TRUE(written);
+ EXPECT_FALSE(content_wrap);
+ EXPECT_EQ(0U, alarm_wrap);
+ EXPECT_TRUE(content_timeout);
+ EXPECT_NE(0U, alarm_timeout);
+}
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index 97c0d28..839ab65 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -18,8 +18,6 @@
libmetrics_sources := \
c_metrics_library.cc \
metrics_library.cc \
- serialization/metric_sample.cc \
- serialization/serialization_utils.cc \
timer.cc
metrics_client_sources := \
@@ -30,18 +28,18 @@
collectors/cpu_usage_collector.cc \
collectors/disk_usage_collector.cc \
metrics_collector.cc \
- persistent_integer.cc \
+ persistent_integer.cc
metricsd_common := \
persistent_integer.cc \
- serialization/metric_sample.cc \
- serialization/serialization_utils.cc \
+ uploader/bn_metricsd_impl.cc \
+ uploader/crash_counters.cc \
uploader/metrics_hashes.cc \
uploader/metrics_log_base.cc \
uploader/metrics_log.cc \
uploader/sender_http.cc \
uploader/system_profile_cache.cc \
- uploader/upload_service.cc \
+ uploader/upload_service.cc
metrics_collector_tests_sources := \
collectors/averaged_statistics_collector_test.cc \
@@ -49,14 +47,13 @@
metrics_collector_test.cc \
metrics_library_test.cc \
persistent_integer_test.cc \
- serialization/serialization_utils_unittest.cc \
- timer_test.cc \
+ timer_test.cc
metricsd_tests_sources := \
uploader/metrics_hashes_unittest.cc \
uploader/metrics_log_base_unittest.cc \
uploader/mock/sender_mock.cc \
- uploader/upload_service_test.cc \
+ uploader/upload_service_test.cc
metrics_CFLAGS := -Wall \
-Wno-char-subscripts \
@@ -70,7 +67,7 @@
-fvisibility=default
metrics_includes := external/gtest/include \
$(LOCAL_PATH)/include
-libmetrics_shared_libraries := libchrome libbrillo
+libmetrics_shared_libraries := libchrome libbinder libbrillo libutils
metrics_collector_shared_libraries := $(libmetrics_shared_libraries) \
libbrillo-dbus \
libbrillo-http \
@@ -78,14 +75,24 @@
libdbus \
libmetrics \
librootdev \
- libweaved \
+ libweaved
metricsd_shared_libraries := \
+ libbinder \
libbrillo \
libbrillo-http \
libchrome \
libprotobuf-cpp-lite \
libupdate_engine_client \
+ libutils
+
+# Static proxy library for the binder interface.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := metricsd_binder_proxy
+LOCAL_SHARED_LIBRARIES := libbinder libutils
+LOCAL_SRC_FILES := aidl/android/brillo/metrics/IMetricsd.aidl
+include $(BUILD_STATIC_LIBRARY)
# Shared library for metrics.
# ========================================================
@@ -100,6 +107,7 @@
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_SHARED_LIBRARIES := $(libmetrics_shared_libraries)
LOCAL_SRC_FILES := $(libmetrics_sources)
+LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
include $(BUILD_SHARED_LIBRARY)
# CLI client for metrics.
@@ -114,6 +122,7 @@
LOCAL_SHARED_LIBRARIES := $(libmetrics_shared_libraries) \
libmetrics
LOCAL_SRC_FILES := $(metrics_client_sources)
+LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
include $(BUILD_EXECUTABLE)
# Protobuf library for metricsd.
@@ -144,6 +153,7 @@
LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
LOCAL_SRC_FILES := $(metrics_collector_common) \
metrics_collector_main.cc
+LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
include $(BUILD_EXECUTABLE)
# metricsd daemon.
@@ -158,9 +168,8 @@
LOCAL_INIT_RC := metricsd.rc
LOCAL_REQUIRED_MODULES := \
metrics_collector
-LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries)
-LOCAL_STATIC_LIBRARIES := metricsd_protos
+LOCAL_STATIC_LIBRARIES := metricsd_protos metricsd_binder_proxy
LOCAL_SRC_FILES := $(metricsd_common) \
metricsd_main.cc
include $(BUILD_EXECUTABLE)
@@ -173,10 +182,9 @@
LOCAL_CLANG := true
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS) -Wno-sign-compare
-LOCAL_RTTI_FLAG := -frtti
-LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries) libmetrics
+LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries)
LOCAL_SRC_FILES := $(metricsd_tests_sources) $(metricsd_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_protos
+LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_protos metricsd_binder_proxy
include $(BUILD_NATIVE_TEST)
# Unit tests for metrics_collector.
@@ -191,7 +199,7 @@
LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
LOCAL_SRC_FILES := $(metrics_collector_tests_sources) \
$(metrics_collector_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock
+LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy
include $(BUILD_NATIVE_TEST)
# Weave schema files
diff --git a/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl b/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl
new file mode 100644
index 0000000..aa3cb34
--- /dev/null
+++ b/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package android.brillo.metrics;
+
+interface IMetricsd {
+ oneway void recordHistogram(String name, int sample, int min, int max,
+ int nbuckets);
+ oneway void recordLinearHistogram(String name, int sample, int max);
+ oneway void recordSparseHistogram(String name, int sample);
+ oneway void recordCrash(String type);
+ String getHistogramsDump();
+}
diff --git a/metricsd/c_metrics_library.cc b/metricsd/c_metrics_library.cc
index 0503876..47a543e 100644
--- a/metricsd/c_metrics_library.cc
+++ b/metricsd/c_metrics_library.cc
@@ -66,14 +66,6 @@
return lib->SendSparseToUMA(std::string(name), sample);
}
-extern "C" int CMetricsLibrarySendUserActionToUMA(CMetricsLibrary handle,
- const char* action) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- if (lib == NULL)
- return 0;
- return lib->SendUserActionToUMA(std::string(action));
-}
-
extern "C" int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
const char* crash_kind) {
MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
diff --git a/metricsd/constants.h b/metricsd/constants.h
index ee0c9cb..4815888 100644
--- a/metricsd/constants.h
+++ b/metricsd/constants.h
@@ -22,7 +22,6 @@
static const char kMetricsdDirectory[] = "/data/misc/metricsd/";
static const char kMetricsCollectorDirectory[] =
"/data/misc/metrics_collector/";
-static const char kMetricsEventsFileName[] = "uma-events";
static const char kMetricsGUIDFileName[] = "Sysinfo.GUID";
static const char kMetricsServer[] = "https://clients4.google.com/uma/v2";
static const char kConsentFileName[] = "enabled";
diff --git a/metricsd/include/metrics/c_metrics_library.h b/metricsd/include/metrics/c_metrics_library.h
index 4e7e666..1e597c2 100644
--- a/metricsd/include/metrics/c_metrics_library.h
+++ b/metricsd/include/metrics/c_metrics_library.h
@@ -44,10 +44,6 @@
int CMetricsLibrarySendSparseToUMA(CMetricsLibrary handle,
const char* name, int sample);
-// C wrapper for MetricsLibrary::SendUserActionToUMA.
-int CMetricsLibrarySendUserActionToUMA(CMetricsLibrary handle,
- const char* action);
-
// C wrapper for MetricsLibrary::SendCrashToUMA.
int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
const char* crash_kind);
diff --git a/metricsd/include/metrics/metrics_library.h b/metricsd/include/metrics/metrics_library.h
index d2e98c8..a1bb926 100644
--- a/metricsd/include/metrics/metrics_library.h
+++ b/metricsd/include/metrics/metrics_library.h
@@ -24,9 +24,17 @@
#include <base/compiler_specific.h>
#include <base/files/file_path.h>
#include <base/macros.h>
-#include <base/memory/scoped_ptr.h>
+#include <binder/IServiceManager.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
+namespace android {
+namespace brillo {
+namespace metrics {
+class IMetricsd;
+} // namespace metrics
+} // namespace brillo
+} // namespace android
+
class MetricsLibraryInterface {
public:
virtual void Init() = 0;
@@ -36,7 +44,6 @@
virtual bool SendEnumToUMA(const std::string& name, int sample, int max) = 0;
virtual bool SendBoolToUMA(const std::string& name, bool sample) = 0;
virtual bool SendSparseToUMA(const std::string& name, int sample) = 0;
- virtual bool SendUserActionToUMA(const std::string& action) = 0;
virtual ~MetricsLibraryInterface() {}
};
@@ -106,18 +113,6 @@
// |sample| is the 32-bit integer value to be recorded.
bool SendSparseToUMA(const std::string& name, int sample) override;
- // Sends a user action to Chrome for transport to UMA and returns true on
- // success. This method results in the equivalent of an asynchronous
- // non-blocking RPC to UserMetrics::RecordAction. The new metric must be
- // added to chrome/tools/extract_actions.py in the Chromium repository, which
- // should then be run to generate a hash for the new action.
- //
- // Until http://crosbug.com/11125 is fixed, the metric must also be added to
- // chrome/browser/chromeos/external_metrics.cc.
- //
- // |action| is the user-generated event (e.g., "MuteKeyPressed").
- bool SendUserActionToUMA(const std::string& action) override;
-
// Sends a signal to UMA that a crash of the given |crash_kind|
// has occurred. Used by UMA to generate stability statistics.
bool SendCrashToUMA(const char *crash_kind);
@@ -130,6 +125,11 @@
// number in the histograms dashboard).
bool SendCrosEventToUMA(const std::string& event);
+ // Debugging only.
+ // Dumps the histograms aggregated since metricsd started into |dump|.
+ // Returns true iff the dump succeeds.
+ bool GetHistogramsDump(std::string* dump);
+
private:
friend class CMetricsLibraryTest;
friend class MetricsLibraryTest;
@@ -152,6 +152,10 @@
char* buffer, int buffer_size,
bool* result);
+ // Connects to IMetricsd if the proxy does not exist or is not alive.
+ // Don't block if we fail to get the proxy for any reason.
+ bool CheckService();
+
// Time at which we last checked if metrics were enabled.
time_t cached_enabled_time_;
@@ -161,7 +165,8 @@
// True iff we should cache the enabled/disabled status.
bool use_caching_;
- base::FilePath uma_events_file_;
+ android::sp<android::IServiceManager> manager_;
+ android::sp<android::brillo::metrics::IMetricsd> metricsd_proxy_;
base::FilePath consent_file_;
DISALLOW_COPY_AND_ASSIGN(MetricsLibrary);
diff --git a/metricsd/include/metrics/metrics_library_mock.h b/metricsd/include/metrics/metrics_library_mock.h
index db56f9e..3b0b24d 100644
--- a/metricsd/include/metrics/metrics_library_mock.h
+++ b/metricsd/include/metrics/metrics_library_mock.h
@@ -34,7 +34,6 @@
int max));
MOCK_METHOD2(SendBoolToUMA, bool(const std::string& name, bool sample));
MOCK_METHOD2(SendSparseToUMA, bool(const std::string& name, int sample));
- MOCK_METHOD1(SendUserActionToUMA, bool(const std::string& action));
bool AreMetricsEnabled() override {return metrics_enabled_;};
};
diff --git a/metricsd/metrics_client.cc b/metricsd/metrics_client.cc
index 946b36a..c66b975 100644
--- a/metricsd/metrics_client.cc
+++ b/metricsd/metrics_client.cc
@@ -17,19 +17,14 @@
#include <cstdio>
#include <cstdlib>
-#include <base/memory/scoped_vector.h>
-
#include "constants.h"
#include "metrics/metrics_library.h"
-#include "serialization/metric_sample.h"
-#include "serialization/serialization_utils.h"
enum Mode {
- kModeDumpLogs,
+ kModeDumpHistograms,
kModeSendSample,
kModeSendEnumSample,
kModeSendSparseSample,
- kModeSendUserAction,
kModeSendCrosEvent,
kModeHasConsent,
kModeIsGuestMode,
@@ -41,19 +36,17 @@
" metrics_client -e name sample max\n"
" metrics_client -s name sample\n"
" metrics_client -v event\n"
- " metrics_client -u action\n"
" metrics_client [-cdg]\n"
"\n"
" default: send metric with integer values \n"
" |min| > 0, |min| <= sample < |max|\n"
" -c: return exit status 0 if user consents to stats, 1 otherwise,\n"
" in guest mode always return 1\n"
- " -d: dump cached logs to the console\n"
+ " -d: dump the histograms recorded by metricsd to stdout\n"
" -e: send linear/enumeration histogram data\n"
" -g: return exit status 0 if machine in guest mode, 1 otherwise\n"
" -s: send a sparse histogram sample\n"
" -t: convert sample from double seconds to int milliseconds\n"
- " -u: send a user action to Chrome\n"
" -v: send a Platform.CrOSEvent enum histogram sample\n");
exit(1);
}
@@ -78,6 +71,20 @@
return value;
}
+static int DumpHistograms() {
+ MetricsLibrary metrics_lib;
+ metrics_lib.Init();
+
+ std::string dump;
+ if (!metrics_lib.GetHistogramsDump(&dump)) {
+ printf("Failed to dump the histograms.");
+ return 1;
+ }
+
+ printf("%s\n", dump.c_str());
+ return 0;
+}
+
static int SendStats(char* argv[],
int name_index,
enum Mode mode,
@@ -106,14 +113,6 @@
return 0;
}
-static int SendUserAction(char* argv[], int action_index) {
- const char* action = argv[action_index];
- MetricsLibrary metrics_lib;
- metrics_lib.Init();
- metrics_lib.SendUserActionToUMA(action);
- return 0;
-}
-
static int SendCrosEvent(char* argv[], int action_index) {
const char* event = argv[action_index];
bool result;
@@ -139,58 +138,19 @@
return metrics_lib.IsGuestMode() ? 0 : 1;
}
-static int DumpLogs() {
- base::FilePath events_file = base::FilePath(metrics::kSharedMetricsDirectory)
- .Append(metrics::kMetricsEventsFileName);
- printf("Metrics from %s\n\n", events_file.value().data());
-
- ScopedVector<metrics::MetricSample> metrics;
- metrics::SerializationUtils::ReadMetricsFromFile(events_file.value(),
- &metrics);
-
- for (ScopedVector<metrics::MetricSample>::const_iterator i = metrics.begin();
- i != metrics.end(); ++i) {
- const metrics::MetricSample* sample = *i;
- printf("name: %s\t", sample->name().c_str());
- printf("type: ");
-
- switch (sample->type()) {
- case metrics::MetricSample::CRASH:
- printf("CRASH");
- break;
- case metrics::MetricSample::HISTOGRAM:
- printf("HISTOGRAM");
- break;
- case metrics::MetricSample::LINEAR_HISTOGRAM:
- printf("LINEAR_HISTOGRAM");
- break;
- case metrics::MetricSample::SPARSE_HISTOGRAM:
- printf("SPARSE_HISTOGRAM");
- break;
- case metrics::MetricSample::USER_ACTION:
- printf("USER_ACTION");
- break;
- }
-
- printf("\n");
- }
-
- return 0;
-}
-
int main(int argc, char** argv) {
enum Mode mode = kModeSendSample;
bool secs_to_msecs = false;
// Parse arguments
int flag;
- while ((flag = getopt(argc, argv, "abcdegstuv")) != -1) {
+ while ((flag = getopt(argc, argv, "abcdegstv")) != -1) {
switch (flag) {
case 'c':
mode = kModeHasConsent;
break;
case 'd':
- mode = kModeDumpLogs;
+ mode = kModeDumpHistograms;
break;
case 'e':
mode = kModeSendEnumSample;
@@ -204,9 +164,6 @@
case 't':
secs_to_msecs = true;
break;
- case 'u':
- mode = kModeSendUserAction;
- break;
case 'v':
mode = kModeSendCrosEvent;
break;
@@ -224,8 +181,6 @@
expected_args = 3;
else if (mode == kModeSendSparseSample)
expected_args = 2;
- else if (mode == kModeSendUserAction)
- expected_args = 1;
else if (mode == kModeSendCrosEvent)
expected_args = 1;
@@ -234,6 +189,8 @@
}
switch (mode) {
+ case kModeDumpHistograms:
+ return DumpHistograms();
case kModeSendSample:
case kModeSendEnumSample:
case kModeSendSparseSample:
@@ -244,16 +201,12 @@
arg_index,
mode,
secs_to_msecs);
- case kModeSendUserAction:
- return SendUserAction(argv, arg_index);
case kModeSendCrosEvent:
return SendCrosEvent(argv, arg_index);
case kModeHasConsent:
return HasConsent();
case kModeIsGuestMode:
return IsGuestMode();
- case kModeDumpLogs:
- return DumpLogs();
default:
ShowUsage();
return 0;
diff --git a/metricsd/metrics_library.cc b/metricsd/metrics_library.cc
index 686c926..d211ab4 100644
--- a/metricsd/metrics_library.cc
+++ b/metricsd/metrics_library.cc
@@ -18,19 +18,21 @@
#include <base/logging.h>
#include <base/strings/stringprintf.h>
+#include <binder/IServiceManager.h>
#include <errno.h>
#include <sys/file.h>
#include <sys/stat.h>
+#include <utils/String16.h>
#include <cstdio>
#include <cstring>
+#include "android/brillo/metrics/IMetricsd.h"
#include "constants.h"
-#include "serialization/metric_sample.h"
-#include "serialization/serialization_utils.h"
static const char kCrosEventHistogramName[] = "Platform.CrOSEvent";
static const int kCrosEventHistogramMax = 100;
+static const char kMetricsServiceName[] = "android.brillo.metrics.IMetricsd";
/* Add new cros events here.
*
@@ -53,6 +55,10 @@
"TPM.EarlyResetDuringCommand", // 12
};
+using android::binder::Status;
+using android::brillo::metrics::IMetricsd;
+using android::String16;
+
MetricsLibrary::MetricsLibrary() {}
MetricsLibrary::~MetricsLibrary() {}
@@ -123,6 +129,17 @@
return result && (access("/var/run/state/logged-in", F_OK) == 0);
}
+bool MetricsLibrary::CheckService() {
+ if (metricsd_proxy_.get() &&
+ android::IInterface::asBinder(metricsd_proxy_)->isBinderAlive())
+ return true;
+
+ const String16 name(kMetricsServiceName);
+ metricsd_proxy_ = android::interface_cast<IMetricsd>(
+ android::defaultServiceManager()->checkService(name));
+ return metricsd_proxy_.get();
+}
+
bool MetricsLibrary::AreMetricsEnabled() {
static struct stat stat_buffer;
time_t this_check_time = time(nullptr);
@@ -135,7 +152,6 @@
void MetricsLibrary::Init() {
base::FilePath dir = base::FilePath(metrics::kSharedMetricsDirectory);
- uma_events_file_ = dir.Append(metrics::kMetricsEventsFileName);
consent_file_ = dir.Append(metrics::kConsentFileName);
cached_enabled_ = false;
cached_enabled_time_ = 0;
@@ -148,54 +164,45 @@
}
void MetricsLibrary::InitForTest(const base::FilePath& metrics_directory) {
- uma_events_file_ = metrics_directory.Append(metrics::kMetricsEventsFileName);
consent_file_ = metrics_directory.Append(metrics::kConsentFileName);
cached_enabled_ = false;
cached_enabled_time_ = 0;
use_caching_ = true;
}
-bool MetricsLibrary::SendToUMA(const std::string& name,
- int sample,
- int min,
- int max,
- int nbuckets) {
- return metrics::SerializationUtils::WriteMetricToFile(
- *metrics::MetricSample::HistogramSample(name, sample, min, max, nbuckets)
- .get(),
- uma_events_file_.value());
+bool MetricsLibrary::SendToUMA(
+ const std::string& name, int sample, int min, int max, int nbuckets) {
+ return CheckService() &&
+ metricsd_proxy_->recordHistogram(String16(name.c_str()), sample, min,
+ max, nbuckets)
+ .isOk();
}
-bool MetricsLibrary::SendEnumToUMA(const std::string& name, int sample,
+bool MetricsLibrary::SendEnumToUMA(const std::string& name,
+ int sample,
int max) {
- return metrics::SerializationUtils::WriteMetricToFile(
- *metrics::MetricSample::LinearHistogramSample(name, sample, max).get(),
- uma_events_file_.value());
+ return CheckService() &&
+ metricsd_proxy_->recordLinearHistogram(String16(name.c_str()), sample,
+ max)
+ .isOk();
}
bool MetricsLibrary::SendBoolToUMA(const std::string& name, bool sample) {
- return metrics::SerializationUtils::WriteMetricToFile(
- *metrics::MetricSample::LinearHistogramSample(name,
- sample ? 1 : 0, 2).get(),
- uma_events_file_.value());
+ return CheckService() &&
+ metricsd_proxy_->recordLinearHistogram(String16(name.c_str()),
+ sample ? 1 : 0, 2)
+ .isOk();
}
bool MetricsLibrary::SendSparseToUMA(const std::string& name, int sample) {
- return metrics::SerializationUtils::WriteMetricToFile(
- *metrics::MetricSample::SparseHistogramSample(name, sample).get(),
- uma_events_file_.value());
+ return CheckService() &&
+ metricsd_proxy_->recordSparseHistogram(String16(name.c_str()), sample)
+ .isOk();
}
-bool MetricsLibrary::SendUserActionToUMA(const std::string& action) {
- return metrics::SerializationUtils::WriteMetricToFile(
- *metrics::MetricSample::UserActionSample(action).get(),
- uma_events_file_.value());
-}
-
-bool MetricsLibrary::SendCrashToUMA(const char *crash_kind) {
- return metrics::SerializationUtils::WriteMetricToFile(
- *metrics::MetricSample::CrashSample(crash_kind).get(),
- uma_events_file_.value());
+bool MetricsLibrary::SendCrashToUMA(const char* crash_kind) {
+ return CheckService() &&
+ metricsd_proxy_->recordCrash(String16(crash_kind)).isOk();
}
bool MetricsLibrary::SendCrosEventToUMA(const std::string& event) {
@@ -206,3 +213,14 @@
}
return false;
}
+
+bool MetricsLibrary::GetHistogramsDump(std::string* dump) {
+ android::String16 temp_dump;
+ if (!CheckService() ||
+ !metricsd_proxy_->getHistogramsDump(&temp_dump).isOk()) {
+ return false;
+ }
+
+ *dump = android::String8(temp_dump).string();
+ return true;
+}
diff --git a/metricsd/metrics_library_test.cc b/metricsd/metrics_library_test.cc
index be8a4bb..52fcce3 100644
--- a/metricsd/metrics_library_test.cc
+++ b/metricsd/metrics_library_test.cc
@@ -29,7 +29,6 @@
virtual void SetUp() {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
lib_.InitForTest(temp_dir_.path());
- EXPECT_EQ(0, WriteFile(lib_.uma_events_file_, "", 0));
// Defeat metrics enabled caching between tests.
lib_.cached_enabled_time_ = 0;
}
diff --git a/metricsd/metricsd_main.cc b/metricsd/metricsd_main.cc
index eee8a94..f460268 100644
--- a/metricsd/metricsd_main.cc
+++ b/metricsd/metricsd_main.cc
@@ -14,34 +14,34 @@
* limitations under the License.
*/
+#include <thread>
+
#include <base/at_exit.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/logging.h>
+#include <base/metrics/statistics_recorder.h>
#include <base/strings/string_util.h>
#include <base/time/time.h>
#include <brillo/flag_helper.h>
#include <brillo/syslog_logging.h>
#include "constants.h"
+#include "uploader/bn_metricsd_impl.h"
+#include "uploader/crash_counters.h"
#include "uploader/upload_service.h"
-
int main(int argc, char** argv) {
DEFINE_bool(foreground, false, "Don't daemonize");
// Upload the metrics once and exit. (used for testing)
- DEFINE_bool(uploader_test,
- false,
- "run the uploader once and exit");
+ DEFINE_bool(uploader_test, false, "run the uploader once and exit");
// Upload Service flags.
- DEFINE_int32(upload_interval_secs,
- 1800,
+ DEFINE_int32(upload_interval_secs, 1800,
"Interval at which metrics_daemon sends the metrics. (needs "
"-uploader)");
- DEFINE_string(server,
- metrics::kMetricsServer,
+ DEFINE_string(server, metrics::kMetricsServer,
"Server to upload the metrics to. (needs -uploader)");
DEFINE_string(private_directory, metrics::kMetricsdDirectory,
"Path to the private directory used by metricsd "
@@ -56,8 +56,8 @@
brillo::FlagHelper::Init(argc, argv, "Brillo metrics daemon.");
- int logging_location = (FLAGS_foreground ? brillo::kLogToStderr
- : brillo::kLogToSyslog);
+ int logging_location =
+ (FLAGS_foreground ? brillo::kLogToStderr : brillo::kLogToSyslog);
if (FLAGS_logtosyslog)
logging_location = brillo::kLogToSyslog;
@@ -76,10 +76,18 @@
return errno;
}
- UploadService service(
+ std::shared_ptr<CrashCounters> counters(new CrashCounters);
+
+ UploadService upload_service(
FLAGS_server, base::TimeDelta::FromSeconds(FLAGS_upload_interval_secs),
base::FilePath(FLAGS_private_directory),
- base::FilePath(FLAGS_shared_directory));
+ base::FilePath(FLAGS_shared_directory), counters);
- service.Run();
+ base::StatisticsRecorder::Initialize();
+
+ // Create and start the binder thread.
+ BnMetricsdImpl binder_service(counters);
+ std::thread binder_thread(&BnMetricsdImpl::Run, &binder_service);
+
+ upload_service.Run();
}
diff --git a/metricsd/serialization/metric_sample.cc b/metricsd/serialization/metric_sample.cc
deleted file mode 100644
index 76a47c0..0000000
--- a/metricsd/serialization/metric_sample.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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 "serialization/metric_sample.h"
-
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
-
-namespace metrics {
-
-MetricSample::MetricSample(MetricSample::SampleType sample_type,
- const std::string& metric_name,
- int sample,
- int min,
- int max,
- int bucket_count)
- : type_(sample_type),
- name_(metric_name),
- sample_(sample),
- min_(min),
- max_(max),
- bucket_count_(bucket_count) {
-}
-
-MetricSample::~MetricSample() {
-}
-
-bool MetricSample::IsValid() const {
- return name().find(' ') == std::string::npos &&
- name().find('\0') == std::string::npos && !name().empty();
-}
-
-std::string MetricSample::ToString() const {
- if (type_ == CRASH) {
- return base::StringPrintf("crash%c%s%c",
- '\0',
- name().c_str(),
- '\0');
- } else if (type_ == SPARSE_HISTOGRAM) {
- return base::StringPrintf("sparsehistogram%c%s %d%c",
- '\0',
- name().c_str(),
- sample_,
- '\0');
- } else if (type_ == LINEAR_HISTOGRAM) {
- return base::StringPrintf("linearhistogram%c%s %d %d%c",
- '\0',
- name().c_str(),
- sample_,
- max_,
- '\0');
- } else if (type_ == HISTOGRAM) {
- return base::StringPrintf("histogram%c%s %d %d %d %d%c",
- '\0',
- name().c_str(),
- sample_,
- min_,
- max_,
- bucket_count_,
- '\0');
- } else {
- // The type can only be USER_ACTION.
- CHECK_EQ(type_, USER_ACTION);
- return base::StringPrintf("useraction%c%s%c",
- '\0',
- name().c_str(),
- '\0');
- }
-}
-
-int MetricSample::sample() const {
- CHECK_NE(type_, USER_ACTION);
- CHECK_NE(type_, CRASH);
- return sample_;
-}
-
-int MetricSample::min() const {
- CHECK_EQ(type_, HISTOGRAM);
- return min_;
-}
-
-int MetricSample::max() const {
- CHECK_NE(type_, CRASH);
- CHECK_NE(type_, USER_ACTION);
- CHECK_NE(type_, SPARSE_HISTOGRAM);
- return max_;
-}
-
-int MetricSample::bucket_count() const {
- CHECK_EQ(type_, HISTOGRAM);
- return bucket_count_;
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::CrashSample(
- const std::string& crash_name) {
- return scoped_ptr<MetricSample>(
- new MetricSample(CRASH, crash_name, 0, 0, 0, 0));
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::HistogramSample(
- const std::string& histogram_name,
- int sample,
- int min,
- int max,
- int bucket_count) {
- return scoped_ptr<MetricSample>(new MetricSample(
- HISTOGRAM, histogram_name, sample, min, max, bucket_count));
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::ParseHistogram(
- const std::string& serialized_histogram) {
- std::vector<std::string> parts;
- base::SplitString(serialized_histogram, ' ', &parts);
-
- if (parts.size() != 5)
- return scoped_ptr<MetricSample>();
- int sample, min, max, bucket_count;
- if (parts[0].empty() || !base::StringToInt(parts[1], &sample) ||
- !base::StringToInt(parts[2], &min) ||
- !base::StringToInt(parts[3], &max) ||
- !base::StringToInt(parts[4], &bucket_count)) {
- return scoped_ptr<MetricSample>();
- }
-
- return HistogramSample(parts[0], sample, min, max, bucket_count);
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::SparseHistogramSample(
- const std::string& histogram_name,
- int sample) {
- return scoped_ptr<MetricSample>(
- new MetricSample(SPARSE_HISTOGRAM, histogram_name, sample, 0, 0, 0));
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::ParseSparseHistogram(
- const std::string& serialized_histogram) {
- std::vector<std::string> parts;
- base::SplitString(serialized_histogram, ' ', &parts);
- if (parts.size() != 2)
- return scoped_ptr<MetricSample>();
- int sample;
- if (parts[0].empty() || !base::StringToInt(parts[1], &sample))
- return scoped_ptr<MetricSample>();
-
- return SparseHistogramSample(parts[0], sample);
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::LinearHistogramSample(
- const std::string& histogram_name,
- int sample,
- int max) {
- return scoped_ptr<MetricSample>(
- new MetricSample(LINEAR_HISTOGRAM, histogram_name, sample, 0, max, 0));
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::ParseLinearHistogram(
- const std::string& serialized_histogram) {
- std::vector<std::string> parts;
- int sample, max;
- base::SplitString(serialized_histogram, ' ', &parts);
- if (parts.size() != 3)
- return scoped_ptr<MetricSample>();
- if (parts[0].empty() || !base::StringToInt(parts[1], &sample) ||
- !base::StringToInt(parts[2], &max)) {
- return scoped_ptr<MetricSample>();
- }
-
- return LinearHistogramSample(parts[0], sample, max);
-}
-
-// static
-scoped_ptr<MetricSample> MetricSample::UserActionSample(
- const std::string& action_name) {
- return scoped_ptr<MetricSample>(
- new MetricSample(USER_ACTION, action_name, 0, 0, 0, 0));
-}
-
-bool MetricSample::IsEqual(const MetricSample& metric) {
- return type_ == metric.type_ && name_ == metric.name_ &&
- sample_ == metric.sample_ && min_ == metric.min_ &&
- max_ == metric.max_ && bucket_count_ == metric.bucket_count_;
-}
-
-} // namespace metrics
diff --git a/metricsd/serialization/metric_sample.h b/metricsd/serialization/metric_sample.h
deleted file mode 100644
index 5a4e4ae..0000000
--- a/metricsd/serialization/metric_sample.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_SERIALIZATION_METRIC_SAMPLE_H_
-#define METRICS_SERIALIZATION_METRIC_SAMPLE_H_
-
-#include <string>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-
-namespace metrics {
-
-// This class is used by libmetrics (ChromeOS) to serialize
-// and deserialize measurements to send them to a metrics sending service.
-// It is meant to be a simple container with serialization functions.
-class MetricSample {
- public:
- // Types of metric sample used.
- enum SampleType {
- CRASH,
- HISTOGRAM,
- LINEAR_HISTOGRAM,
- SPARSE_HISTOGRAM,
- USER_ACTION
- };
-
- ~MetricSample();
-
- // Returns true if the sample is valid (can be serialized without ambiguity).
- //
- // This function should be used to filter bad samples before serializing them.
- bool IsValid() const;
-
- // Getters for type and name. All types of metrics have these so we do not
- // need to check the type.
- SampleType type() const { return type_; }
- const std::string& name() const { return name_; }
-
- // Getters for sample, min, max, bucket_count.
- // Check the metric type to make sure the request make sense. (ex: a crash
- // sample does not have a bucket_count so we crash if we call bucket_count()
- // on it.)
- int sample() const;
- int min() const;
- int max() const;
- int bucket_count() const;
-
- // Returns a serialized version of the sample.
- //
- // The serialized message for each type is:
- // crash: crash\0|name_|\0
- // user action: useraction\0|name_|\0
- // histogram: histogram\0|name_| |sample_| |min_| |max_| |bucket_count_|\0
- // sparsehistogram: sparsehistogram\0|name_| |sample_|\0
- // linearhistogram: linearhistogram\0|name_| |sample_| |max_|\0
- std::string ToString() const;
-
- // Builds a crash sample.
- static scoped_ptr<MetricSample> CrashSample(const std::string& crash_name);
-
- // Builds a histogram sample.
- static scoped_ptr<MetricSample> HistogramSample(
- const std::string& histogram_name,
- int sample,
- int min,
- int max,
- int bucket_count);
- // Deserializes a histogram sample.
- static scoped_ptr<MetricSample> ParseHistogram(const std::string& serialized);
-
- // Builds a sparse histogram sample.
- static scoped_ptr<MetricSample> SparseHistogramSample(
- const std::string& histogram_name,
- int sample);
- // Deserializes a sparse histogram sample.
- static scoped_ptr<MetricSample> ParseSparseHistogram(
- const std::string& serialized);
-
- // Builds a linear histogram sample.
- static scoped_ptr<MetricSample> LinearHistogramSample(
- const std::string& histogram_name,
- int sample,
- int max);
- // Deserializes a linear histogram sample.
- static scoped_ptr<MetricSample> ParseLinearHistogram(
- const std::string& serialized);
-
- // Builds a user action sample.
- static scoped_ptr<MetricSample> UserActionSample(
- const std::string& action_name);
-
- // Returns true if sample and this object represent the same sample (type,
- // name, sample, min, max, bucket_count match).
- bool IsEqual(const MetricSample& sample);
-
- private:
- MetricSample(SampleType sample_type,
- const std::string& metric_name,
- const int sample,
- const int min,
- const int max,
- const int bucket_count);
-
- const SampleType type_;
- const std::string name_;
- const int sample_;
- const int min_;
- const int max_;
- const int bucket_count_;
-
- DISALLOW_COPY_AND_ASSIGN(MetricSample);
-};
-
-} // namespace metrics
-
-#endif // METRICS_SERIALIZATION_METRIC_SAMPLE_H_
diff --git a/metricsd/serialization/serialization_utils.cc b/metricsd/serialization/serialization_utils.cc
deleted file mode 100644
index 102c940..0000000
--- a/metricsd/serialization/serialization_utils.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * 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 "serialization/serialization_utils.h"
-
-#include <sys/file.h>
-
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "serialization/metric_sample.h"
-
-#define READ_WRITE_ALL_FILE_FLAGS \
- (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
-
-namespace metrics {
-namespace {
-
-// Reads the next message from |file_descriptor| into |message|.
-//
-// |message| will be set to the empty string if no message could be read (EOF)
-// or the message was badly constructed.
-//
-// Returns false if no message can be read from this file anymore (EOF or
-// unrecoverable error).
-bool ReadMessage(int fd, std::string* message) {
- CHECK(message);
-
- int result;
- int32_t message_size;
- const int32_t message_hdr_size = sizeof(message_size);
- // The file containing the metrics do not leave the device so the writer and
- // the reader will always have the same endianness.
- result = HANDLE_EINTR(read(fd, &message_size, sizeof(message_size)));
- if (result < 0) {
- DPLOG(ERROR) << "reading metrics message header";
- return false;
- }
- if (result == 0) {
- // This indicates a normal EOF.
- return false;
- }
- if (result < message_hdr_size) {
- DLOG(ERROR) << "bad read size " << result << ", expecting "
- << sizeof(message_size);
- return false;
- }
-
- // kMessageMaxLength applies to the entire message: the 4-byte
- // length field and the content.
- if (message_size > SerializationUtils::kMessageMaxLength) {
- DLOG(ERROR) << "message too long : " << message_size;
- if (HANDLE_EINTR(lseek(fd, message_size - 4, SEEK_CUR)) == -1) {
- DLOG(ERROR) << "error while skipping message. abort";
- return false;
- }
- // Badly formatted message was skipped. Treat the badly formatted sample as
- // an empty sample.
- message->clear();
- return true;
- }
-
- if (message_size < message_hdr_size) {
- DLOG(ERROR) << "message too short : " << message_size;
- return false;
- }
-
- message_size -= message_hdr_size; // The message size includes itself.
- char buffer[SerializationUtils::kMessageMaxLength];
- if (!base::ReadFromFD(fd, buffer, message_size)) {
- DPLOG(ERROR) << "reading metrics message body";
- return false;
- }
- *message = std::string(buffer, message_size);
- return true;
-}
-
-
-// Opens the metrics log file at |filename| in the given |mode|.
-//
-// Returns the file descriptor wrapped in a valid ScopedFD on success.
-base::ScopedFD OpenMetricsFile(const std::string& filename, mode_t mode) {
- struct stat stat_buf;
- int result;
-
- result = stat(filename.c_str(), &stat_buf);
- if (result < 0) {
- if (errno != ENOENT)
- DPLOG(ERROR) << filename << ": bad metrics file stat";
-
- // Nothing to collect---try later.
- return base::ScopedFD();
- }
- if (stat_buf.st_size == 0) {
- // Also nothing to collect.
- return base::ScopedFD();
- }
- base::ScopedFD fd(open(filename.c_str(), mode));
- if (fd.get() < 0) {
- DPLOG(ERROR) << filename << ": cannot open";
- return base::ScopedFD();
- }
-
- return fd.Pass();
-}
-
-
-// Parses the contents of the metrics log file descriptor |fd| into |metrics|.
-void ReadAllMetricsFromFd(int fd, ScopedVector<MetricSample>* metrics) {
- for (;;) {
- std::string message;
-
- if (!ReadMessage(fd, &message))
- break;
-
- scoped_ptr<MetricSample> sample = SerializationUtils::ParseSample(message);
- if (sample)
- metrics->push_back(sample.release());
- }
-}
-
-} // namespace
-
-scoped_ptr<MetricSample> SerializationUtils::ParseSample(
- const std::string& sample) {
- if (sample.empty())
- return scoped_ptr<MetricSample>();
-
- std::vector<std::string> parts;
- base::SplitString(sample, '\0', &parts);
- // We should have two null terminated strings so split should produce
- // three chunks.
- if (parts.size() != 3) {
- DLOG(ERROR) << "splitting message on \\0 produced " << parts.size()
- << " parts (expected 3)";
- return scoped_ptr<MetricSample>();
- }
- const std::string& name = parts[0];
- const std::string& value = parts[1];
-
- if (base::LowerCaseEqualsASCII(name, "crash")) {
- return MetricSample::CrashSample(value);
- } else if (base::LowerCaseEqualsASCII(name, "histogram")) {
- return MetricSample::ParseHistogram(value);
- } else if (base::LowerCaseEqualsASCII(name, "linearhistogram")) {
- return MetricSample::ParseLinearHistogram(value);
- } else if (base::LowerCaseEqualsASCII(name, "sparsehistogram")) {
- return MetricSample::ParseSparseHistogram(value);
- } else if (base::LowerCaseEqualsASCII(name, "useraction")) {
- return MetricSample::UserActionSample(value);
- } else {
- DLOG(ERROR) << "invalid event type: " << name << ", value: " << value;
- }
- return scoped_ptr<MetricSample>();
-}
-
-void SerializationUtils::ReadMetricsFromFile(
- const std::string& filename,
- ScopedVector<MetricSample>* metrics) {
- base::ScopedFD fd(OpenMetricsFile(filename, O_RDONLY));
- if (!fd.is_valid()) {
- return;
- }
-
- // This processes all messages in the log.
- ReadAllMetricsFromFd(fd.get(), metrics);
-}
-
-void SerializationUtils::ReadAndTruncateMetricsFromFile(
- const std::string& filename,
- ScopedVector<MetricSample>* metrics) {
- base::ScopedFD fd(OpenMetricsFile(filename, O_RDWR));
- if (!fd.is_valid()) {
- return;
- }
-
- int result = flock(fd.get(), LOCK_EX);
- if (result < 0) {
- DPLOG(ERROR) << filename << ": cannot lock";
- return;
- }
-
- // This processes all messages in the log. When all messages are
- // read and processed, or an error occurs, truncate the file to zero size.
- ReadAllMetricsFromFd(fd.get(), metrics);
-
- result = ftruncate(fd.get(), 0);
- if (result < 0)
- DPLOG(ERROR) << "truncate metrics log";
-
- result = flock(fd.get(), LOCK_UN);
- if (result < 0)
- DPLOG(ERROR) << "unlock metrics log";
-}
-
-bool SerializationUtils::WriteMetricToFile(const MetricSample& sample,
- const std::string& filename) {
- if (!sample.IsValid())
- return false;
-
- base::ScopedFD file_descriptor(open(filename.c_str(),
- O_WRONLY | O_APPEND | O_CREAT,
- READ_WRITE_ALL_FILE_FLAGS));
-
- if (file_descriptor.get() < 0) {
- DPLOG(ERROR) << filename << ": cannot open";
- return false;
- }
-
- fchmod(file_descriptor.get(), READ_WRITE_ALL_FILE_FLAGS);
- // Grab a lock to avoid chrome truncating the file
- // underneath us. Keep the file locked as briefly as possible.
- // Freeing file_descriptor will close the file and and remove the lock.
- if (HANDLE_EINTR(flock(file_descriptor.get(), LOCK_EX)) < 0) {
- DPLOG(ERROR) << filename << ": cannot lock";
- return false;
- }
-
- std::string msg = sample.ToString();
- int32 size = msg.length() + sizeof(int32);
- if (size > kMessageMaxLength) {
- DLOG(ERROR) << "cannot write message: too long";
- return false;
- }
-
- // The file containing the metrics samples will only be read by programs on
- // the same device so we do not check endianness.
- if (!base::WriteFileDescriptor(file_descriptor.get(),
- reinterpret_cast<char*>(&size),
- sizeof(size))) {
- DPLOG(ERROR) << "error writing message length";
- return false;
- }
-
- if (!base::WriteFileDescriptor(
- file_descriptor.get(), msg.c_str(), msg.size())) {
- DPLOG(ERROR) << "error writing message";
- return false;
- }
-
- return true;
-}
-
-} // namespace metrics
diff --git a/metricsd/serialization/serialization_utils.h b/metricsd/serialization/serialization_utils.h
deleted file mode 100644
index 655652d..0000000
--- a/metricsd/serialization/serialization_utils.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_SERIALIZATION_SERIALIZATION_UTILS_H_
-#define METRICS_SERIALIZATION_SERIALIZATION_UTILS_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-
-namespace metrics {
-
-class MetricSample;
-
-// Metrics helpers to serialize and deserialize metrics collected by
-// ChromeOS.
-namespace SerializationUtils {
-
-// Deserializes a sample passed as a string and return a sample.
-// The return value will either be a scoped_ptr to a Metric sample (if the
-// deserialization was successful) or a NULL scoped_ptr.
-scoped_ptr<MetricSample> ParseSample(const std::string& sample);
-
-// Reads all samples from a file. The file contents remain unchanged.
-void ReadMetricsFromFile(const std::string& filename,
- ScopedVector<MetricSample>* metrics);
-
-// Reads all samples from a file and truncates the file when done.
-void ReadAndTruncateMetricsFromFile(const std::string& filename,
- ScopedVector<MetricSample>* metrics);
-
-// Serializes a sample and write it to filename.
-// The format for the message is:
-// message_size, serialized_message
-// where
-// * message_size is the total length of the message (message_size +
-// serialized_message) on 4 bytes
-// * serialized_message is the serialized version of sample (using ToString)
-//
-// NB: the file will never leave the device so message_size will be written
-// with the architecture's endianness.
-bool WriteMetricToFile(const MetricSample& sample, const std::string& filename);
-
-// Maximum length of a serialized message
-static const int kMessageMaxLength = 1024;
-
-} // namespace SerializationUtils
-} // namespace metrics
-
-#endif // METRICS_SERIALIZATION_SERIALIZATION_UTILS_H_
diff --git a/metricsd/serialization/serialization_utils_unittest.cc b/metricsd/serialization/serialization_utils_unittest.cc
deleted file mode 100644
index 7a572de..0000000
--- a/metricsd/serialization/serialization_utils_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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 "serialization/serialization_utils.h"
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/logging.h>
-#include <base/strings/stringprintf.h>
-#include <gtest/gtest.h>
-
-#include "serialization/metric_sample.h"
-
-namespace metrics {
-namespace {
-
-class SerializationUtilsTest : public testing::Test {
- protected:
- SerializationUtilsTest() {
- bool success = temporary_dir.CreateUniqueTempDir();
- if (success) {
- base::FilePath dir_path = temporary_dir.path();
- filename = dir_path.value() + "chromeossampletest";
- filepath = base::FilePath(filename);
- }
- }
-
- void SetUp() override { base::DeleteFile(filepath, false); }
-
- void TestSerialization(MetricSample* sample) {
- std::string serialized(sample->ToString());
- ASSERT_EQ('\0', serialized[serialized.length() - 1]);
- scoped_ptr<MetricSample> deserialized =
- SerializationUtils::ParseSample(serialized);
- ASSERT_TRUE(deserialized);
- EXPECT_TRUE(sample->IsEqual(*deserialized.get()));
- }
-
- std::string filename;
- base::ScopedTempDir temporary_dir;
- base::FilePath filepath;
-};
-
-TEST_F(SerializationUtilsTest, CrashSerializeTest) {
- TestSerialization(MetricSample::CrashSample("test").get());
-}
-
-TEST_F(SerializationUtilsTest, HistogramSerializeTest) {
- TestSerialization(
- MetricSample::HistogramSample("myhist", 13, 1, 100, 10).get());
-}
-
-TEST_F(SerializationUtilsTest, LinearSerializeTest) {
- TestSerialization(
- MetricSample::LinearHistogramSample("linearhist", 12, 30).get());
-}
-
-TEST_F(SerializationUtilsTest, SparseSerializeTest) {
- TestSerialization(MetricSample::SparseHistogramSample("mysparse", 30).get());
-}
-
-TEST_F(SerializationUtilsTest, UserActionSerializeTest) {
- TestSerialization(MetricSample::UserActionSample("myaction").get());
-}
-
-TEST_F(SerializationUtilsTest, IllegalNameAreFilteredTest) {
- scoped_ptr<MetricSample> sample1 =
- MetricSample::SparseHistogramSample("no space", 10);
- scoped_ptr<MetricSample> sample2 = MetricSample::LinearHistogramSample(
- base::StringPrintf("here%cbhe", '\0'), 1, 3);
-
- EXPECT_FALSE(SerializationUtils::WriteMetricToFile(*sample1.get(), filename));
- EXPECT_FALSE(SerializationUtils::WriteMetricToFile(*sample2.get(), filename));
- int64 size = 0;
-
- ASSERT_TRUE(!PathExists(filepath) || base::GetFileSize(filepath, &size));
-
- EXPECT_EQ(0, size);
-}
-
-TEST_F(SerializationUtilsTest, BadInputIsCaughtTest) {
- std::string input(
- base::StringPrintf("sparsehistogram%cname foo%c", '\0', '\0'));
- EXPECT_EQ(NULL, MetricSample::ParseSparseHistogram(input).get());
-}
-
-TEST_F(SerializationUtilsTest, MessageSeparatedByZero) {
- scoped_ptr<MetricSample> crash = MetricSample::CrashSample("mycrash");
-
- SerializationUtils::WriteMetricToFile(*crash.get(), filename);
- int64 size = 0;
- ASSERT_TRUE(base::GetFileSize(filepath, &size));
- // 4 bytes for the size
- // 5 bytes for crash
- // 7 bytes for mycrash
- // 2 bytes for the \0
- // -> total of 18
- EXPECT_EQ(size, 18);
-}
-
-TEST_F(SerializationUtilsTest, MessagesTooLongAreDiscardedTest) {
- // Creates a message that is bigger than the maximum allowed size.
- // As we are adding extra character (crash, \0s, etc), if the name is
- // kMessageMaxLength long, it will be too long.
- std::string name(SerializationUtils::kMessageMaxLength, 'c');
-
- scoped_ptr<MetricSample> crash = MetricSample::CrashSample(name);
- EXPECT_FALSE(SerializationUtils::WriteMetricToFile(*crash.get(), filename));
- int64 size = 0;
- ASSERT_TRUE(base::GetFileSize(filepath, &size));
- EXPECT_EQ(0, size);
-}
-
-TEST_F(SerializationUtilsTest, ReadLongMessageTest) {
- base::File test_file(filepath,
- base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
- std::string message(SerializationUtils::kMessageMaxLength + 1, 'c');
-
- int32 message_size = message.length() + sizeof(int32);
- test_file.WriteAtCurrentPos(reinterpret_cast<const char*>(&message_size),
- sizeof(message_size));
- test_file.WriteAtCurrentPos(message.c_str(), message.length());
- test_file.Close();
-
- scoped_ptr<MetricSample> crash = MetricSample::CrashSample("test");
- SerializationUtils::WriteMetricToFile(*crash.get(), filename);
-
- ScopedVector<MetricSample> samples;
- SerializationUtils::ReadAndTruncateMetricsFromFile(filename, &samples);
- ASSERT_EQ(size_t(1), samples.size());
- ASSERT_TRUE(samples[0] != NULL);
- EXPECT_TRUE(crash->IsEqual(*samples[0]));
-}
-
-TEST_F(SerializationUtilsTest, WriteReadTest) {
- scoped_ptr<MetricSample> hist =
- MetricSample::HistogramSample("myhist", 1, 2, 3, 4);
- scoped_ptr<MetricSample> crash = MetricSample::CrashSample("mycrash");
- scoped_ptr<MetricSample> lhist =
- MetricSample::LinearHistogramSample("linear", 1, 10);
- scoped_ptr<MetricSample> shist =
- MetricSample::SparseHistogramSample("mysparse", 30);
- scoped_ptr<MetricSample> action = MetricSample::UserActionSample("myaction");
-
- SerializationUtils::WriteMetricToFile(*hist.get(), filename);
- SerializationUtils::WriteMetricToFile(*crash.get(), filename);
- SerializationUtils::WriteMetricToFile(*lhist.get(), filename);
- SerializationUtils::WriteMetricToFile(*shist.get(), filename);
- SerializationUtils::WriteMetricToFile(*action.get(), filename);
- ScopedVector<MetricSample> vect;
- SerializationUtils::ReadAndTruncateMetricsFromFile(filename, &vect);
- ASSERT_EQ(vect.size(), size_t(5));
- for (int i = 0; i < 5; i++) {
- ASSERT_TRUE(vect[0] != NULL);
- }
- EXPECT_TRUE(hist->IsEqual(*vect[0]));
- EXPECT_TRUE(crash->IsEqual(*vect[1]));
- EXPECT_TRUE(lhist->IsEqual(*vect[2]));
- EXPECT_TRUE(shist->IsEqual(*vect[3]));
- EXPECT_TRUE(action->IsEqual(*vect[4]));
-
- int64 size = 0;
- ASSERT_TRUE(base::GetFileSize(filepath, &size));
- ASSERT_EQ(0, size);
-}
-
-} // namespace
-} // namespace metrics
diff --git a/metricsd/uploader/bn_metricsd_impl.cc b/metricsd/uploader/bn_metricsd_impl.cc
new file mode 100644
index 0000000..113a705
--- /dev/null
+++ b/metricsd/uploader/bn_metricsd_impl.cc
@@ -0,0 +1,106 @@
+/*
+ * 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 "uploader/bn_metricsd_impl.h"
+
+#include <base/metrics/histogram.h>
+#include <base/metrics/sparse_histogram.h>
+#include <base/metrics/statistics_recorder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+using android::binder::Status;
+using android::String16;
+
+static const char16_t kCrashTypeKernel[] = u"kernel";
+static const char16_t kCrashTypeUncleanShutdown[] = u"uncleanshutdown";
+static const char16_t kCrashTypeUser[] = u"user";
+
+BnMetricsdImpl::BnMetricsdImpl(const std::shared_ptr<CrashCounters>& counters)
+ : counters_(counters) {
+ CHECK(counters_);
+}
+
+void BnMetricsdImpl::Run() {
+ android::defaultServiceManager()->addService(getInterfaceDescriptor(), this);
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ android::IPCThreadState::self()->disableBackgroundScheduling(true);
+ android::IPCThreadState::self()->joinThreadPool();
+}
+
+Status BnMetricsdImpl::recordHistogram(
+ const String16& name, int sample, int min, int max, int nbuckets) {
+ base::HistogramBase* histogram = base::Histogram::FactoryGet(
+ android::String8(name).string(), min, max, nbuckets,
+ base::Histogram::kUmaTargetedHistogramFlag);
+ // |histogram| may be null if a client reports two contradicting histograms
+ // with the same name but different limits.
+ // FactoryGet will print a useful message if that is the case.
+ if (histogram) {
+ histogram->Add(sample);
+ }
+ return Status::ok();
+}
+
+Status BnMetricsdImpl::recordLinearHistogram(const String16& name,
+ int sample,
+ int max) {
+ base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+ android::String8(name).string(), 1, max, max + 1,
+ base::Histogram::kUmaTargetedHistogramFlag);
+ // |histogram| may be null if a client reports two contradicting histograms
+ // with the same name but different limits.
+ // FactoryGet will print a useful message if that is the case.
+ if (histogram) {
+ histogram->Add(sample);
+ }
+ return Status::ok();
+}
+
+Status BnMetricsdImpl::recordSparseHistogram(const String16& name, int sample) {
+ base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
+ android::String8(name).string(),
+ base::Histogram::kUmaTargetedHistogramFlag);
+ // |histogram| may be null if a client reports two contradicting histograms
+ // with the same name but different limits.
+ // FactoryGet will print a useful message if that is the case.
+ if (histogram) {
+ histogram->Add(sample);
+ }
+ return Status::ok();
+}
+
+Status BnMetricsdImpl::recordCrash(const String16& type) {
+ if (type == kCrashTypeUser) {
+ counters_->IncrementUserCrashCount();
+ } else if (type == kCrashTypeKernel) {
+ counters_->IncrementKernelCrashCount();
+ } else if (type == kCrashTypeUncleanShutdown) {
+ counters_->IncrementUncleanShutdownCount();
+ } else {
+ LOG(ERROR) << "Unknown crash type received: " << type;
+ }
+ return Status::ok();
+}
+
+Status BnMetricsdImpl::getHistogramsDump(String16* dump) {
+ std::string str_dump;
+ base::StatisticsRecorder::WriteGraph(std::string(), &str_dump);
+ *dump = String16(str_dump.c_str());
+ return Status::ok();
+}
diff --git a/metricsd/uploader/bn_metricsd_impl.h b/metricsd/uploader/bn_metricsd_impl.h
new file mode 100644
index 0000000..016ccb6
--- /dev/null
+++ b/metricsd/uploader/bn_metricsd_impl.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
+#define METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
+
+#include "android/brillo/metrics/BnMetricsd.h"
+#include "uploader/crash_counters.h"
+
+class BnMetricsdImpl : public android::brillo::metrics::BnMetricsd {
+ public:
+ explicit BnMetricsdImpl(const std::shared_ptr<CrashCounters>& counters);
+ virtual ~BnMetricsdImpl() = default;
+
+ // Starts the binder main loop.
+ void Run();
+
+ // Records a histogram.
+ android::binder::Status recordHistogram(const android::String16& name,
+ int sample,
+ int min,
+ int max,
+ int nbuckets) override;
+
+ // Records a linear histogram.
+ android::binder::Status recordLinearHistogram(const android::String16& name,
+ int sample,
+ int max) override;
+
+ // Records a sparse histogram.
+ android::binder::Status recordSparseHistogram(const android::String16& name,
+ int sample) override;
+
+ // Records a crash.
+ android::binder::Status recordCrash(const android::String16& type) override;
+
+ // Returns a dump of the histograms aggregated in memory.
+ android::binder::Status getHistogramsDump(android::String16* dump) override;
+
+ private:
+ std::shared_ptr<CrashCounters> counters_;
+};
+
+#endif // METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
diff --git a/metricsd/uploader/crash_counters.cc b/metricsd/uploader/crash_counters.cc
new file mode 100644
index 0000000..1478b9a
--- /dev/null
+++ b/metricsd/uploader/crash_counters.cc
@@ -0,0 +1,44 @@
+/*
+ * 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 "uploader/crash_counters.h"
+
+CrashCounters::CrashCounters()
+ : kernel_crashes_(0), unclean_shutdowns_(0), user_crashes_(0) {}
+
+void CrashCounters::IncrementKernelCrashCount() {
+ kernel_crashes_++;
+}
+
+unsigned int CrashCounters::GetAndResetKernelCrashCount() {
+ return kernel_crashes_.exchange(0);
+}
+
+void CrashCounters::IncrementUncleanShutdownCount() {
+ unclean_shutdowns_++;
+}
+
+unsigned int CrashCounters::GetAndResetUncleanShutdownCount() {
+ return unclean_shutdowns_.exchange(0);
+}
+
+void CrashCounters::IncrementUserCrashCount() {
+ user_crashes_++;
+}
+
+unsigned int CrashCounters::GetAndResetUserCrashCount() {
+ return user_crashes_.exchange(0);
+}
diff --git a/metricsd/uploader/crash_counters.h b/metricsd/uploader/crash_counters.h
new file mode 100644
index 0000000..3fdbf3f
--- /dev/null
+++ b/metricsd/uploader/crash_counters.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef METRICSD_UPLOADER_CRASH_COUNTERS_H_
+#define METRICSD_UPLOADER_CRASH_COUNTERS_H_
+
+#include <atomic>
+
+// This class is used to keep track of the crash counters.
+// An instance of it will be used by both the binder thread (to increment the
+// counters) and the uploader thread (to gather and reset the counters).
+// As such, the internal counters are atomic uints to allow concurrent access.
+class CrashCounters {
+ public:
+ CrashCounters();
+
+ void IncrementKernelCrashCount();
+ unsigned int GetAndResetKernelCrashCount();
+
+ void IncrementUserCrashCount();
+ unsigned int GetAndResetUserCrashCount();
+
+ void IncrementUncleanShutdownCount();
+ unsigned int GetAndResetUncleanShutdownCount();
+
+ private:
+ std::atomic_uint kernel_crashes_;
+ std::atomic_uint unclean_shutdowns_;
+ std::atomic_uint user_crashes_;
+};
+
+#endif // METRICSD_UPLOADER_CRASH_COUNTERS_H_
diff --git a/metricsd/uploader/metrics_log.cc b/metricsd/uploader/metrics_log.cc
index 1f16ca1..a01b5da 100644
--- a/metricsd/uploader/metrics_log.cc
+++ b/metricsd/uploader/metrics_log.cc
@@ -27,25 +27,25 @@
: MetricsLogBase("", 0, metrics::MetricsLogBase::ONGOING_LOG, "") {
}
-void MetricsLog::IncrementUserCrashCount() {
+void MetricsLog::IncrementUserCrashCount(unsigned int count) {
metrics::SystemProfileProto::Stability* stability(
uma_proto()->mutable_system_profile()->mutable_stability());
int current = stability->other_user_crash_count();
- stability->set_other_user_crash_count(current + 1);
+ stability->set_other_user_crash_count(current + count);
}
-void MetricsLog::IncrementKernelCrashCount() {
+void MetricsLog::IncrementKernelCrashCount(unsigned int count) {
metrics::SystemProfileProto::Stability* stability(
uma_proto()->mutable_system_profile()->mutable_stability());
int current = stability->kernel_crash_count();
- stability->set_kernel_crash_count(current + 1);
+ stability->set_kernel_crash_count(current + count);
}
-void MetricsLog::IncrementUncleanShutdownCount() {
+void MetricsLog::IncrementUncleanShutdownCount(unsigned int count) {
metrics::SystemProfileProto::Stability* stability(
uma_proto()->mutable_system_profile()->mutable_stability());
int current = stability->unclean_system_shutdown_count();
- stability->set_unclean_system_shutdown_count(current + 1);
+ stability->set_unclean_system_shutdown_count(current + count);
}
bool MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
diff --git a/metricsd/uploader/metrics_log.h b/metricsd/uploader/metrics_log.h
index 5e09070..b76cd72 100644
--- a/metricsd/uploader/metrics_log.h
+++ b/metricsd/uploader/metrics_log.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef METRICS_UPLOADER_METRICS_LOG_H_
-#define METRICS_UPLOADER_METRICS_LOG_H_
+#ifndef METRICSD_UPLOADER_METRICS_LOG_H_
+#define METRICSD_UPLOADER_METRICS_LOG_H_
#include <string>
@@ -34,15 +34,20 @@
// SystemProfileSetter.
MetricsLog();
- void IncrementUserCrashCount();
- void IncrementKernelCrashCount();
- void IncrementUncleanShutdownCount();
+ // Increment the crash counters in the protobuf.
+ // These methods don't have to be thread safe as metrics logs are only
+ // accessed by the uploader thread.
+ void IncrementUserCrashCount(unsigned int count);
+ void IncrementKernelCrashCount(unsigned int count);
+ void IncrementUncleanShutdownCount(unsigned int count);
// Populate the system profile with system information using setter.
bool PopulateSystemProfile(SystemProfileSetter* setter);
private:
+ friend class UploadServiceTest;
FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
+ FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts);
FRIEND_TEST(UploadServiceTest, LogKernelCrash);
FRIEND_TEST(UploadServiceTest, LogUncleanShutdown);
FRIEND_TEST(UploadServiceTest, LogUserCrash);
@@ -51,4 +56,4 @@
DISALLOW_COPY_AND_ASSIGN(MetricsLog);
};
-#endif // METRICS_UPLOADER_METRICS_LOG_H_
+#endif // METRICSD_UPLOADER_METRICS_LOG_H_
diff --git a/metricsd/uploader/upload_service.cc b/metricsd/uploader/upload_service.cc
index 3e0c503..ea8427a 100644
--- a/metricsd/uploader/upload_service.cc
+++ b/metricsd/uploader/upload_service.cc
@@ -33,8 +33,6 @@
#include <base/sha1.h>
#include "constants.h"
-#include "serialization/metric_sample.h"
-#include "serialization/serialization_utils.h"
#include "uploader/metrics_log.h"
#include "uploader/sender_http.h"
#include "uploader/system_profile_setter.h"
@@ -44,21 +42,19 @@
UploadService::UploadService(const std::string& server,
const base::TimeDelta& upload_interval,
const base::FilePath& private_metrics_directory,
- const base::FilePath& shared_metrics_directory)
+ const base::FilePath& shared_metrics_directory,
+ const std::shared_ptr<CrashCounters> counters)
: histogram_snapshot_manager_(this),
sender_(new HttpSender(server)),
failed_upload_count_(metrics::kFailedUploadCountName,
private_metrics_directory),
+ counters_(counters),
upload_interval_(upload_interval) {
- metrics_file_ =
- shared_metrics_directory.Append(metrics::kMetricsEventsFileName);
staged_log_path_ = private_metrics_directory.Append(metrics::kStagedLogName);
consent_file_ = shared_metrics_directory.Append(metrics::kConsentFileName);
}
int UploadService::OnInit() {
- base::StatisticsRecorder::Initialize();
-
system_profile_setter_.reset(new SystemProfileCache());
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
@@ -70,7 +66,6 @@
}
void UploadService::InitForTest(SystemProfileSetter* setter) {
- base::StatisticsRecorder::Initialize();
system_profile_setter_.reset(setter);
}
@@ -102,8 +97,7 @@
return;
}
- // Previous upload successful, reading metrics sample from the file.
- ReadMetrics();
+ // Previous upload successful, stage another log.
GatherHistograms();
StageCurrentLog();
@@ -143,76 +137,24 @@
failed_upload_count_.Set(0);
}
-void UploadService::ReadMetrics() {
- CHECK(!HasStagedLog()) << "cannot read metrics until the old logs have been "
- << "discarded";
-
- ScopedVector<metrics::MetricSample> vector;
- metrics::SerializationUtils::ReadAndTruncateMetricsFromFile(
- metrics_file_.value(), &vector);
-
- int i = 0;
- for (ScopedVector<metrics::MetricSample>::iterator it = vector.begin();
- it != vector.end(); it++) {
- metrics::MetricSample* sample = *it;
- AddSample(*sample);
- i++;
- }
- VLOG(1) << i << " samples read";
-}
-
-void UploadService::AddSample(const metrics::MetricSample& sample) {
- base::HistogramBase* counter;
- switch (sample.type()) {
- case metrics::MetricSample::CRASH:
- AddCrash(sample.name());
- break;
- case metrics::MetricSample::HISTOGRAM:
- counter = base::Histogram::FactoryGet(
- sample.name(), sample.min(), sample.max(), sample.bucket_count(),
- base::Histogram::kUmaTargetedHistogramFlag);
- counter->Add(sample.sample());
- break;
- case metrics::MetricSample::SPARSE_HISTOGRAM:
- counter = base::SparseHistogram::FactoryGet(
- sample.name(), base::HistogramBase::kUmaTargetedHistogramFlag);
- counter->Add(sample.sample());
- break;
- case metrics::MetricSample::LINEAR_HISTOGRAM:
- counter = base::LinearHistogram::FactoryGet(
- sample.name(),
- 1,
- sample.max(),
- sample.max() + 1,
- base::Histogram::kUmaTargetedHistogramFlag);
- counter->Add(sample.sample());
- break;
- case metrics::MetricSample::USER_ACTION:
- GetOrCreateCurrentLog()->RecordUserAction(sample.name());
- break;
- default:
- break;
- }
-}
-
-void UploadService::AddCrash(const std::string& crash_name) {
- if (crash_name == "user") {
- GetOrCreateCurrentLog()->IncrementUserCrashCount();
- } else if (crash_name == "kernel") {
- GetOrCreateCurrentLog()->IncrementKernelCrashCount();
- } else if (crash_name == "uncleanshutdown") {
- GetOrCreateCurrentLog()->IncrementUncleanShutdownCount();
- } else {
- DLOG(ERROR) << "crash name unknown" << crash_name;
- }
-}
-
void UploadService::GatherHistograms() {
base::StatisticsRecorder::Histograms histograms;
base::StatisticsRecorder::GetHistograms(&histograms);
histogram_snapshot_manager_.PrepareDeltas(
base::Histogram::kNoFlags, base::Histogram::kUmaTargetedHistogramFlag);
+
+ // Gather and reset the crash counters, shared with the binder threads.
+ unsigned int kernel_crashes = counters_->GetAndResetKernelCrashCount();
+ unsigned int unclean_shutdowns = counters_->GetAndResetUncleanShutdownCount();
+ unsigned int user_crashes = counters_->GetAndResetUserCrashCount();
+
+ // Only create a log if the counters have changed.
+ if (kernel_crashes > 0 || unclean_shutdowns > 0 || user_crashes > 0) {
+ GetOrCreateCurrentLog()->IncrementKernelCrashCount(kernel_crashes);
+ GetOrCreateCurrentLog()->IncrementUncleanShutdownCount(unclean_shutdowns);
+ GetOrCreateCurrentLog()->IncrementUserCrashCount(user_crashes);
+ }
}
void UploadService::RecordDelta(const base::HistogramBase& histogram,
diff --git a/metricsd/uploader/upload_service.h b/metricsd/uploader/upload_service.h
index eed0d9d..fe064b8 100644
--- a/metricsd/uploader/upload_service.h
+++ b/metricsd/uploader/upload_service.h
@@ -25,20 +25,12 @@
#include <brillo/daemons/daemon.h>
#include "persistent_integer.h"
+#include "uploader/crash_counters.h"
#include "uploader/metrics_log.h"
+#include "uploader/proto/chrome_user_metrics_extension.pb.h"
#include "uploader/sender.h"
#include "uploader/system_profile_cache.h"
-namespace metrics {
-class ChromeUserMetricsExtension;
-class CrashSample;
-class HistogramSample;
-class LinearHistogramSample;
-class MetricSample;
-class SparseHistogramSample;
-class UserActionSample;
-}
-
class SystemProfileSetter;
// Service responsible for uploading the metrics periodically to the server.
@@ -57,22 +49,21 @@
// - if the upload is successful, we discard the log (therefore
// transitioning back to no staged log)
// - if the upload fails, we keep the log to try again later.
-// We do not try to read the metrics that are stored on
-// the disk as we want to avoid storing the metrics in memory.
//
// * if no staged logs are present:
-// Read all metrics from the disk, aggregate them and try to send them.
+// Take a snapshot of the aggregated metrics, save it to disk and try to send
+// it:
// - if the upload succeeds, we discard the staged log (transitioning back
// to the no staged log state)
-// - if the upload fails, we keep the staged log in memory to retry
-// uploading later.
+// - if the upload fails, we continue and will retry to upload later.
//
class UploadService : public base::HistogramFlattener, public brillo::Daemon {
public:
UploadService(const std::string& server,
const base::TimeDelta& upload_interval,
const base::FilePath& private_metrics_directory,
- const base::FilePath& shared_metrics_directory);
+ const base::FilePath& shared_metrics_directory,
+ const std::shared_ptr<CrashCounters> counters);
// Initializes the upload service.
int OnInit();
@@ -106,6 +97,7 @@
FRIEND_TEST(UploadServiceTest, EmptyLogsAreNotSent);
FRIEND_TEST(UploadServiceTest, FailedSendAreRetried);
FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
+ FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts);
FRIEND_TEST(UploadServiceTest, LogEmptyAfterUpload);
FRIEND_TEST(UploadServiceTest, LogEmptyByDefault);
FRIEND_TEST(UploadServiceTest, LogFromTheMetricsLibrary);
@@ -125,15 +117,6 @@
// Resets the internal state.
void Reset();
- // Reads all the metrics from the disk.
- void ReadMetrics();
-
- // Adds a generic sample to the current log.
- void AddSample(const metrics::MetricSample& sample);
-
- // Adds a crash to the current log.
- void AddCrash(const std::string& crash_name);
-
// Returns true iff metrics reporting is enabled.
bool AreMetricsEnabled();
@@ -163,11 +146,11 @@
scoped_ptr<Sender> sender_;
chromeos_metrics::PersistentInteger failed_upload_count_;
scoped_ptr<MetricsLog> current_log_;
+ std::shared_ptr<CrashCounters> counters_;
base::TimeDelta upload_interval_;
base::FilePath consent_file_;
- base::FilePath metrics_file_;
base::FilePath staged_log_path_;
bool testing_;
diff --git a/metricsd/uploader/upload_service_test.cc b/metricsd/uploader/upload_service_test.cc
index 9fc5e71..0e2ba8f 100644
--- a/metricsd/uploader/upload_service_test.cc
+++ b/metricsd/uploader/upload_service_test.cc
@@ -20,12 +20,12 @@
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
+#include <base/metrics/sparse_histogram.h>
+#include <base/metrics/statistics_recorder.h>
#include <base/sys_info.h>
#include "constants.h"
-#include "metrics/metrics_library_mock.h"
#include "persistent_integer.h"
-#include "serialization/metric_sample.h"
#include "uploader/metrics_log.h"
#include "uploader/mock/mock_system_profile_setter.h"
#include "uploader/mock/sender_mock.h"
@@ -39,6 +39,10 @@
protected:
virtual void SetUp() {
CHECK(dir_.CreateUniqueTempDir());
+ // Make sure the statistics recorder is inactive (contains no metrics) then
+ // initialize it.
+ ASSERT_FALSE(base::StatisticsRecorder::IsActive());
+ base::StatisticsRecorder::Initialize();
base::FilePath private_dir = dir_.path().Append("private");
base::FilePath shared_dir = dir_.path().Append("shared");
@@ -46,11 +50,12 @@
EXPECT_TRUE(base::CreateDirectory(private_dir));
EXPECT_TRUE(base::CreateDirectory(shared_dir));
- metrics_lib_.InitForTest(shared_dir);
ASSERT_EQ(0, base::WriteFile(shared_dir.Append(metrics::kConsentFileName),
"", 0));
- upload_service_.reset(
- new UploadService("", base::TimeDelta(), private_dir, shared_dir));
+ counters_.reset(new CrashCounters);
+
+ upload_service_.reset(new UploadService("", base::TimeDelta(), private_dir,
+ shared_dir, counters_));
upload_service_->sender_.reset(new SenderMock);
upload_service_->InitForTest(new MockSystemProfileSetter);
@@ -58,8 +63,17 @@
upload_service_->Reset();
}
- scoped_ptr<metrics::MetricSample> Crash(const std::string& name) {
- return metrics::MetricSample::CrashSample(name);
+ void SendSparseHistogram(const std::string& name, int sample) {
+ base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
+ name, base::Histogram::kUmaTargetedHistogramFlag);
+ histogram->Add(sample);
+ }
+
+ void SendHistogram(
+ const std::string& name, int sample, int min, int max, int nbuckets) {
+ base::HistogramBase* histogram = base::Histogram::FactoryGet(
+ name, min, max, nbuckets, base::Histogram::kUmaTargetedHistogramFlag);
+ histogram->Add(sample);
}
void SetTestingProperty(const std::string& name, const std::string& value) {
@@ -71,57 +85,26 @@
base::WriteFile(filepath, value.data(), value.size()));
}
+ const metrics::SystemProfileProto_Stability GetCurrentStability() {
+ EXPECT_TRUE(upload_service_->current_log_);
+
+ return upload_service_->current_log_->uma_proto()->system_profile().stability();
+ }
+
base::ScopedTempDir dir_;
scoped_ptr<UploadService> upload_service_;
- MetricsLibrary metrics_lib_;
scoped_ptr<base::AtExitManager> exit_manager_;
+ std::shared_ptr<CrashCounters> counters_;
};
-// Tests that the right crash increments a values.
-TEST_F(UploadServiceTest, LogUserCrash) {
- upload_service_->AddSample(*Crash("user").get());
-
- MetricsLog* log = upload_service_->current_log_.get();
- metrics::ChromeUserMetricsExtension* proto = log->uma_proto();
-
- EXPECT_EQ(1, proto->system_profile().stability().other_user_crash_count());
-}
-
-TEST_F(UploadServiceTest, LogUncleanShutdown) {
- upload_service_->AddSample(*Crash("uncleanshutdown"));
-
- EXPECT_EQ(1, upload_service_->current_log_
- ->uma_proto()
- ->system_profile()
- .stability()
- .unclean_system_shutdown_count());
-}
-
-TEST_F(UploadServiceTest, LogKernelCrash) {
- upload_service_->AddSample(*Crash("kernel"));
-
- EXPECT_EQ(1, upload_service_->current_log_
- ->uma_proto()
- ->system_profile()
- .stability()
- .kernel_crash_count());
-}
-
-TEST_F(UploadServiceTest, UnknownCrashIgnored) {
- upload_service_->AddSample(*Crash("foo"));
-
- // The log should be empty.
- EXPECT_FALSE(upload_service_->current_log_);
-}
-
TEST_F(UploadServiceTest, FailedSendAreRetried) {
SenderMock* sender = new SenderMock();
upload_service_->sender_.reset(sender);
sender->set_should_succeed(false);
- upload_service_->AddSample(*Crash("user"));
+ SendSparseHistogram("hello", 1);
upload_service_->UploadEvent();
EXPECT_EQ(1, sender->send_call_count());
std::string sent_string = sender->last_message();
@@ -137,7 +120,7 @@
sender->set_should_succeed(false);
- upload_service_->AddSample(*Crash("user"));
+ SendSparseHistogram("hello", 1);
for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
upload_service_->UploadEvent();
@@ -148,7 +131,7 @@
EXPECT_FALSE(upload_service_->HasStagedLog());
// Log a new sample. The failed upload counter should be reset.
- upload_service_->AddSample(*Crash("user"));
+ SendSparseHistogram("hello", 1);
for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
upload_service_->UploadEvent();
}
@@ -165,7 +148,8 @@
}
TEST_F(UploadServiceTest, LogEmptyByDefault) {
- UploadService upload_service("", base::TimeDelta(), dir_.path(), dir_.path());
+ UploadService upload_service("", base::TimeDelta(), dir_.path(), dir_.path(),
+ std::make_shared<CrashCounters>());
// current_log_ should be initialized later as it needs AtExitManager to exit
// in order to gather system information from SysInfo.
@@ -176,34 +160,28 @@
SenderMock* sender = new SenderMock();
upload_service_->sender_.reset(sender);
- upload_service_->AddSample(*Crash("user"));
+ SendSparseHistogram("hello", 1);
+
upload_service_->UploadEvent();
std::string first_message = sender->last_message();
+ SendSparseHistogram("hello", 2);
- upload_service_->AddSample(*Crash("kernel"));
upload_service_->UploadEvent();
EXPECT_NE(first_message, sender->last_message());
}
TEST_F(UploadServiceTest, LogEmptyAfterUpload) {
- upload_service_->AddSample(*Crash("user"));
-
- EXPECT_TRUE(upload_service_->current_log_);
+ SendSparseHistogram("hello", 2);
upload_service_->UploadEvent();
EXPECT_FALSE(upload_service_->current_log_);
}
TEST_F(UploadServiceTest, LogContainsAggregatedValues) {
- scoped_ptr<metrics::MetricSample> histogram =
- metrics::MetricSample::HistogramSample("foo", 10, 0, 42, 10);
- upload_service_->AddSample(*histogram.get());
-
- scoped_ptr<metrics::MetricSample> histogram2 =
- metrics::MetricSample::HistogramSample("foo", 11, 0, 42, 10);
- upload_service_->AddSample(*histogram2.get());
+ SendHistogram("foo", 11, 0, 42, 10);
+ SendHistogram("foo", 12, 0, 42, 10);
upload_service_->GatherHistograms();
metrics::ChromeUserMetricsExtension* proto =
@@ -211,6 +189,37 @@
EXPECT_EQ(1, proto->histogram_event().size());
}
+TEST_F(UploadServiceTest, LogContainsCrashCounts) {
+ // By default, there is no current log.
+ upload_service_->GatherHistograms();
+ EXPECT_FALSE(upload_service_->current_log_);
+
+ // If the user crash counter is incremented, we add the count to the current
+ // log.
+ counters_->IncrementUserCrashCount();
+ upload_service_->GatherHistograms();
+ EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
+
+ // If the kernel crash counter is incremented, we add the count to the current
+ // log.
+ counters_->IncrementKernelCrashCount();
+ upload_service_->GatherHistograms();
+ EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
+
+ // If the kernel crash counter is incremented, we add the count to the current
+ // log.
+ counters_->IncrementUncleanShutdownCount();
+ counters_->IncrementUncleanShutdownCount();
+ upload_service_->GatherHistograms();
+ EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
+
+ // If no counter is incremented, the reported numbers don't change.
+ upload_service_->GatherHistograms();
+ EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
+ EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
+ EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
+}
+
TEST_F(UploadServiceTest, ExtractChannelFromString) {
EXPECT_EQ(
SystemProfileCache::ProtoChannelFromString(
@@ -234,13 +243,12 @@
SetTestingProperty(metrics::kProductId, "hello");
SetTestingProperty(metrics::kProductVersion, "1.2.3.4");
- scoped_ptr<metrics::MetricSample> histogram =
- metrics::MetricSample::SparseHistogramSample("myhistogram", 1);
+ SendSparseHistogram("hello", 1);
+
// Reset to create the new log with the profile setter.
upload_service_->system_profile_setter_.reset(
new SystemProfileCache(true, dir_.path()));
upload_service_->Reset();
- upload_service_->AddSample(*histogram.get());
upload_service_->UploadEvent();
EXPECT_EQ(1, sender->send_call_count());
@@ -281,21 +289,6 @@
EXPECT_EQ(cache.profile_.session_id, session_id + 1);
}
-// Test that we can log metrics from the metrics library and have the uploader
-// upload them.
-TEST_F(UploadServiceTest, LogFromTheMetricsLibrary) {
- SenderMock* sender = new SenderMock();
- upload_service_->sender_.reset(sender);
-
- upload_service_->UploadEvent();
- EXPECT_EQ(0, sender->send_call_count());
-
- metrics_lib_.SendEnumToUMA("testname", 2, 10);
- upload_service_->UploadEvent();
-
- EXPECT_EQ(1, sender->send_call_count());
-}
-
// The product id must be set for metrics to be uploaded.
// If it is not set, the system profile cache should fail to initialize.
TEST_F(UploadServiceTest, ProductIdMandatory) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a0b1acf..b40b9ba 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -138,23 +138,27 @@
# sets up initial cpusets for ActivityManager
mkdir /dev/cpuset
mount cpuset none /dev/cpuset
- mkdir /dev/cpuset/foreground
- mkdir /dev/cpuset/foreground/boost
- mkdir /dev/cpuset/background
- # system-background is for system tasks that should only run on
- # little cores, not on bigs
- # to be used only by init, so don't change the permissions
- mkdir /dev/cpuset/system-background
+
# this ensures that the cpusets are present and usable, but the device's
# init.rc must actually set the correct cpus
+ mkdir /dev/cpuset/foreground
write /dev/cpuset/foreground/cpus 0
- write /dev/cpuset/foreground/boost/cpus 0
- write /dev/cpuset/background/cpus 0
- write /dev/cpuset/system-background/cpus 0
write /dev/cpuset/foreground/mems 0
+ mkdir /dev/cpuset/foreground/boost
+ write /dev/cpuset/foreground/boost/cpus 0
write /dev/cpuset/foreground/boost/mems 0
+ mkdir /dev/cpuset/background
+ write /dev/cpuset/background/cpus 0
write /dev/cpuset/background/mems 0
+
+ # system-background is for system tasks that should only run on
+ # little cores, not on bigs
+ # to be used only by init, so don't change system-bg permissions
+ mkdir /dev/cpuset/system-background
+ write /dev/cpuset/system-background/cpus 0
write /dev/cpuset/system-background/mems 0
+
+ # change permissions for all cpusets we'll touch at runtime
chown system system /dev/cpuset
chown system system /dev/cpuset/foreground
chown system system /dev/cpuset/foreground/boost
@@ -244,6 +248,9 @@
# Mount default storage into root namespace
mount none /mnt/runtime/default /storage slave bind rec
+ # Make sure /sys/kernel/debug (if present) is labeled properly
+ restorecon_recursive /sys/kernel/debug
+
# We chown/chmod /cache again so because mount is run as root + defaults
chown system cache /cache
chmod 0770 /cache
diff --git a/tzdatacheck/tzdatacheck.cpp b/tzdatacheck/tzdatacheck.cpp
index 31f7b55..c1ab2ac 100644
--- a/tzdatacheck/tzdatacheck.cpp
+++ b/tzdatacheck/tzdatacheck.cpp
@@ -27,7 +27,7 @@
#include <string>
#include <vector>
-#include "base/logging.h"
+#include "android-base/logging.h"
static const char* TZDATA_FILENAME = "/tzdata";
// tzdata file header (as much as we need for the version):