Merge "Lose ls to toybox."
diff --git a/adb/Android.mk b/adb/Android.mk
index f9d4441..bbdc2ea 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -5,12 +5,6 @@
LOCAL_PATH:= $(call my-dir)
-ifeq ($(HOST_OS),windows)
- adb_host_clang := false # libc++ for mingw not ready yet.
-else
- adb_host_clang := true
-endif
-
adb_host_sanitize :=
adb_target_sanitize :=
@@ -29,8 +23,6 @@
ADB_COMMON_windows_CFLAGS := \
-DUNICODE=1 -D_UNICODE=1 \
-ADB_COMMON_CFLAGS += $(ADB_COMMON_$(HOST_OS)_CFLAGS)
-
# libadb
# =========================================================
@@ -63,7 +55,8 @@
LIBADB_linux_CFLAGS := \
-std=c++14 \
-LIBADB_CFLAGS += $(LIBADB_$(HOST_OS)_CFLAGS)
+LIBADB_windows_CFLAGS := \
+ $(ADB_COMMON_windows_CFLAGS) \
LIBADB_darwin_SRC_FILES := \
fdevent.cpp \
@@ -79,6 +72,12 @@
sysdeps_win32.cpp \
usb_windows.cpp \
+LIBADB_TEST_linux_SRCS := \
+ fdevent_test.cpp \
+
+LIBADB_TEST_darwin_SRCS := \
+ fdevent_test.cpp \
+
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_MODULE := libadbd
@@ -91,7 +90,6 @@
usb_linux_client.cpp \
LOCAL_SANITIZE := $(adb_target_sanitize)
-LOCAL_SHARED_LIBRARIES := libbase
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
@@ -100,24 +98,27 @@
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
-LOCAL_CLANG := $(adb_host_clang)
LOCAL_MODULE := libadb
+LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=1
+LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
+LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
LOCAL_SRC_FILES := \
$(LIBADB_SRC_FILES) \
- $(LIBADB_$(HOST_OS)_SRC_FILES) \
adb_auth_host.cpp \
+LOCAL_SRC_FILES_darwin := $(LIBADB_darwin_SRC_FILES)
+LOCAL_SRC_FILES_linux := $(LIBADB_linux_SRC_FILES)
+LOCAL_SRC_FILES_windows := $(LIBADB_windows_SRC_FILES)
+
LOCAL_SANITIZE := $(adb_host_sanitize)
-LOCAL_SHARED_LIBRARIES := libbase
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
LOCAL_STATIC_LIBRARIES := libcrypto_static libbase
-ifeq ($(HOST_OS),windows)
- LOCAL_C_INCLUDES += development/host/windows/usb/api/
-else
+LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
+ifneq ($(HOST_OS),windows)
LOCAL_MULTILIB := 64
endif
@@ -127,7 +128,10 @@
LOCAL_CLANG := true
LOCAL_MODULE := adbd_test
LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS)
-LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS)
+LOCAL_SRC_FILES := \
+ $(LIBADB_TEST_SRCS) \
+ $(LIBADB_TEST_linux_SRCS) \
+
LOCAL_SANITIZE := $(adb_target_sanitize)
LOCAL_STATIC_LIBRARIES := libadbd
LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
@@ -137,10 +141,13 @@
# =========================================================
include $(CLEAR_VARS)
-LOCAL_CLANG := $(adb_host_clang)
LOCAL_MODULE := adb_test
LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
+LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
+LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.cpp
+LOCAL_SRC_FILES_linux := $(LIBADB_TEST_linux_SRCS)
+LOCAL_SRC_FILES_darwin := $(LIBADB_TEST_darwin_SRCS)
LOCAL_SANITIZE := $(adb_host_sanitize)
LOCAL_SHARED_LIBRARIES := liblog libbase
LOCAL_STATIC_LIBRARIES := \
@@ -148,18 +155,10 @@
libcrypto_static \
libcutils \
-ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -ldl -lpthread
-endif
-
-ifeq ($(HOST_OS),darwin)
- LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
-endif
-
-ifeq ($(HOST_OS),windows)
- LOCAL_LDLIBS += -lws2_32 -luserenv
- LOCAL_STATIC_LIBRARIES += AdbWinApi
-endif
+LOCAL_LDLIBS_linux := -lrt -ldl -lpthread
+LOCAL_LDLIBS_darwin := -framework CoreFoundation -framework IOKit
+LOCAL_LDLIBS_windows := -lws2_32 -luserenv
+LOCAL_STATIC_LIBRARIES_windows := AdbWinApi
include $(BUILD_HOST_NATIVE_TEST)
@@ -168,9 +167,10 @@
ifeq ($(HOST_OS),linux)
include $(CLEAR_VARS)
-LOCAL_CLANG := $(adb_host_clang)
LOCAL_MODULE := adb_device_tracker_test
LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
+LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
+LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
LOCAL_SRC_FILES := test_track_devices.cpp
LOCAL_SANITIZE := $(adb_host_sanitize)
LOCAL_SHARED_LIBRARIES := liblog libbase
@@ -183,24 +183,16 @@
# =========================================================
include $(CLEAR_VARS)
-ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -ldl -lpthread
- LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
-endif
+LOCAL_LDLIBS_linux := -lrt -ldl -lpthread
-ifeq ($(HOST_OS),darwin)
- LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
- LOCAL_CFLAGS += -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
-endif
+LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
+LOCAL_CFLAGS_darwin := -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
-ifeq ($(HOST_OS),windows)
- # Use wmain instead of main
- LOCAL_LDFLAGS += -municode
- LOCAL_LDLIBS += -lws2_32 -lgdi32
- EXTRA_STATIC_LIBS := AdbWinApi
-endif
-
-LOCAL_CLANG := $(adb_host_clang)
+# Use wmain instead of main
+LOCAL_LDFLAGS_windows := -municode
+LOCAL_LDLIBS_windows := -lws2_32 -lgdi32
+LOCAL_STATIC_LIBRARIES_windows := AdbWinApi
+LOCAL_REQUIRED_MODULES_windows := AdbWinApi AdbWinUsbApi
LOCAL_SRC_FILES := \
client/main.cpp \
@@ -215,8 +207,12 @@
-D_GNU_SOURCE \
-DADB_HOST=1 \
+LOCAL_CFLAGS_windows := \
+ $(ADB_COMMON_windows_CFLAGS)
+
LOCAL_MODULE := adb
LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_SANITIZE := $(adb_host_sanitize)
LOCAL_STATIC_LIBRARIES := \
@@ -225,12 +221,8 @@
libcrypto_static \
libcutils \
liblog \
- $(EXTRA_STATIC_LIBS) \
-# libc++ not available on windows yet
-ifneq ($(HOST_OS),windows)
- LOCAL_CXX_STL := libc++_static
-endif
+LOCAL_CXX_STL := libc++_static
# Don't add anything here, we don't want additional shared dependencies
# on the host adb tool, and shared libraries that link against libc++
@@ -241,12 +233,6 @@
$(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))
-ifeq ($(HOST_OS),windows)
-$(LOCAL_INSTALLED_MODULE): \
- $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll \
- $(HOST_OUT_EXECUTABLES)/AdbWinUsbApi.dll
-endif
-
# adbd device daemon
# =========================================================
diff --git a/adb/adb.cpp b/adb/adb.cpp
index eb01da8..14df8a1 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -53,8 +53,6 @@
#include <sys/mount.h>
#endif
-ADB_MUTEX_DEFINE(D_lock);
-
#if !ADB_HOST
const char* adb_device_banner = "device";
static android::base::LogdLogger gLogdLogger;
@@ -184,7 +182,7 @@
for (const auto& elem : elements) {
const auto& flag = trace_flags.find(elem);
if (flag == trace_flags.end()) {
- D("Unknown trace flag: %s\n", flag->first.c_str());
+ D("Unknown trace flag: %s", flag->first.c_str());
continue;
}
@@ -234,13 +232,13 @@
void handle_online(atransport *t)
{
- D("adb: online\n");
+ D("adb: online");
t->online = 1;
}
void handle_offline(atransport *t)
{
- D("adb: offline\n");
+ D("adb: offline");
//Close the associated usb
t->online = 0;
@@ -294,7 +292,7 @@
static void send_ready(unsigned local, unsigned remote, atransport *t)
{
- D("Calling send_ready \n");
+ D("Calling send_ready");
apacket *p = get_apacket();
p->msg.command = A_OKAY;
p->msg.arg0 = local;
@@ -304,7 +302,7 @@
static void send_close(unsigned local, unsigned remote, atransport *t)
{
- D("Calling send_close \n");
+ D("Calling send_close");
apacket *p = get_apacket();
p->msg.command = A_CLSE;
p->msg.arg0 = local;
@@ -339,7 +337,7 @@
}
void send_connect(atransport* t) {
- D("Calling send_connect \n");
+ D("Calling send_connect");
apacket* cp = get_apacket();
cp->msg.command = A_CNXN;
cp->msg.arg0 = t->get_protocol_version();
@@ -369,7 +367,7 @@
}
void parse_banner(const std::string& banner, atransport* t) {
- D("parse_banner: %s\n", banner.c_str());
+ D("parse_banner: %s", banner.c_str());
// The format is something like:
// "device::ro.product.name=x;ro.product.model=y;ro.product.device=z;".
@@ -402,23 +400,23 @@
const std::string& type = pieces[0];
if (type == "bootloader") {
- D("setting connection_state to kCsBootloader\n");
+ D("setting connection_state to kCsBootloader");
t->connection_state = kCsBootloader;
update_transports();
} else if (type == "device") {
- D("setting connection_state to kCsDevice\n");
+ D("setting connection_state to kCsDevice");
t->connection_state = kCsDevice;
update_transports();
} else if (type == "recovery") {
- D("setting connection_state to kCsRecovery\n");
+ D("setting connection_state to kCsRecovery");
t->connection_state = kCsRecovery;
update_transports();
} else if (type == "sideload") {
- D("setting connection_state to kCsSideload\n");
+ D("setting connection_state to kCsSideload");
t->connection_state = kCsSideload;
update_transports();
} else {
- D("setting connection_state to kCsHost\n");
+ D("setting connection_state to kCsHost");
t->connection_state = kCsHost;
}
}
@@ -450,7 +448,7 @@
{
asocket *s;
- D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
+ D("handle_packet() %c%c%c%c", ((char*) (&(p->msg.command)))[0],
((char*) (&(p->msg.command)))[1],
((char*) (&(p->msg.command)))[2],
((char*) (&(p->msg.command)))[3]);
@@ -526,7 +524,7 @@
/* Other READY messages must use the same local-id */
s->ready(s);
} else {
- D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
+ D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s",
p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
}
}
@@ -547,7 +545,7 @@
* socket has a peer on the same transport.
*/
if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
- D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
+ D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s",
p->msg.arg1, t->serial, s->peer->transport->serial);
} else {
s->close(s);
@@ -563,7 +561,7 @@
p->len = p->msg.data_length;
if(s->enqueue(s, p) == 0) {
- D("Enqueue the socket\n");
+ D("Enqueue the socket");
send_ready(s->id, rid, t);
}
return;
@@ -1125,9 +1123,9 @@
if (!strncmp(service, "devices", 7)) {
bool long_listing = (strcmp(service+7, "-l") == 0);
if (long_listing || service[7] == 0) {
- D("Getting device list...\n");
+ D("Getting device list...");
std::string device_list = list_transports(long_listing);
- D("Sending device list...\n");
+ D("Sending device list...");
return SendOkay(reply_fd, device_list);
}
return 1;
diff --git a/adb/adb_auth.cpp b/adb/adb_auth.cpp
index 8a6b156..2364f7b 100644
--- a/adb/adb_auth.cpp
+++ b/adb/adb_auth.cpp
@@ -32,13 +32,13 @@
void send_auth_request(atransport *t)
{
- D("Calling send_auth_request\n");
+ D("Calling send_auth_request");
apacket *p;
int ret;
ret = adb_auth_generate_token(t->token, sizeof(t->token));
if (ret != sizeof(t->token)) {
- D("Error generating token ret=%d\n", ret);
+ D("Error generating token ret=%d", ret);
return;
}
@@ -52,13 +52,13 @@
void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
{
- D("Calling send_auth_response\n");
+ D("Calling send_auth_response");
apacket *p = get_apacket();
int ret;
ret = adb_auth_sign(t->key, token, token_size, p->data);
if (!ret) {
- D("Error signing the token\n");
+ D("Error signing the token");
put_apacket(p);
return;
}
@@ -71,13 +71,13 @@
void send_auth_publickey(atransport *t)
{
- D("Calling send_auth_publickey\n");
+ D("Calling send_auth_publickey");
apacket *p = get_apacket();
int ret;
ret = adb_auth_get_userkey(p->data, MAX_PAYLOAD_V1);
if (!ret) {
- D("Failed to get user public key\n");
+ D("Failed to get user public key");
put_apacket(p);
return;
}
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index c3af024..cedc847 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -60,7 +60,7 @@
f = fopen(file, "re");
if (!f) {
- D("Can't open '%s'\n", file);
+ D("Can't open '%s'", file);
return;
}
@@ -69,7 +69,7 @@
auto key = reinterpret_cast<adb_public_key*>(
calloc(1, sizeof(adb_public_key) + 4));
if (key == nullptr) {
- D("Can't malloc key\n");
+ D("Can't malloc key");
break;
}
@@ -79,13 +79,13 @@
ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4);
if (ret != sizeof(key->key)) {
- D("%s: Invalid base64 data ret=%d\n", file, ret);
+ D("%s: Invalid base64 data ret=%d", file, ret);
free(key);
continue;
}
if (key->key.len != RSANUMWORDS) {
- D("%s: Invalid key len %d\n", file, key->key.len);
+ D("%s: Invalid key len %d", file, key->key.len);
free(key);
continue;
}
@@ -117,7 +117,7 @@
while ((path = *paths++)) {
if (!stat(path, &buf)) {
- D("Loading keys from '%s'\n", path);
+ D("Loading keys from '%s'", path);
read_keys(path, list);
}
}
@@ -163,7 +163,7 @@
static void usb_disconnected(void* unused, atransport* t)
{
- D("USB disconnect\n");
+ D("USB disconnect");
usb_transport = NULL;
needs_retry = false;
}
@@ -176,7 +176,7 @@
if (events & FDE_READ) {
ret = unix_read(fd, response, sizeof(response));
if (ret <= 0) {
- D("Framework disconnect\n");
+ D("Framework disconnect");
if (usb_transport)
fdevent_remove(&usb_transport->auth_fde);
framework_fd = -1;
@@ -199,26 +199,26 @@
}
if (framework_fd < 0) {
- D("Client not connected\n");
+ D("Client not connected");
needs_retry = true;
return;
}
if (key[len - 1] != '\0') {
- D("Key must be a null-terminated string\n");
+ D("Key must be a null-terminated string");
return;
}
ret = snprintf(msg, sizeof(msg), "PK%s", key);
if (ret >= (signed)sizeof(msg)) {
- D("Key too long. ret=%d\n", ret);
+ D("Key too long. ret=%d", ret);
return;
}
- D("Sending '%s'\n", msg);
+ D("Sending '%s'", msg);
ret = unix_write(framework_fd, msg, ret);
if (ret < 0) {
- D("Failed to write PK, errno=%d\n", errno);
+ D("Failed to write PK, errno=%d", errno);
return;
}
@@ -236,7 +236,7 @@
s = adb_socket_accept(fd, &addr, &alen);
if (s < 0) {
- D("Failed to accept: errno=%d\n", errno);
+ D("Failed to accept: errno=%d", errno);
return;
}
@@ -251,7 +251,7 @@
void adbd_cloexec_auth_socket() {
int fd = android_get_control_socket("adbd");
if (fd == -1) {
- D("Failed to get adbd socket\n");
+ D("Failed to get adbd socket");
return;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -260,12 +260,12 @@
void adbd_auth_init(void) {
int fd = android_get_control_socket("adbd");
if (fd == -1) {
- D("Failed to get adbd socket\n");
+ D("Failed to get adbd socket");
return;
}
if (listen(fd, 4) == -1) {
- D("Failed to listen on '%d'\n", fd);
+ D("Failed to listen on '%d'", fd);
return;
}
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index e7f82a9..749fec2 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -164,26 +164,26 @@
if (snprintf(path, sizeof(path), "%s.pub", private_key_path) >=
(int)sizeof(path)) {
- D("Path too long while writing public key\n");
+ D("Path too long while writing public key");
return 0;
}
if (!RSA_to_RSAPublicKey(private_key, &pkey)) {
- D("Failed to convert to publickey\n");
+ D("Failed to convert to publickey");
return 0;
}
outfile = fopen(path, "w");
if (!outfile) {
- D("Failed to open '%s'\n", path);
+ D("Failed to open '%s'", path);
return 0;
}
- D("Writing public key to '%s'\n", path);
+ D("Writing public key to '%s'", path);
#if defined(OPENSSL_IS_BORINGSSL)
if (!EVP_EncodedLength(&encoded_length, sizeof(pkey))) {
- D("Public key too large to base64 encode\n");
+ D("Public key too large to base64 encode");
goto out;
}
#else
@@ -194,7 +194,7 @@
encoded = new uint8_t[encoded_length];
if (encoded == nullptr) {
- D("Allocation failure\n");
+ D("Allocation failure");
goto out;
}
@@ -203,7 +203,7 @@
if (fwrite(encoded, encoded_length, 1, outfile) != 1 ||
fwrite(info, strlen(info), 1, outfile) != 1) {
- D("Write error while writing public key\n");
+ D("Write error while writing public key");
goto out;
}
@@ -226,10 +226,10 @@
FILE *f = NULL;
int ret = 0;
- D("generate_key '%s'\n", file);
+ D("generate_key '%s'", file);
if (!pkey || !exponent || !rsa) {
- D("Failed to allocate key\n");
+ D("Failed to allocate key");
goto out;
}
@@ -241,7 +241,7 @@
f = fopen(file, "w");
if (!f) {
- D("Failed to open '%s'\n", file);
+ D("Failed to open '%s'", file);
umask(old_mask);
goto out;
}
@@ -249,12 +249,12 @@
umask(old_mask);
if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
- D("Failed to write key\n");
+ D("Failed to write key");
goto out;
}
if (!write_public_keyfile(rsa, file)) {
- D("Failed to write public key\n");
+ D("Failed to write public key");
goto out;
}
@@ -271,11 +271,11 @@
static int read_key(const char *file, struct listnode *list)
{
- D("read_key '%s'\n", file);
+ D("read_key '%s'", file);
FILE* fp = fopen(file, "r");
if (!fp) {
- D("Failed to open '%s': %s\n", file, strerror(errno));
+ D("Failed to open '%s': %s", file, strerror(errno));
return 0;
}
@@ -283,7 +283,7 @@
key->rsa = RSA_new();
if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
- D("Failed to read key\n");
+ D("Failed to read key");
fclose(fp);
RSA_free(key->rsa);
delete key;
@@ -307,7 +307,7 @@
WCHAR path[MAX_PATH];
const HRESULT hr = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path);
if (FAILED(hr)) {
- D("SHGetFolderPathW failed: %s\n",
+ D("SHGetFolderPathW failed: %s",
SystemErrorCodeToString(hr).c_str());
return -1;
}
@@ -322,7 +322,7 @@
format = "%s/%s";
#endif
- D("home '%s'\n", home);
+ D("home '%s'", home);
if (snprintf(android_dir, sizeof(android_dir), format, home,
ANDROID_PATH) >= (int)sizeof(android_dir))
@@ -330,7 +330,7 @@
if (stat(android_dir, &buf)) {
if (adb_mkdir(android_dir, 0750) < 0) {
- D("Cannot mkdir '%s'\n", android_dir);
+ D("Cannot mkdir '%s'", android_dir);
return -1;
}
}
@@ -346,15 +346,15 @@
ret = get_user_keyfilepath(path, sizeof(path));
if (ret < 0 || ret >= (signed)sizeof(path)) {
- D("Error getting user key filename\n");
+ D("Error getting user key filename");
return 0;
}
- D("user key '%s'\n", path);
+ D("user key '%s'", path);
if (stat(path, &buf) == -1) {
if (!generate_key(path)) {
- D("Failed to generate new key\n");
+ D("Failed to generate new key");
return 0;
}
}
@@ -370,7 +370,7 @@
for (auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
if (!read_key(path.c_str(), key_list)) {
- D("Failed to read '%s'\n", path.c_str());
+ D("Failed to read '%s'", path.c_str());
}
}
}
@@ -382,7 +382,7 @@
struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
if (token_size != TOKEN_SIZE) {
- D("Unexpected token size %zd\n", token_size);
+ D("Unexpected token size %zd", token_size);
return 0;
}
@@ -390,7 +390,7 @@
return 0;
}
- D("adb_auth_sign len=%d\n", len);
+ D("adb_auth_sign len=%d", len);
return (int)len;
}
@@ -421,7 +421,7 @@
char path[PATH_MAX];
int ret = get_user_keyfilepath(path, sizeof(path) - 4);
if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
- D("Error getting user key filename\n");
+ D("Error getting user key filename");
return 0;
}
strcat(path, ".pub");
@@ -433,12 +433,12 @@
unsigned size;
char* file_data = reinterpret_cast<char*>(load_file(path, &size));
if (file_data == nullptr) {
- D("Can't load '%s'\n", path);
+ D("Can't load '%s'", path);
return 0;
}
if (len < (size_t)(size + 1)) {
- D("%s: Content too large ret=%d\n", path, size);
+ D("%s: Content too large ret=%d", path, size);
free(file_data);
return 0;
}
@@ -460,13 +460,13 @@
{
int ret;
- D("adb_auth_init\n");
+ D("adb_auth_init");
list_init(&key_list);
ret = get_user_key(&key_list);
if (!ret) {
- D("Failed to get user key\n");
+ D("Failed to get user key");
return;
}
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index a1bbb78..ff68415 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -90,14 +90,14 @@
adb_close(fd);
return -1;
}
- D("Switch transport in progress\n");
+ D("Switch transport in progress");
if (!adb_status(fd, error)) {
adb_close(fd);
- D("Switch transport failed: %s\n", error->c_str());
+ D("Switch transport failed: %s", error->c_str());
return -1;
}
- D("Switch transport success\n");
+ D("Switch transport success");
return 0;
}
@@ -123,7 +123,7 @@
}
int _adb_connect(const std::string& service, std::string* error) {
- D("_adb_connect: %s\n", service.c_str());
+ D("_adb_connect: %s", service.c_str());
if (service.empty() || service.size() > 1024) {
*error = android::base::StringPrintf("bad service name length (%zd)",
service.size());
@@ -164,7 +164,7 @@
return -1;
}
- D("_adb_connect: return fd %d\n", fd);
+ D("_adb_connect: return fd %d", fd);
return fd;
}
@@ -172,7 +172,7 @@
// first query the adb server's version
int fd = _adb_connect("host:version", error);
- D("adb_connect: service %s\n", service.c_str());
+ D("adb_connect: service %s", service.c_str());
if (fd == -2 && __adb_server_name) {
fprintf(stderr,"** Cannot start server on remote host\n");
// error is the original network connection error
@@ -246,11 +246,11 @@
fd = _adb_connect(service, error);
if (fd == -1) {
- D("_adb_connect error: %s\n", error->c_str());
+ D("_adb_connect error: %s", error->c_str());
} else if(fd == -2) {
fprintf(stderr,"** daemon still not running\n");
}
- D("adb_connect: return fd %d\n", fd);
+ D("adb_connect: return fd %d", fd);
return fd;
error:
@@ -277,7 +277,7 @@
}
bool adb_query(const std::string& service, std::string* result, std::string* error) {
- D("adb_query: %s\n", service.c_str());
+ D("adb_query: %s", service.c_str());
int fd = adb_connect(service, error);
if (fd < 0) {
return false;
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index 7092609..14e295f 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -68,23 +68,23 @@
size_t len0 = len;
- D("readx: fd=%d wanted=%zu\n", fd, len);
+ D("readx: fd=%d wanted=%zu", fd, len);
while (len > 0) {
int r = adb_read(fd, p, len);
if (r > 0) {
len -= r;
p += r;
} else if (r == -1) {
- D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
+ D("readx: fd=%d error %d: %s", fd, errno, strerror(errno));
return false;
} else {
- D("readx: fd=%d disconnected\n", fd);
+ D("readx: fd=%d disconnected", fd);
errno = 0;
return false;
}
}
- D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
+ D("readx: fd=%d wanted=%zu got=%zu", fd, len0, len0 - len);
if (ADB_TRACING) {
dump_hex(reinterpret_cast<const unsigned char*>(buf), len0);
}
@@ -104,12 +104,12 @@
while (len > 0) {
r = adb_write(fd, p, len);
if (r == -1) {
- D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
+ D("writex: fd=%d error %d: %s", fd, errno, strerror(errno));
if (errno == EAGAIN) {
adb_sleep_ms(1); // just yield some cpu time
continue;
} else if (errno == EPIPE) {
- D("writex: fd=%d disconnected\n", fd);
+ D("writex: fd=%d disconnected", fd);
errno = 0;
return false;
} else {
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index f637073..84e3db6 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -31,10 +31,11 @@
#include "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(). Also, the
-// android::base file APIs use the C Runtime which uses CR/LF translation by
-// default (changeable with _setmode()), but the adb_io APIs use adb_read()
-// and adb_write() which do no translation.
+// but the adb_io APIs expect file descriptors from adb_open(). This could
+// theoretically be fixed by making adb_read()/adb_write() fallback to using
+// read()/write() if an unrecognized fd is used, and by making adb_open() return
+// fds far from the range that open() returns. But all of that might defeat the
+// purpose of the tests.
TEST(io, ReadFdExactly_whole) {
const char expected[] = "Foobar";
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index 4e03165..67ee854 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -17,11 +17,8 @@
#ifndef __ADB_TRACE_H
#define __ADB_TRACE_H
-#if !ADB_HOST
-#include <android/log.h>
-#else
-#include <stdio.h>
-#endif
+#include <base/logging.h>
+#include <base/stringprintf.h>
/* IMPORTANT: if you change the following list, don't
* forget to update the corresponding 'tags' table in
@@ -46,48 +43,16 @@
extern unsigned char adb_trace_output_count;
void adb_trace_init(char**);
-# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
+#define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
-/* you must define TRACE_TAG before using this macro */
-#if ADB_HOST
-# define D(fmt, ...) \
+// You must define TRACE_TAG before using this macro.
+#define D(...) \
do { \
if (ADB_TRACING) { \
int saved_errno = errno; \
- adb_mutex_lock(&D_lock); \
- errno = saved_errno; \
- fprintf(stderr, "%5d:%5lu %s | " fmt, \
- getpid(), adb_thread_id(), __FUNCTION__, ## __VA_ARGS__); \
- fflush(stderr); \
- adb_mutex_unlock(&D_lock); \
+ LOG(INFO) << android::base::StringPrintf(__VA_ARGS__); \
errno = saved_errno; \
} \
} while (0)
-# define DR(...) \
- do { \
- if (ADB_TRACING) { \
- int saved_errno = errno; \
- adb_mutex_lock(&D_lock); \
- errno = saved_errno; \
- fprintf(stderr, __VA_ARGS__); \
- fflush(stderr); \
- adb_mutex_unlock(&D_lock); \
- errno = saved_errno; \
- } \
- } while (0)
-#else
-# define D(...) \
- do { \
- if (ADB_TRACING) { \
- __android_log_print(ANDROID_LOG_INFO, __FUNCTION__, __VA_ARGS__); \
- } \
- } while (0)
-# define DR(...) \
- do { \
- if (ADB_TRACING) { \
- __android_log_print(ANDROID_LOG_INFO, __FUNCTION__, __VA_ARGS__); \
- } \
- } while (0)
-#endif /* ADB_HOST */
#endif /* __ADB_TRACE_H */
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index e5dc692..72ee901 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -170,7 +170,7 @@
line.push_back(c);
}
- DR("%s\n", line.c_str());
+ D("%s", line.c_str());
}
bool parse_host_and_port(const std::string& address,
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index f6ddeb4..6e27c0f 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -36,42 +36,6 @@
#include "adb_listeners.h"
#include "transport.h"
-#if defined(WORKAROUND_BUG6558362) && defined(__linux__)
-static const bool kWorkaroundBug6558362 = true;
-#else
-static const bool kWorkaroundBug6558362 = false;
-#endif
-
-static void adb_workaround_affinity(void) {
-#if defined(__linux__)
- const char affinity_env[] = "ADB_CPU_AFFINITY_BUG6558362";
- const char* cpunum_str = getenv(affinity_env);
- if (cpunum_str == nullptr || *cpunum_str == '\0') {
- return;
- }
-
- char* strtol_res;
- int cpu_num = strtol(cpunum_str, &strtol_res, 0);
- if (*strtol_res != '\0') {
- fatal("bad number (%s) in env var %s. Expecting 0..n.\n", cpunum_str,
- affinity_env);
- }
-
- cpu_set_t cpu_set;
- sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
- D("orig cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
-
- CPU_ZERO(&cpu_set);
- CPU_SET(cpu_num, &cpu_set);
- sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
-
- sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
- D("new cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
-#else
- // No workaround was ever implemented for the other platforms.
-#endif
-}
-
#if defined(_WIN32)
static const char kNullFileName[] = "NUL";
@@ -157,10 +121,6 @@
init_transport_registration();
- if (kWorkaroundBug6558362 && is_daemon) {
- adb_workaround_affinity();
- }
-
usb_init();
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
adb_auth_init();
@@ -203,7 +163,7 @@
#endif
}
- D("Event loop starting\n");
+ D("Event loop starting");
fdevent_loop();
return 0;
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 6325e64..86f9263 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -258,10 +258,10 @@
static void read_and_dump(int fd) {
while (fd >= 0) {
- D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
+ D("read_and_dump(): pre adb_read(fd=%d)", fd);
char buf[BUFSIZ];
int len = adb_read(fd, buf, sizeof(buf));
- D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
+ D("read_and_dump(): post adb_read(fd=%d): len=%d", fd, len);
if (len <= 0) {
break;
}
@@ -297,7 +297,7 @@
int old_stdout_mode = -1;
#endif
- D("copy_to_file(%d -> %d)\n", inFd, outFd);
+ D("copy_to_file(%d -> %d)", inFd, outFd);
if (inFd == STDIN_FILENO) {
stdin_raw_init(STDIN_FILENO);
@@ -325,11 +325,11 @@
len = adb_read(inFd, buf, BUFSIZE);
}
if (len == 0) {
- D("copy_to_file() : read 0 bytes; exiting\n");
+ D("copy_to_file() : read 0 bytes; exiting");
break;
}
if (len < 0) {
- D("copy_to_file(): read failed: %s\n", strerror(errno));
+ D("copy_to_file(): read failed: %s", strerror(errno));
break;
}
if (outFd == STDOUT_FILENO) {
@@ -358,7 +358,7 @@
}
#endif
- D("copy_to_file() finished after %lu bytes\n", total);
+ D("copy_to_file() finished after %lu bytes", total);
free(buf);
}
@@ -378,9 +378,9 @@
while (true) {
/* fdi is really the client's stdin, so use read, not adb_read here */
- D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
+ D("stdin_read_thread(): pre unix_read(fdi=%d,...)", fdi);
r = unix_read(fdi, buf, 1024);
- D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
+ D("stdin_read_thread(): post unix_read(fdi=%d,...)", fdi);
if (r <= 0) break;
for (n = 0; n < r; n++){
switch(buf[n]) {
@@ -777,7 +777,7 @@
cmd += " " + escape_arg(*argv++);
}
- D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
+ D("backup. filename=%s cmd=%s", filename, cmd.c_str());
std::string error;
int fd = adb_connect(cmd, &error);
if (fd < 0) {
@@ -1152,7 +1152,7 @@
}
if (argc < 2) {
- D("starting interactive shell\n");
+ D("starting interactive shell");
r = interactive_shell();
if (h) {
printf("\x1b[0m");
@@ -1171,14 +1171,14 @@
}
while (true) {
- D("interactive shell loop. cmd=%s\n", cmd.c_str());
+ D("interactive shell loop. cmd=%s", cmd.c_str());
std::string error;
int fd = adb_connect(cmd, &error);
int r;
if (fd >= 0) {
- D("about to read_and_dump(fd=%d)\n", fd);
+ D("about to read_and_dump(fd=%d)", fd);
read_and_dump(fd);
- D("read_and_dump() done.\n");
+ D("read_and_dump() done.");
adb_close(fd);
r = 0;
} else {
@@ -1190,7 +1190,7 @@
printf("\x1b[0m");
fflush(stdout);
}
- D("interactive shell loop. return r=%d\n", r);
+ D("interactive shell loop. return r=%d", r);
return r;
}
}
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 2eba625..cb0cb3d 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -162,7 +162,7 @@
PLOG(FATAL) << "Could not setuid";
}
- D("Local port disabled\n");
+ D("Local port disabled");
} else {
if (root_seclabel != nullptr) {
if (setcon(root_seclabel) < 0) {
@@ -197,7 +197,7 @@
int port;
if (sscanf(prop_port, "%d", &port) == 1 && port > 0) {
- printf("using port=%d\n", port);
+ D("using port=%d", port);
// Listen on TCP port specified by service.adb.tcp.port property.
local_init(port);
} else if (!is_usb) {
@@ -205,11 +205,11 @@
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
}
- D("adbd_main(): pre init_jdwp()\n");
+ D("adbd_main(): pre init_jdwp()");
init_jdwp();
- D("adbd_main(): post init_jdwp()\n");
+ D("adbd_main(): post init_jdwp()");
- D("Event loop starting\n");
+ D("Event loop starting");
fdevent_loop();
return 0;
@@ -261,6 +261,6 @@
adb_trace_init(argv);
- D("Handling main()\n");
+ D("Handling main()");
return adbd_main(DEFAULT_ADB_PORT);
}
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index d25bbfb..db5157f 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -331,11 +331,11 @@
do { \
printed_out = snprintf(pb, max_chars, __VA_ARGS__); \
if (printed_out <= 0) { \
- D("... snprintf failed.\n"); \
+ D("... snprintf failed."); \
return; \
} \
if (max_chars < (unsigned int)printed_out) { \
- D("... snprintf out of space.\n"); \
+ D("... snprintf out of space."); \
return; \
} \
pb += printed_out; \
@@ -354,7 +354,7 @@
}
SAFE_SPRINTF(" ");
}
- D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
+ D("%s fd_table[]->fd = {%s}", extra_msg, msg_buff);
}
#endif
@@ -373,7 +373,7 @@
n = select(select_n, &rfd, &wfd, &efd, NULL);
int saved_errno = errno;
- D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
+ D("select() returned n=%d, errno=%d", n, n<0?saved_errno:0);
dump_all_fds("post select()");
@@ -387,7 +387,7 @@
FD_ZERO(&rfd);
break;
default:
- D("Unexpected select() error=%d\n", saved_errno);
+ D("Unexpected select() error=%d", saved_errno);
return;
}
}
@@ -410,7 +410,7 @@
fde->events |= events;
- D("got events fde->fd=%d events=%04x, state=%04x\n",
+ D("got events fde->fd=%d events=%04x, state=%04x",
fde->fd, fde->events, fde->state);
if(fde->state & FDE_PENDING) continue;
fde->state |= FDE_PENDING;
@@ -516,7 +516,7 @@
void* /* userdata */)
{
- D("subproc handling on fd=%d ev=%04x\n", fd, ev);
+ D("subproc handling on fd=%d ev=%04x", fd, ev);
// Hook oneself back into the fde's suitable for select() on read.
if((fd < 0) || (fd >= fd_table_max)) {
@@ -532,18 +532,18 @@
FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
}
if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
- D("subproc_fd %d out of range 0, fd_table_max=%d\n",
+ D("subproc_fd %d out of range 0, fd_table_max=%d",
subproc_fd, fd_table_max);
return;
}
fdevent *subproc_fde = fd_table[subproc_fd];
if(!subproc_fde) {
- D("subproc_fd %d cleared from fd_table\n", subproc_fd);
+ D("subproc_fd %d cleared from fd_table", subproc_fd);
return;
}
if(subproc_fde->fd != subproc_fd) {
// Already reallocated?
- D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
+ D("subproc_fd %d != fd_table[].fd %d", subproc_fd, subproc_fde->fd);
return;
}
@@ -551,7 +551,7 @@
int rcount = 0;
ioctl(subproc_fd, FIONREAD, &rcount);
- D("subproc with fd=%d has rcount=%d err=%d\n",
+ D("subproc with fd=%d has rcount=%d err=%d",
subproc_fd, rcount, errno);
if(rcount) {
@@ -561,7 +561,7 @@
return;
}
- D("subproc_fde.state=%04x\n", subproc_fde->state);
+ D("subproc_fde.state=%04x", subproc_fde->state);
subproc_fde->events |= FDE_READ;
if(subproc_fde->state & FDE_PENDING) {
return;
@@ -578,7 +578,7 @@
if(adb_socketpair(s)) {
FATAL("cannot create shell-exit socket-pair\n");
}
- D("socketpair: (%d,%d)\n", s[0], s[1]);
+ D("socketpair: (%d,%d)", s[0], s[1]);
SHELL_EXIT_NOTIFY_FD = s[0];
fdevent *fde;
@@ -689,7 +689,7 @@
#endif // !ADB_HOST
while (true) {
- D("--- ---- waiting for events\n");
+ D("--- ---- waiting for events");
fdevent_process();
diff --git a/adb/fdevent.h b/adb/fdevent.h
index 8d84b29..ca1494c 100644
--- a/adb/fdevent.h
+++ b/adb/fdevent.h
@@ -23,7 +23,6 @@
#define FDE_READ 0x0001
#define FDE_WRITE 0x0002
#define FDE_ERROR 0x0004
-#define FDE_TIMEOUT 0x0008
/* features that may be set (via the events set/add/del interface) */
#define FDE_DONT_CLOSE 0x0080
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
new file mode 100644
index 0000000..f7622b5
--- /dev/null
+++ b/adb/fdevent_test.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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 "fdevent.h"
+
+#include <gtest/gtest.h>
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include <pthread.h>
+#include <signal.h>
+
+#include "adb_io.h"
+
+class SignalHandlerRegister {
+ public:
+ SignalHandlerRegister(const std::vector<int>& signums, void (*handler)(int)) {
+ for (auto& sig : signums) {
+ sig_t old_handler = signal(sig, handler);
+ saved_signal_handlers_.push_back(std::make_pair(sig, old_handler));
+ }
+ }
+
+ ~SignalHandlerRegister() {
+ for (auto& pair : saved_signal_handlers_) {
+ signal(pair.first, pair.second);
+ }
+ }
+
+ private:
+ std::vector<std::pair<int, sig_t>> saved_signal_handlers_;
+};
+
+class FdHandler {
+ public:
+ FdHandler(int read_fd, int write_fd) : read_fd_(read_fd), write_fd_(write_fd) {
+ fdevent_install(&read_fde_, read_fd_, FdEventCallback, this);
+ fdevent_add(&read_fde_, FDE_READ | FDE_ERROR);
+ fdevent_install(&write_fde_, write_fd_, FdEventCallback, this);
+ fdevent_add(&write_fde_, FDE_ERROR);
+ }
+
+ private:
+ static void FdEventCallback(int fd, unsigned events, void* userdata) {
+ FdHandler* handler = reinterpret_cast<FdHandler*>(userdata);
+ ASSERT_EQ(0u, (events & ~(FDE_READ | FDE_WRITE))) << "unexpected events: " << events;
+ if (events & FDE_READ) {
+ ASSERT_EQ(fd, handler->read_fd_);
+ char c;
+ ASSERT_EQ(1, read(fd, &c, 1));
+ handler->queue_.push(c);
+ fdevent_add(&handler->write_fde_, FDE_WRITE);
+ }
+ if (events & FDE_WRITE) {
+ ASSERT_EQ(fd, handler->write_fd_);
+ ASSERT_FALSE(handler->queue_.empty());
+ char c = handler->queue_.front();
+ handler->queue_.pop();
+ ASSERT_EQ(1, write(fd, &c, 1));
+ if (handler->queue_.empty()) {
+ fdevent_del(&handler->write_fde_, FDE_WRITE);
+ }
+ }
+ }
+
+ private:
+ const int read_fd_;
+ const int write_fd_;
+ fdevent read_fde_;
+ fdevent write_fde_;
+ std::queue<char> queue_;
+};
+
+static void signal_handler(int) {
+ pthread_exit(nullptr);
+}
+
+struct ThreadArg {
+ int first_read_fd;
+ int last_write_fd;
+ size_t middle_pipe_count;
+};
+
+static void FdEventThreadFunc(ThreadArg* arg) {
+ SignalHandlerRegister signal_handler_register({SIGUSR1}, signal_handler);
+
+ std::vector<int> read_fds;
+ std::vector<int> write_fds;
+
+ read_fds.push_back(arg->first_read_fd);
+ for (size_t i = 0; i < arg->middle_pipe_count; ++i) {
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+ read_fds.push_back(fds[0]);
+ write_fds.push_back(fds[1]);
+ }
+ write_fds.push_back(arg->last_write_fd);
+
+ std::vector<std::unique_ptr<FdHandler>> fd_handlers;
+ for (size_t i = 0; i < read_fds.size(); ++i) {
+ fd_handlers.push_back(std::unique_ptr<FdHandler>(new FdHandler(read_fds[i], write_fds[i])));
+ }
+
+ fdevent_loop();
+}
+
+TEST(fdevent, smoke) {
+ const size_t PIPE_COUNT = 10;
+ const size_t MESSAGE_LOOP_COUNT = 100;
+ const std::string MESSAGE = "fdevent_test";
+ int fd_pair1[2];
+ int fd_pair2[2];
+ ASSERT_EQ(0, pipe(fd_pair1));
+ ASSERT_EQ(0, pipe(fd_pair2));
+ pthread_t thread;
+ ThreadArg thread_arg;
+ thread_arg.first_read_fd = fd_pair1[0];
+ thread_arg.last_write_fd = fd_pair2[1];
+ thread_arg.middle_pipe_count = PIPE_COUNT;
+ int writer = fd_pair1[1];
+ int reader = fd_pair2[0];
+
+ ASSERT_EQ(0, pthread_create(&thread, nullptr,
+ reinterpret_cast<void* (*)(void*)>(FdEventThreadFunc),
+ &thread_arg));
+
+ for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
+ std::string read_buffer = MESSAGE;
+ std::string write_buffer(MESSAGE.size(), 'a');
+ ASSERT_TRUE(WriteFdExactly(writer, read_buffer.c_str(), read_buffer.size()));
+ ASSERT_TRUE(ReadFdExactly(reader, &write_buffer[0], write_buffer.size()));
+ ASSERT_EQ(read_buffer, write_buffer);
+ }
+
+ ASSERT_EQ(0, pthread_kill(thread, SIGUSR1));
+ ASSERT_EQ(0, pthread_join(thread, nullptr));
+}
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 3793b8e..8db9ca7 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -130,7 +130,7 @@
}
static bool SendSyncFail(int fd, const std::string& reason) {
- D("sync: failure: %s\n", reason.c_str());
+ D("sync: failure: %s", reason.c_str());
syncmsg msg;
msg.data.id = ID_FAIL;
@@ -346,7 +346,7 @@
}
static bool handle_sync_command(int fd, std::vector<char>& buffer) {
- D("sync: waiting for request\n");
+ D("sync: waiting for request");
SyncRequest request;
if (!ReadFdExactly(fd, &request, sizeof(request))) {
@@ -366,7 +366,7 @@
name[path_length] = 0;
const char* id = reinterpret_cast<const char*>(&request.id);
- D("sync: '%.4s' '%s'\n", id, name);
+ D("sync: '%.4s' '%s'", id, name);
switch (request.id) {
case ID_STAT:
@@ -398,6 +398,6 @@
while (handle_sync_command(fd, buffer)) {
}
- D("sync: done\n");
+ D("sync: done");
adb_close(fd);
}
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index 06e7780..0fa0732 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -218,7 +218,7 @@
calloc(1, sizeof(*proc)));
if (proc == NULL) {
- D("not enough memory to create new JDWP process\n");
+ D("not enough memory to create new JDWP process");
return NULL;
}
@@ -229,7 +229,7 @@
proc->fde = fdevent_create( socket, jdwp_process_event, proc );
if (proc->fde == NULL) {
- D("could not create fdevent for new JDWP process\n" );
+ D("could not create fdevent for new JDWP process" );
free(proc);
return NULL;
}
@@ -271,13 +271,13 @@
if (errno == EAGAIN)
return;
/* this can fail here if the JDWP process crashes very fast */
- D("weird unknown JDWP process failure: %s\n",
+ D("weird unknown JDWP process failure: %s",
strerror(errno));
goto CloseProcess;
}
if (len == 0) { /* end of stream ? */
- D("weird end-of-stream from unknown JDWP process\n");
+ D("weird end-of-stream from unknown JDWP process");
goto CloseProcess;
}
p += len;
@@ -289,12 +289,12 @@
temp[4] = 0;
if (sscanf( temp, "%04x", &proc->pid ) != 1) {
- D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
+ D("could not decode JDWP %p PID number: '%s'", proc, temp);
goto CloseProcess;
}
/* all is well, keep reading to detect connection closure */
- D("Adding pid %d to jdwp process list\n", proc->pid);
+ D("Adding pid %d to jdwp process list", proc->pid);
jdwp_process_list_updated();
}
else
@@ -312,27 +312,27 @@
if (len < 0 && errno == EAGAIN)
return;
else {
- D("terminating JDWP %d connection: %s\n", proc->pid,
+ D("terminating JDWP %d connection: %s", proc->pid,
strerror(errno));
break;
}
}
else {
- D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
+ D( "ignoring unexpected JDWP %d control socket activity (%d bytes)",
proc->pid, len );
}
}
CloseProcess:
if (proc->pid >= 0)
- D( "remove pid %d to jdwp process list\n", proc->pid );
+ D( "remove pid %d to jdwp process list", proc->pid );
jdwp_process_free(proc);
return;
}
}
if (events & FDE_WRITE) {
- D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
+ D("trying to write to JDWP pid controli (count=%d first=%d) %d",
proc->pid, proc->out_count, proc->out_fds[0]);
if (proc->out_count > 0) {
int fd = proc->out_fds[0];
@@ -363,14 +363,14 @@
flags = fcntl(proc->socket,F_GETFL,0);
if (flags == -1) {
- D("failed to get cntl flags for socket %d: %s\n",
+ D("failed to get cntl flags for socket %d: %s",
proc->pid, strerror(errno));
goto CloseProcess;
}
if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
- D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
+ D("failed to remove O_NONBLOCK flag for socket %d: %s",
proc->pid, strerror(errno));
goto CloseProcess;
}
@@ -383,19 +383,19 @@
}
if (errno == EINTR)
continue;
- D("sending new file descriptor to JDWP %d failed: %s\n",
+ D("sending new file descriptor to JDWP %d failed: %s",
proc->pid, strerror(errno));
goto CloseProcess;
}
- D("sent file descriptor %d to JDWP process %d\n",
+ D("sent file descriptor %d to JDWP process %d",
fd, proc->pid);
for (n = 1; n < proc->out_count; n++)
proc->out_fds[n-1] = proc->out_fds[n];
if (fcntl(proc->socket, F_SETFL, flags) == -1) {
- D("failed to set O_NONBLOCK flag for socket %d: %s\n",
+ D("failed to set O_NONBLOCK flag for socket %d: %s",
proc->pid, strerror(errno));
goto CloseProcess;
}
@@ -412,13 +412,13 @@
{
JdwpProcess* proc = _jdwp_list.next;
- D("looking for pid %d in JDWP process list\n", pid);
+ D("looking for pid %d in JDWP process list", pid);
for ( ; proc != &_jdwp_list; proc = proc->next ) {
if (proc->pid == pid) {
goto FoundIt;
}
}
- D("search failed !!\n");
+ D("search failed !!");
return -1;
FoundIt:
@@ -426,17 +426,17 @@
int fds[2];
if (proc->out_count >= MAX_OUT_FDS) {
- D("%s: too many pending JDWP connection for pid %d\n",
+ D("%s: too many pending JDWP connection for pid %d",
__FUNCTION__, pid);
return -1;
}
if (adb_socketpair(fds) < 0) {
- D("%s: socket pair creation failed: %s\n",
+ D("%s: socket pair creation failed: %s",
__FUNCTION__, strerror(errno));
return -1;
}
- D("socketpair: (%d,%d)\n", fds[0], fds[1]);
+ D("socketpair: (%d,%d)", fds[0], fds[1]);
proc->out_fds[ proc->out_count ] = fds[1];
if (++proc->out_count == 1)
@@ -477,7 +477,7 @@
int pathlen = socknamelen;
if (pathlen >= maxpath) {
- D( "vm debug control socket name too long (%d extra chars)\n",
+ D( "vm debug control socket name too long (%d extra chars)",
pathlen+1-maxpath );
return -1;
}
@@ -488,7 +488,7 @@
s = socket( AF_UNIX, SOCK_STREAM, 0 );
if (s < 0) {
- D( "could not create vm debug control socket. %d: %s\n",
+ D( "could not create vm debug control socket. %d: %s",
errno, strerror(errno));
return -1;
}
@@ -496,14 +496,14 @@
addrlen = (pathlen + sizeof(addr.sun_family));
if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {
- D( "could not bind vm debug control socket: %d: %s\n",
+ D( "could not bind vm debug control socket: %d: %s",
errno, strerror(errno) );
adb_close(s);
return -1;
}
if ( listen(s, 4) < 0 ) {
- D("listen failed in jdwp control socket: %d: %s\n",
+ D("listen failed in jdwp control socket: %d: %s",
errno, strerror(errno));
adb_close(s);
return -1;
@@ -513,7 +513,7 @@
control->fde = fdevent_create(s, jdwp_control_event, control);
if (control->fde == NULL) {
- D( "could not create fdevent for jdwp control socket\n" );
+ D( "could not create fdevent for jdwp control socket" );
adb_close(s);
return -1;
}
@@ -522,7 +522,7 @@
fdevent_add(control->fde, FDE_READ);
close_on_exec(s);
- D("jdwp control socket started (%d)\n", control->listen_socket);
+ D("jdwp control socket started (%d)", control->listen_socket);
return 0;
}
@@ -545,11 +545,11 @@
continue;
if (errno == ECONNABORTED) {
/* oops, the JDWP process died really quick */
- D("oops, the JDWP process died really quick\n");
+ D("oops, the JDWP process died really quick");
return;
}
/* the socket is probably closed ? */
- D( "weird accept() failed on jdwp control socket: %s\n",
+ D( "weird accept() failed on jdwp control socket: %s",
strerror(errno) );
return;
}
diff --git a/adb/mutex_list.h b/adb/mutex_list.h
index 9003361..79c48d8 100644
--- a/adb/mutex_list.h
+++ b/adb/mutex_list.h
@@ -14,13 +14,4 @@
#endif
ADB_MUTEX(usb_lock)
-// Sadly logging to /data/adb/adb-... is not thread safe.
-// After modifying adb.h::D() to count invocations:
-// DEBUG(jpa):0:Handling main()
-// DEBUG(jpa):1:[ usb_init - starting thread ]
-// (Oopsies, no :2:, and matching message is also gone.)
-// DEBUG(jpa):3:[ usb_thread - opening device ]
-// DEBUG(jpa):4:jdwp control socket started (10)
-ADB_MUTEX(D_lock)
-
#undef ADB_MUTEX
diff --git a/adb/services.cpp b/adb/services.cpp
index 4606804..ac672f0 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -147,7 +147,7 @@
const char* const command_file = "/cache/recovery/command";
// Ensure /cache/recovery exists.
if (adb_mkdir(recovery_dir, 0770) == -1 && errno != EEXIST) {
- D("Failed to create directory '%s': %s\n", recovery_dir, strerror(errno));
+ D("Failed to create directory '%s': %s", recovery_dir, strerror(errno));
return false;
}
@@ -212,7 +212,7 @@
printf("cannot create service socket pair\n");
return -1;
}
- D("socketpair: (%d,%d)\n", s[0], s[1]);
+ D("socketpair: (%d,%d)", s[0], s[1]);
stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
if (sti == nullptr) {
@@ -230,7 +230,7 @@
return -1;
}
- D("service thread started, %d:%d\n",s[0], s[1]);
+ D("service thread started, %d:%d",s[0], s[1]);
return s[0];
}
@@ -246,14 +246,14 @@
adb_write(fd, "0", 1);
adb_close(fd);
} else {
- D("adb: unable to update oom_score_adj\n");
+ D("adb: unable to update oom_score_adj");
}
}
#if !ADB_HOST
static int create_subproc_pty(const char* cmd, const char* arg0,
const char* arg1, pid_t* pid) {
- D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
+ D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)", cmd, arg0, arg1);
char pts_name[PATH_MAX];
int ptm;
*pid = forkpty(&ptm, pts_name, nullptr, nullptr);
@@ -312,7 +312,7 @@
static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
- D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
+ D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)", cmd, arg0, arg1);
#if defined(_WIN32)
fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
return -1;
@@ -324,7 +324,7 @@
printf("[ cannot create socket pair - %s ]\n", strerror(errno));
return -1;
}
- D("socketpair: (%d,%d)\n", sv[0], sv[1]);
+ D("socketpair: (%d,%d)", sv[0], sv[1]);
*pid = fork();
if (*pid < 0) {
@@ -367,29 +367,29 @@
{
pid_t pid = (pid_t) (uintptr_t) cookie;
- D("entered. fd=%d of pid=%d\n", fd, pid);
+ D("entered. fd=%d of pid=%d", fd, pid);
while (true) {
int status;
pid_t p = waitpid(pid, &status, 0);
if (p == pid) {
- D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
+ D("fd=%d, post waitpid(pid=%d) status=%04x", fd, p, status);
if (WIFSIGNALED(status)) {
- D("*** Killed by signal %d\n", WTERMSIG(status));
+ D("*** Killed by signal %d", WTERMSIG(status));
break;
} else if (!WIFEXITED(status)) {
- D("*** Didn't exit!!. status %d\n", status);
+ D("*** Didn't exit!!. status %d", status);
break;
} else if (WEXITSTATUS(status) >= 0) {
- D("*** Exit code %d\n", WEXITSTATUS(status));
+ D("*** Exit code %d", WEXITSTATUS(status));
break;
}
}
}
- D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
+ D("shell exited fd=%d of pid=%d err=%d", fd, pid, errno);
if (SHELL_EXIT_NOTIFY_FD >=0) {
int res;
res = WriteFdExactly(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd)) ? 0 : -1;
- D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
+ D("notified shell exit via fd=%d for pid=%d res=%d errno=%d",
SHELL_EXIT_NOTIFY_FD, pid, res, errno);
}
}
@@ -419,7 +419,7 @@
} else {
ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
}
- D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
+ D("create_subproc ret_fd=%d pid=%d", ret_fd, pid);
stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo)));
if(sti == 0) fatal("cannot allocate stinfo");
@@ -434,7 +434,7 @@
return -1;
}
- D("service thread started, fd=%d pid=%d\n", ret_fd, pid);
+ D("service thread started, fd=%d pid=%d", ret_fd, pid);
return ret_fd;
}
#endif
@@ -549,7 +549,7 @@
{
state_info* sinfo = reinterpret_cast<state_info*>(cookie);
- D("wait_for_state %d\n", sinfo->state);
+ D("wait_for_state %d", sinfo->state);
std::string error_msg = "unknown error";
atransport* t = acquire_one_transport(sinfo->state, sinfo->transport_type, sinfo->serial,
@@ -564,7 +564,7 @@
free(sinfo->serial);
free(sinfo);
adb_close(fd);
- D("wait_for_state is done\n");
+ D("wait_for_state is done");
}
static void connect_device(const std::string& address, std::string* response) {
@@ -588,7 +588,7 @@
return;
}
- D("client: connected %s remote on fd %d\n", serial.c_str(), fd);
+ D("client: connected %s remote on fd %d", serial.c_str(), fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 9c13936..f8c22cc 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -133,7 +133,7 @@
static int local_socket_enqueue(asocket *s, apacket *p)
{
- D("LS(%d): enqueue %d\n", s->id, p->len);
+ D("LS(%d): enqueue %d", s->id, p->len);
p->ptr = p->data;
@@ -156,7 +156,7 @@
continue;
}
if((r == 0) || (errno != EAGAIN)) {
- D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );
+ D( "LS(%d): not ready, errno=%d: %s", s->id, errno, strerror(errno) );
s->close(s);
return 1; /* not ready (error) */
} else {
@@ -204,7 +204,7 @@
apacket *p, *n;
int exit_on_close = s->exit_on_close;
- D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd);
+ D("LS(%d): destroying fde.fd=%d", s->id, s->fde.fd);
/* IMPORTANT: the remove closes the fd
** that belongs to this socket
@@ -213,7 +213,7 @@
/* dispose of any unwritten data */
for(p = s->pkt_first; p; p = n) {
- D("LS(%d): discarding %d bytes\n", s->id, p->len);
+ D("LS(%d): discarding %d bytes", s->id, p->len);
n = p->next;
put_apacket(p);
}
@@ -221,7 +221,7 @@
free(s);
if (exit_on_close) {
- D("local_socket_destroy: exiting\n");
+ D("local_socket_destroy: exiting");
exit(1);
}
}
@@ -229,9 +229,9 @@
static void local_socket_close_locked(asocket *s)
{
- D("entered local_socket_close_locked. LS(%d) fd=%d\n", s->id, s->fd);
+ D("entered local_socket_close_locked. LS(%d) fd=%d", s->id, s->fd);
if(s->peer) {
- D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
+ D("LS(%d): closing peer. peer->id=%d peer->fd=%d",
s->id, s->peer->id, s->peer->fd);
/* Note: it's important to call shutdown before disconnecting from
* the peer, this ensures that remote sockets can still get the id
@@ -255,24 +255,24 @@
if (s->closing || s->pkt_first == NULL) {
int id = s->id;
local_socket_destroy(s);
- D("LS(%d): closed\n", id);
+ D("LS(%d): closed", id);
return;
}
/* otherwise, put on the closing list
*/
- D("LS(%d): closing\n", s->id);
+ D("LS(%d): closing", s->id);
s->closing = 1;
fdevent_del(&s->fde, FDE_READ);
remove_socket(s);
- D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
+ D("LS(%d): put on socket_closing_list fd=%d", s->id, s->fd);
insert_local_socket(s, &local_socket_closing_list);
}
static void local_socket_event_func(int fd, unsigned ev, void* _s)
{
asocket* s = reinterpret_cast<asocket*>(_s);
- D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
+ D("LS(%d): event_func(fd=%d(==%d), ev=%04x)", s->id, s->fd, fd, ev);
/* put the FDE_WRITE processing before the FDE_READ
** in order to simplify the code.
@@ -295,7 +295,7 @@
continue;
}
- D(" closing after write because r=%d and errno is %d\n", r, errno);
+ D(" closing after write because r=%d and errno is %d", r, errno);
s->close(s);
return;
}
@@ -313,7 +313,7 @@
** we can now destroy it.
*/
if (s->closing) {
- D(" closing because 'closing' is set after write\n");
+ D(" closing because 'closing' is set after write");
s->close(s);
return;
}
@@ -337,7 +337,7 @@
while (avail > 0) {
r = adb_read(fd, x, avail);
- D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n",
+ D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu",
s->id, s->fd, r, r < 0 ? errno : 0, avail);
if (r == -1) {
if (errno == EAGAIN) {
@@ -353,7 +353,7 @@
is_eof = 1;
break;
}
- D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
+ D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d",
s->id, s->fd, r, is_eof, s->fde.force_eof);
if ((avail == max_payload) || (s->peer == 0)) {
put_apacket(p);
@@ -365,7 +365,7 @@
unsigned saved_id = s->id;
int saved_fd = s->fd;
r = s->peer->enqueue(s->peer, p);
- D("LS(%u): fd=%d post peer->enqueue(). r=%d\n", saved_id, saved_fd, r);
+ D("LS(%u): fd=%d post peer->enqueue(). r=%d", saved_id, saved_fd, r);
if (r < 0) {
/* error return means they closed us as a side-effect
@@ -389,7 +389,7 @@
}
/* Don't allow a forced eof if data is still there */
if ((s->fde.force_eof && !r) || is_eof) {
- D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n",
+ D(" closing because is_eof=%d r=%d s->fde.force_eof=%d",
is_eof, r, s->fde.force_eof);
s->close(s);
}
@@ -400,7 +400,7 @@
** catching it here means we may skip the last few
** bytes of readable data.
*/
- D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
+ D("LS(%d): FDE_ERROR (fd=%d)", s->id, s->fd);
return;
}
@@ -418,7 +418,7 @@
install_local_socket(s);
fdevent_install(&s->fde, fd, local_socket_event_func, s);
- D("LS(%d): created (fd=%d)\n", s->id, s->fd);
+ D("LS(%d): created (fd=%d)", s->id, s->fd);
return s;
}
@@ -436,7 +436,7 @@
if(fd < 0) return 0;
asocket* s = create_local_socket(fd);
- D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
+ D("LS(%d): bound to '%s' via %d", s->id, name, fd);
#if !ADB_HOST
char debug[PROPERTY_VALUE_MAX];
@@ -447,7 +447,7 @@
|| (!strncmp(name, "unroot:", 7) && getuid() == 0)
|| !strncmp(name, "usb:", 4)
|| !strncmp(name, "tcpip:", 6)) {
- D("LS(%d): enabling exit_on_close\n", s->id);
+ D("LS(%d): enabling exit_on_close", s->id);
s->exit_on_close = 1;
}
#endif
@@ -463,7 +463,7 @@
s = host_service_to_socket(name, serial);
if (s != NULL) {
- D("LS(%d) bound to '%s'\n", s->id, name);
+ D("LS(%d) bound to '%s'", s->id, name);
return s;
}
@@ -473,7 +473,7 @@
static int remote_socket_enqueue(asocket *s, apacket *p)
{
- D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n",
+ D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d",
s->id, s->fd, s->peer->fd);
p->msg.command = A_WRTE;
p->msg.arg0 = s->peer->id;
@@ -485,7 +485,7 @@
static void remote_socket_ready(asocket *s)
{
- D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n",
+ D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d",
s->id, s->fd, s->peer->fd);
apacket *p = get_apacket();
p->msg.command = A_OKAY;
@@ -496,7 +496,7 @@
static void remote_socket_shutdown(asocket *s)
{
- D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d\n",
+ D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d",
s->id, s->fd, s->peer?s->peer->fd:-1);
apacket *p = get_apacket();
p->msg.command = A_CLSE;
@@ -511,13 +511,13 @@
{
if (s->peer) {
s->peer->peer = 0;
- D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n",
+ D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d",
s->id, s->peer->id, s->peer->fd);
s->peer->close(s->peer);
}
- D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n",
+ D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d",
s->id, s->fd, s->peer?s->peer->fd:-1);
- D("RS(%d): closed\n", s->id);
+ D("RS(%d): closed", s->id);
free(s);
}
@@ -538,13 +538,13 @@
s->close = remote_socket_close;
s->transport = t;
- D("RS(%d): created\n", s->id);
+ D("RS(%d): created", s->id);
return s;
}
void connect_to_remote(asocket *s, const char *destination)
{
- D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd);
+ D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
apacket *p = get_apacket();
size_t len = strlen(destination) + 1;
@@ -552,7 +552,7 @@
fatal("destination oversized");
}
- D("LS(%d): connect('%s')\n", s->id, destination);
+ D("LS(%d): connect('%s')", s->id, destination);
p->msg.command = A_OPEN;
p->msg.arg0 = s->id;
p->msg.data_length = len;
@@ -671,14 +671,14 @@
TransportType type = kTransportAny;
#endif
- D("SS(%d): enqueue %d\n", s->id, p->len);
+ D("SS(%d): enqueue %d", s->id, p->len);
if(s->pkt_first == 0) {
s->pkt_first = p;
s->pkt_last = p;
} else {
if((s->pkt_first->len + p->len) > s->get_max_payload()) {
- D("SS(%d): overflow\n", s->id);
+ D("SS(%d): overflow", s->id);
put_apacket(p);
goto fail;
}
@@ -696,20 +696,20 @@
len = unhex(p->data, 4);
if((len < 1) || (len > 1024)) {
- D("SS(%d): bad size (%d)\n", s->id, len);
+ D("SS(%d): bad size (%d)", s->id, len);
goto fail;
}
- D("SS(%d): len is %d\n", s->id, len );
+ D("SS(%d): len is %d", s->id, len );
/* can't do anything until we have the full header */
if((len + 4) > p->len) {
- D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len);
+ D("SS(%d): waiting for %d more bytes", s->id, len+4 - p->len);
return 0;
}
p->data[len + 4] = 0;
- D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));
+ D("SS(%d): '%s'", s->id, (char*) (p->data + 4));
#if ADB_HOST
service = (char *)p->data + 4;
@@ -747,11 +747,11 @@
*/
if(handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
/* XXX fail message? */
- D( "SS(%d): handled host service '%s'\n", s->id, service );
+ D( "SS(%d): handled host service '%s'", s->id, service );
goto fail;
}
if (!strncmp(service, "transport", strlen("transport"))) {
- D( "SS(%d): okay transport\n", s->id );
+ D( "SS(%d): okay transport", s->id );
p->len = 0;
return 0;
}
@@ -762,7 +762,7 @@
*/
s2 = create_host_service_socket(service, serial);
if(s2 == 0) {
- D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
+ D( "SS(%d): couldn't create host service '%s'", s->id, service );
SendFail(s->peer->fd, "unknown host service");
goto fail;
}
@@ -782,7 +782,7 @@
s->peer->peer = s2;
s2->peer = s->peer;
s->peer = 0;
- D( "SS(%d): okay\n", s->id );
+ D( "SS(%d): okay", s->id );
s->close(s);
/* initial state is "ready" */
@@ -839,12 +839,12 @@
static void smart_socket_ready(asocket *s)
{
- D("SS(%d): ready\n", s->id);
+ D("SS(%d): ready", s->id);
}
static void smart_socket_close(asocket *s)
{
- D("SS(%d): closed\n", s->id);
+ D("SS(%d): closed", s->id);
if(s->pkt_first){
put_apacket(s->pkt_first);
}
@@ -858,7 +858,7 @@
static asocket *create_smart_socket(void)
{
- D("Creating smart socket \n");
+ D("Creating smart socket");
asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
if (s == NULL) fatal("cannot allocate socket");
s->enqueue = smart_socket_enqueue;
@@ -866,13 +866,13 @@
s->shutdown = NULL;
s->close = smart_socket_close;
- D("SS(%d)\n", s->id);
+ D("SS(%d)", s->id);
return s;
}
void connect_to_smartsocket(asocket *s)
{
- D("Connecting to smart socket \n");
+ D("Connecting to smart socket");
asocket *ss = create_smart_socket();
s->peer = ss;
ss->peer = s;
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 015f89e..b53cd77 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -122,7 +122,7 @@
// only need to check for INVALID_HANDLE_VALUE.
if (h != INVALID_HANDLE_VALUE) {
if (!CloseHandle(h)) {
- D("CloseHandle(%p) failed: %s\n", h,
+ D("CloseHandle(%p) failed: %s", h,
SystemErrorCodeToString(GetLastError()).c_str());
}
}
@@ -159,7 +159,7 @@
if (file_size > 0) {
data = (char*) malloc( file_size + 1 );
if (data == NULL) {
- D("load_file: could not allocate %ld bytes\n", file_size );
+ D("load_file: could not allocate %ld bytes", file_size );
file_size = 0;
} else {
DWORD out_bytes;
@@ -167,7 +167,7 @@
if ( !ReadFile( file, data, file_size, &out_bytes, NULL ) ||
out_bytes != file_size )
{
- D("load_file: could not read %ld bytes from '%s'\n", file_size, fn);
+ D("load_file: could not read %ld bytes from '%s'", file_size, fn);
free(data);
data = NULL;
file_size = 0;
@@ -229,7 +229,7 @@
fd -= WIN32_FH_BASE;
if (fd < 0 || fd >= WIN32_MAX_FHS) {
- D( "_fh_from_int: invalid fd %d passed to %s\n", fd + WIN32_FH_BASE,
+ D( "_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE,
func );
errno = EBADF;
return NULL;
@@ -238,7 +238,7 @@
f = &_win32_fhs[fd];
if (f->used == 0) {
- D( "_fh_from_int: invalid fd %d passed to %s\n", fd + WIN32_FH_BASE,
+ D( "_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE,
func );
errno = EBADF;
return NULL;
@@ -278,7 +278,7 @@
goto Exit;
}
}
- D( "_fh_alloc: no more free file descriptors\n" );
+ D( "_fh_alloc: no more free file descriptors" );
errno = EMFILE; // Too many open files
Exit:
if (f) {
@@ -349,7 +349,7 @@
DWORD read_bytes;
if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) {
- D( "adb_read: could not read %d bytes from %s\n", len, f->name );
+ D( "adb_read: could not read %d bytes from %s", len, f->name );
errno = EIO;
return -1;
} else if (read_bytes < (DWORD)len) {
@@ -362,7 +362,7 @@
DWORD wrote_bytes;
if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) {
- D( "adb_file_write: could not write %d bytes from %s\n", len, f->name );
+ D( "adb_file_write: could not write %d bytes from %s", len, f->name );
errno = EIO;
return -1;
} else if (wrote_bytes < (DWORD)len) {
@@ -422,7 +422,7 @@
desiredAccess = GENERIC_READ | GENERIC_WRITE;
break;
default:
- D("adb_open: invalid options (0x%0x)\n", options);
+ D("adb_open: invalid options (0x%0x)", options);
errno = EINVAL;
return -1;
}
@@ -441,17 +441,17 @@
D( "adb_open: could not open '%s': ", path );
switch (err) {
case ERROR_FILE_NOT_FOUND:
- D( "file not found\n" );
+ D( "file not found" );
errno = ENOENT;
return -1;
case ERROR_PATH_NOT_FOUND:
- D( "path not found\n" );
+ D( "path not found" );
errno = ENOTDIR;
return -1;
default:
- D( "unknown error: %s\n",
+ D( "unknown error: %s",
SystemErrorCodeToString( err ).c_str() );
errno = ENOENT;
return -1;
@@ -459,7 +459,7 @@
}
snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
- D( "adb_open: '%s' => fd %d\n", path, _fh_to_int(f) );
+ D( "adb_open: '%s' => fd %d", path, _fh_to_int(f) );
return _fh_to_int(f);
}
@@ -484,24 +484,24 @@
D( "adb_creat: could not open '%s': ", path );
switch (err) {
case ERROR_FILE_NOT_FOUND:
- D( "file not found\n" );
+ D( "file not found" );
errno = ENOENT;
return -1;
case ERROR_PATH_NOT_FOUND:
- D( "path not found\n" );
+ D( "path not found" );
errno = ENOTDIR;
return -1;
default:
- D( "unknown error: %s\n",
+ D( "unknown error: %s",
SystemErrorCodeToString( err ).c_str() );
errno = ENOENT;
return -1;
}
}
snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
- D( "adb_creat: '%s' => fd %d\n", path, _fh_to_int(f) );
+ D( "adb_creat: '%s' => fd %d", path, _fh_to_int(f) );
return _fh_to_int(f);
}
@@ -550,7 +550,7 @@
return -1;
}
- D( "adb_close: %s\n", f->name);
+ D( "adb_close: %s", f->name);
_fh_close(f);
return 0;
}
@@ -580,7 +580,7 @@
case WSAEMFILE: errno = EMFILE; break;
default:
errno = EINVAL;
- D( "_socket_set_errno: mapping Windows error code %lu to errno %d\n",
+ D( "_socket_set_errno: mapping Windows error code %lu to errno %d",
err, errno );
}
}
@@ -589,7 +589,7 @@
f->fh_socket = INVALID_SOCKET;
f->event = WSACreateEvent();
if (f->event == WSA_INVALID_EVENT) {
- D("WSACreateEvent failed: %s\n",
+ D("WSACreateEvent failed: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
// _event_socket_start assumes that this field is INVALID_HANDLE_VALUE
@@ -608,19 +608,19 @@
// If the socket is not connected, this returns an error. We want to
// minimize logging spam, so don't log these errors for now.
#if 0
- D("socket shutdown failed: %s\n",
+ D("socket shutdown failed: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
#endif
}
if (closesocket(f->fh_socket) == SOCKET_ERROR) {
- D("closesocket failed: %s\n",
+ D("closesocket failed: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
}
f->fh_socket = INVALID_SOCKET;
}
if (f->event != NULL) {
if (!CloseHandle(f->event)) {
- D("CloseHandle failed: %s\n",
+ D("CloseHandle failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
}
f->event = NULL;
@@ -641,7 +641,7 @@
// WSAEWOULDBLOCK is normal with a non-blocking socket, so don't trace
// that to reduce spam and confusion.
if (err != WSAEWOULDBLOCK) {
- D("recv fd %d failed: %s\n", _fh_to_int(f),
+ D("recv fd %d failed: %s", _fh_to_int(f),
SystemErrorCodeToString(err).c_str());
}
_socket_set_errno(err);
@@ -654,7 +654,7 @@
int result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
if (result == SOCKET_ERROR) {
const DWORD err = WSAGetLastError();
- D("send fd %d failed: %s\n", _fh_to_int(f),
+ D("send fd %d failed: %s", _fh_to_int(f),
SystemErrorCodeToString(err).c_str());
_socket_set_errno(err);
result = -1;
@@ -726,7 +726,7 @@
if(s == INVALID_SOCKET) {
*error = android::base::StringPrintf("cannot create socket: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
- D("%s\n", error->c_str());
+ D("%s", error->c_str());
return -1;
}
f->fh_socket = s;
@@ -737,7 +737,7 @@
*error = android::base::StringPrintf("cannot connect to %s:%u: %s",
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port),
SystemErrorCodeToString(err).c_str());
- D("could not connect to %s:%d: %s\n",
+ D("could not connect to %s:%d: %s",
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
}
@@ -745,7 +745,7 @@
const int fd = _fh_to_int(f.get());
snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", fd,
type != SOCK_STREAM ? "udp:" : "", port );
- D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
+ D( "port %d type %s => fd %d", port, type != SOCK_STREAM ? "udp" : "tcp",
fd );
f.release();
return fd;
@@ -780,7 +780,7 @@
if (s == INVALID_SOCKET) {
*error = android::base::StringPrintf("cannot create socket: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
- D("%s\n", error->c_str());
+ D("%s", error->c_str());
return -1;
}
@@ -794,7 +794,7 @@
*error = android::base::StringPrintf(
"cannot set socket option SO_EXCLUSIVEADDRUSE: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
- D("%s\n", error->c_str());
+ D("%s", error->c_str());
return -1;
}
@@ -804,7 +804,7 @@
*error = android::base::StringPrintf("cannot bind to %s:%u: %s",
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port),
SystemErrorCodeToString(err).c_str());
- D("could not bind to %s:%d: %s\n",
+ D("could not bind to %s:%d: %s",
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
}
@@ -812,7 +812,7 @@
if (listen(s, LISTEN_BACKLOG) == SOCKET_ERROR) {
*error = android::base::StringPrintf("cannot listen on socket: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
- D("could not listen on %s:%d: %s\n",
+ D("could not listen on %s:%d: %s",
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
}
@@ -821,7 +821,7 @@
snprintf( f->name, sizeof(f->name), "%d(%s-server:%s%d)", fd,
interface_address == INADDR_LOOPBACK ? "lo" : "any",
type != SOCK_STREAM ? "udp:" : "", port );
- D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
+ D( "port %d type %s => fd %d", port, type != SOCK_STREAM ? "udp" : "tcp",
fd );
f.release();
return fd;
@@ -865,7 +865,7 @@
*error = android::base::StringPrintf(
"cannot resolve host '%s' and port %s: %s", host.c_str(),
port_str, SystemErrorCodeToString(WSAGetLastError()).c_str());
- D("%s\n", error->c_str());
+ D("%s", error->c_str());
return -1;
}
std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*>
@@ -880,7 +880,7 @@
if(s == INVALID_SOCKET) {
*error = android::base::StringPrintf("cannot create socket: %s",
SystemErrorCodeToString(WSAGetLastError()).c_str());
- D("%s\n", error->c_str());
+ D("%s", error->c_str());
return -1;
}
f->fh_socket = s;
@@ -892,7 +892,7 @@
*error = android::base::StringPrintf("cannot connect to %s:%s: %s",
host.c_str(), port_str,
SystemErrorCodeToString(WSAGetLastError()).c_str());
- D("could not connect to %s:%s:%s: %s\n",
+ D("could not connect to %s:%s:%s: %s",
type != SOCK_STREAM ? "udp" : "tcp", host.c_str(), port_str,
error->c_str());
return -1;
@@ -901,7 +901,7 @@
const int fd = _fh_to_int(f.get());
snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", fd,
type != SOCK_STREAM ? "udp:" : "", port );
- D( "host '%s' port %d type %s => fd %d\n", host.c_str(), port,
+ D( "host '%s' port %d type %s => fd %d", host.c_str(), port,
type != SOCK_STREAM ? "udp" : "tcp", fd );
f.release();
return fd;
@@ -913,7 +913,7 @@
FH serverfh = _fh_from_int(serverfd, __func__);
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
- D("adb_socket_accept: invalid fd %d\n", serverfd);
+ D("adb_socket_accept: invalid fd %d", serverfd);
errno = EBADF;
return -1;
}
@@ -936,7 +936,7 @@
const int fd = _fh_to_int(fh.get());
snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name );
- D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, fd );
+ D( "adb_socket_accept on fd %d returns fd %d", serverfd, fd );
fh.release();
return fd;
}
@@ -947,7 +947,7 @@
FH fh = _fh_from_int(fd, __func__);
if ( !fh || fh->clazz != &_fh_socket_class ) {
- D("adb_setsockopt: invalid fd %d\n", fd);
+ D("adb_setsockopt: invalid fd %d", fd);
errno = EBADF;
return -1;
}
@@ -970,15 +970,15 @@
FH f = _fh_from_int(fd, __func__);
if (!f || f->clazz != &_fh_socket_class) {
- D("adb_shutdown: invalid fd %d\n", fd);
+ D("adb_shutdown: invalid fd %d", fd);
errno = EBADF;
return -1;
}
- D( "adb_shutdown: %s\n", f->name);
+ D( "adb_shutdown: %s", f->name);
if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
const DWORD err = WSAGetLastError();
- D("socket shutdown fd %d failed: %s\n", fd,
+ D("socket shutdown fd %d failed: %s", fd,
SystemErrorCodeToString(err).c_str());
_socket_set_errno(err);
return -1;
@@ -1073,7 +1073,7 @@
static void
bip_buffer_init( BipBuffer buffer )
{
- D( "bit_buffer_init %p\n", buffer );
+ D( "bit_buffer_init %p", buffer );
buffer->a_start = 0;
buffer->a_end = 0;
buffer->b_end = 0;
@@ -1103,7 +1103,7 @@
static void
bip_buffer_done( BipBuffer bip )
{
- BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout ));
+ BIPD(( "bip_buffer_done: %d->%d", bip->fdin, bip->fdout ));
CloseHandle( bip->evt_read );
CloseHandle( bip->evt_write );
DeleteCriticalSection( &bip->lock );
@@ -1117,7 +1117,7 @@
if (len <= 0)
return 0;
- BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+ BIPD(( "bip_buffer_write: enter %d->%d len %d", bip->fdin, bip->fdout, len ));
BIPDUMP( src, len );
EnterCriticalSection( &bip->lock );
@@ -1133,7 +1133,7 @@
/* spinlocking here is probably unfair, but let's live with it */
ret = WaitForSingleObject( bip->evt_write, INFINITE );
if (ret != WAIT_OBJECT_0) { /* buffer probably closed */
- D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() );
+ D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld", bip->fdin, bip->fdout, ret, GetLastError() );
return 0;
}
if (bip->closed) {
@@ -1143,7 +1143,7 @@
EnterCriticalSection( &bip->lock );
}
- BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+ BIPD(( "bip_buffer_write: exec %d->%d len %d", bip->fdin, bip->fdout, len ));
avail = BIP_BUFFER_SIZE - bip->a_end;
if (avail > 0)
@@ -1191,7 +1191,7 @@
SetEvent( bip->evt_read );
}
- BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
+ BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d",
bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
LeaveCriticalSection( &bip->lock );
@@ -1206,7 +1206,7 @@
if (len <= 0)
return 0;
- BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+ BIPD(( "bip_buffer_read: enter %d->%d len %d", bip->fdin, bip->fdout, len ));
EnterCriticalSection( &bip->lock );
while ( !bip->can_read )
@@ -1226,7 +1226,7 @@
ret = WaitForSingleObject( bip->evt_read, INFINITE );
if (ret != WAIT_OBJECT_0) { /* probably closed buffer */
- D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError());
+ D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld", bip->fdin, bip->fdout, ret, GetLastError());
return 0;
}
if (bip->closed) {
@@ -1237,7 +1237,7 @@
#endif
}
- BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
+ BIPD(( "bip_buffer_read: exec %d->%d len %d", bip->fdin, bip->fdout, len ));
avail = bip->a_end - bip->a_start;
assert( avail > 0 ); /* since can_read is TRUE */
@@ -1284,7 +1284,7 @@
}
BIPDUMP( (const unsigned char*)dst - count, count );
- BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
+ BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d",
bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
LeaveCriticalSection( &bip->lock );
@@ -1397,7 +1397,7 @@
pair = reinterpret_cast<SocketPair>(malloc(sizeof(*pair)));
if (pair == NULL) {
- D("adb_socketpair: not enough memory to allocate pipes\n" );
+ D("adb_socketpair: not enough memory to allocate pipes" );
return -1;
}
@@ -1419,7 +1419,7 @@
snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
- D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
+ D( "adb_socketpair: returns (%d, %d)", sv[0], sv[1] );
fa.release();
fb.release();
return 0;
@@ -1575,7 +1575,7 @@
EventHook node;
if (f == NULL) /* invalid arg */ {
- D("event_looper_hook: invalid fd=%d\n", fd);
+ D("event_looper_hook: invalid fd=%d", fd);
return;
}
@@ -1589,12 +1589,12 @@
if ( (node->wanted & events) != events ) {
/* this should update start/stop/check/peek */
- D("event_looper_hook: call hook for %d (new=%x, old=%x)\n",
+ D("event_looper_hook: call hook for %d (new=%x, old=%x)",
fd, node->wanted, events);
f->clazz->_fh_hook( f, events & ~node->wanted, node );
node->wanted |= events;
} else {
- D("event_looper_hook: ignoring events %x for %d wanted=%x)\n",
+ D("event_looper_hook: ignoring events %x for %d wanted=%x)",
events, fd, node->wanted);
}
}
@@ -1609,7 +1609,7 @@
if (node != NULL) {
int events2 = events & node->wanted;
if ( events2 == 0 ) {
- D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd );
+ D( "event_looper_unhook: events %x not registered for fd %d", events, fd );
return;
}
node->wanted &= ~events2;
@@ -1728,7 +1728,7 @@
threads = (WaitForAllParam*)malloc((chunks + (remains ? 1 : 0)) *
sizeof(WaitForAllParam));
if (threads == NULL) {
- D("Unable to allocate thread array for %d handles.\n", handles_count);
+ D("Unable to allocate thread array for %d handles.", handles_count);
return (int)WAIT_FAILED;
}
@@ -1736,7 +1736,7 @@
* reset" event that will remain set once it was set. */
main_event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (main_event == NULL) {
- D("Unable to create main event. Error: %ld\n", GetLastError());
+ D("Unable to create main event. Error: %ld", GetLastError());
free(threads);
return (int)WAIT_FAILED;
}
@@ -1769,7 +1769,7 @@
&threads[chunk], 0, NULL);
if (threads[chunk].thread == NULL) {
/* Unable to create a waiter thread. Collapse. */
- D("Unable to create a waiting thread %d of %d. errno=%d\n",
+ D("Unable to create a waiting thread %d of %d. errno=%d",
chunk, chunks, errno);
chunks = chunk;
SetEvent(main_event);
@@ -1829,11 +1829,11 @@
int removes = events0 & ~events;
int adds = events & ~events0;
if (removes) {
- D("fdevent_update: remove %x from %d\n", removes, fde->fd);
+ D("fdevent_update: remove %x from %d", removes, fde->fd);
event_looper_unhook( looper, fde->fd, removes );
}
if (adds) {
- D("fdevent_update: add %x to %d\n", adds, fde->fd);
+ D("fdevent_update: add %x to %d", adds, fde->fd);
event_looper_hook ( looper, fde->fd, adds );
}
}
@@ -1865,7 +1865,7 @@
for (hook = looper->hooks; hook; hook = hook->next)
{
if (hook->start && !hook->start(hook)) {
- D( "fdevent_process: error when starting a hook\n" );
+ D( "fdevent_process: error when starting a hook" );
return;
}
if (hook->h != INVALID_HANDLE_VALUE) {
@@ -1883,7 +1883,7 @@
}
if (looper->htab_count == 0) {
- D( "fdevent_process: nothing to wait for !!\n" );
+ D( "fdevent_process: nothing to wait for !!" );
return;
}
@@ -1891,17 +1891,17 @@
{
int wait_ret;
- D( "adb_win32: waiting for %d events\n", looper->htab_count );
+ D( "adb_win32: waiting for %d events", looper->htab_count );
if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
- D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS.\n", looper->htab_count);
+ D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS.", looper->htab_count);
wait_ret = _wait_for_all(looper->htab, looper->htab_count);
} else {
wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
}
if (wait_ret == (int)WAIT_FAILED) {
- D( "adb_win32: wait failed, error %ld\n", GetLastError() );
+ D( "adb_win32: wait failed, error %ld", GetLastError() );
} else {
- D( "adb_win32: got one (index %d)\n", wait_ret );
+ D( "adb_win32: got one (index %d)", wait_ret );
/* according to Cygwin, some objects like consoles wake up on "inappropriate" events
* like mouse movements. we need to filter these with the "check" function
@@ -1913,7 +1913,7 @@
if ( looper->htab[wait_ret] == hook->h &&
(!hook->check || hook->check(hook)) )
{
- D( "adb_win32: signaling %s for %x\n", hook->fh->name, hook->ready );
+ D( "adb_win32: signaling %s for %x", hook->fh->name, hook->ready );
event_hook_signal( hook );
gotone = 1;
break;
@@ -2205,14 +2205,14 @@
hook->h = fh->event;
if (hook->h == INVALID_HANDLE_VALUE) {
- D( "_event_socket_start: no event for %s\n", fh->name );
+ D( "_event_socket_start: no event for %s", fh->name );
return 0;
}
if ( flags != fh->mask ) {
- D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
+ D( "_event_socket_start: hooking %s for %x (flags %ld)", hook->fh->name, hook->wanted, flags );
if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
- D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() );
+ D( "_event_socket_start: WSAEventSelect() for %s failed, error %d", hook->fh->name, WSAGetLastError() );
CloseHandle( hook->h );
hook->h = INVALID_HANDLE_VALUE;
exit(1);
@@ -2241,7 +2241,7 @@
ResetEvent( hook->h );
}
}
- D( "_event_socket_check %s returns %d\n", fh->name, result );
+ D( "_event_socket_check %s returns %d", fh->name, result );
return result;
}
@@ -2305,10 +2305,10 @@
hook->h = wbip->evt_write;
else {
- D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
+ D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE" );
return 0;
}
- D( "_event_socketpair_start: hook %s for %x wanted=%x\n",
+ D( "_event_socketpair_start: hook %s for %x wanted=%x",
hook->fh->name, _fh_to_int(fh), hook->wanted);
return 1;
}
@@ -3118,7 +3118,7 @@
//
// Consume the input and 'continue' to cause us to get a new key
// event.
- D("_console_read: unknown virtual key code: %d, enhanced: %s\n",
+ D("_console_read: unknown virtual key code: %d, enhanced: %s",
vk, _is_enhanced_key(control_key_state) ? "true" : "false");
key_event->wRepeatCount = 0;
continue;
@@ -3192,7 +3192,7 @@
if (!SetConsoleMode(in, _old_console_mode & ~(ENABLE_PROCESSED_INPUT |
ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))) {
// This really should not fail.
- D("stdin_raw_init: SetConsoleMode() failed: %s\n",
+ D("stdin_raw_init: SetConsoleMode() failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
}
@@ -3214,7 +3214,7 @@
if (!SetConsoleMode(in, _old_console_mode)) {
// This really should not fail.
- D("stdin_raw_restore: SetConsoleMode() failed: %s\n",
+ D("stdin_raw_restore: SetConsoleMode() failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
}
}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 43691dc..e97c479 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -94,7 +94,7 @@
len -= r;
p += r;
} else {
- D("%s: read_packet (fd=%d), error ret=%d: %s\n", name, fd, r, strerror(errno));
+ D("%s: read_packet (fd=%d), error ret=%d: %s", name, fd, r, strerror(errno));
return -1;
}
}
@@ -124,7 +124,7 @@
len -= r;
p += r;
} else {
- D("%s: write_packet (fd=%d) error ret=%d: %s\n", name, fd, r, strerror(errno));
+ D("%s: write_packet (fd=%d) error ret=%d: %s", name, fd, r, strerror(errno));
return -1;
}
}
@@ -134,11 +134,11 @@
static void transport_socket_events(int fd, unsigned events, void *_t)
{
atransport *t = reinterpret_cast<atransport*>(_t);
- D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
+ D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
if(events & FDE_READ){
apacket *p = 0;
if(read_packet(fd, t->serial, &p)){
- D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
+ D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
} else {
handle_packet(p, (atransport *) _t);
}
@@ -164,7 +164,7 @@
print_packet("send", p);
if (t == NULL) {
- D("Transport is null \n");
+ D("Transport is null");
// Zap errno because print_packet() and other stuff have errno effect.
errno = 0;
fatal_errno("Transport is null");
@@ -175,26 +175,27 @@
}
}
-/* The transport is opened by transport_register_func before
-** the input and output threads are started.
-**
-** The output thread issues a SYNC(1, token) message to let
-** the input thread know to start things up. In the event
-** of transport IO failure, the output thread will post a
-** SYNC(0,0) message to ensure shutdown.
-**
-** The transport will not actually be closed until both
-** threads exit, but the input thread will kick the transport
-** on its way out to disconnect the underlying device.
-*/
-
-static void *output_thread(void *_t)
+// The transport is opened by transport_register_func before
+// the read_transport and write_transport threads are started.
+//
+// The read_transport thread issues a SYNC(1, token) message to let
+// the write_transport thread know to start things up. In the event
+// of transport IO failure, the read_transport thread will post a
+// SYNC(0,0) message to ensure shutdown.
+//
+// The transport will not actually be closed until both threads exit, but the threads
+// will kick the transport on their way out to disconnect the underlying device.
+//
+// read_transport thread reads data from a transport (representing a usb/tcp connection),
+// and makes the main thread call handle_packet().
+static void *read_transport_thread(void *_t)
{
atransport *t = reinterpret_cast<atransport*>(_t);
apacket *p;
- adb_thread_setname(android::base::StringPrintf("->%s", t->serial));
- D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
+ adb_thread_setname(android::base::StringPrintf("<-%s",
+ (t->serial != nullptr ? t->serial : "transport")));
+ D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
t->serial, t->fd, t->sync_token + 1);
p = get_apacket();
p->msg.command = A_SYNC;
@@ -203,30 +204,30 @@
p->msg.magic = A_SYNC ^ 0xffffffff;
if(write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
- D("%s: failed to write SYNC packet\n", t->serial);
+ D("%s: failed to write SYNC packet", t->serial);
goto oops;
}
- D("%s: data pump started\n", t->serial);
+ D("%s: data pump started", t->serial);
for(;;) {
p = get_apacket();
if(t->read_from_remote(p, t) == 0){
- D("%s: received remote packet, sending to transport\n",
+ D("%s: received remote packet, sending to transport",
t->serial);
if(write_packet(t->fd, t->serial, &p)){
put_apacket(p);
- D("%s: failed to write apacket to transport\n", t->serial);
+ D("%s: failed to write apacket to transport", t->serial);
goto oops;
}
} else {
- D("%s: remote read failed for transport\n", t->serial);
+ D("%s: remote read failed for transport", t->serial);
put_apacket(p);
break;
}
}
- D("%s: SYNC offline for transport\n", t->serial);
+ D("%s: SYNC offline for transport", t->serial);
p = get_apacket();
p->msg.command = A_SYNC;
p->msg.arg0 = 0;
@@ -234,59 +235,62 @@
p->msg.magic = A_SYNC ^ 0xffffffff;
if(write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
- D("%s: failed to write SYNC apacket to transport\n", t->serial);
+ D("%s: failed to write SYNC apacket to transport", t->serial);
}
oops:
- D("%s: transport output thread is exiting\n", t->serial);
+ D("%s: read_transport thread is exiting", t->serial);
kick_transport(t);
transport_unref(t);
return 0;
}
-static void *input_thread(void *_t)
+// write_transport thread gets packets sent by the main thread (through send_packet()),
+// and writes to a transport (representing a usb/tcp connection).
+static void *write_transport_thread(void *_t)
{
atransport *t = reinterpret_cast<atransport*>(_t);
apacket *p;
int active = 0;
- adb_thread_setname(android::base::StringPrintf("<-%s", t->serial));
- D("%s: starting transport input thread, reading from fd %d\n",
+ adb_thread_setname(android::base::StringPrintf("->%s",
+ (t->serial != nullptr ? t->serial : "transport")));
+ D("%s: starting write_transport thread, reading from fd %d",
t->serial, t->fd);
for(;;){
if(read_packet(t->fd, t->serial, &p)) {
- D("%s: failed to read apacket from transport on fd %d\n",
+ D("%s: failed to read apacket from transport on fd %d",
t->serial, t->fd );
break;
}
if(p->msg.command == A_SYNC){
if(p->msg.arg0 == 0) {
- D("%s: transport SYNC offline\n", t->serial);
+ D("%s: transport SYNC offline", t->serial);
put_apacket(p);
break;
} else {
if(p->msg.arg1 == t->sync_token) {
- D("%s: transport SYNC online\n", t->serial);
+ D("%s: transport SYNC online", t->serial);
active = 1;
} else {
- D("%s: transport ignoring SYNC %d != %d\n",
+ D("%s: transport ignoring SYNC %d != %d",
t->serial, p->msg.arg1, t->sync_token);
}
}
} else {
if(active) {
- D("%s: transport got packet, sending to remote\n", t->serial);
+ D("%s: transport got packet, sending to remote", t->serial);
t->write_to_remote(p, t);
} else {
- D("%s: transport ignoring packet while offline\n", t->serial);
+ D("%s: transport ignoring packet while offline", t->serial);
}
}
put_apacket(p);
}
- D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
+ D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
kick_transport(t);
transport_unref(t);
return 0;
@@ -351,7 +355,7 @@
device_tracker* tracker = (device_tracker*) socket;
asocket* peer = socket->peer;
- D( "device tracker %p removed\n", tracker);
+ D( "device tracker %p removed", tracker);
if (peer) {
peer->peer = NULL;
peer->close(peer);
@@ -398,7 +402,7 @@
device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
if (tracker == nullptr) fatal("cannot allocate device tracker");
- D( "device tracker %p created\n", tracker);
+ D( "device tracker %p created", tracker);
tracker->socket.enqueue = device_tracker_enqueue;
tracker->socket.ready = device_tracker_ready;
@@ -452,7 +456,7 @@
len -= r;
p += r;
} else {
- D("transport_read_action: on fd %d: %s\n", fd, strerror(errno));
+ D("transport_read_action: on fd %d: %s", fd, strerror(errno));
return -1;
}
}
@@ -472,7 +476,7 @@
len -= r;
p += r;
} else {
- D("transport_write_action: on fd %d: %s\n", fd, strerror(errno));
+ D("transport_write_action: on fd %d: %s", fd, strerror(errno));
return -1;
}
}
@@ -496,7 +500,7 @@
t = m.transport;
if (m.action == 0) {
- D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
+ D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
/* IMPORTANT: the remove closes one half of the
** socket pair. The close closes the other half.
@@ -534,7 +538,7 @@
fatal_errno("cannot open transport socketpair");
}
- D("transport: %s socketpair: (%d,%d) starting\n", t->serial, s[0], s[1]);
+ D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
t->transport_socket = s[0];
t->fd = s[1];
@@ -546,12 +550,12 @@
fdevent_set(&(t->transport_fde), FDE_READ);
- if (!adb_thread_create(input_thread, t)) {
- fatal_errno("cannot create input thread");
+ if (!adb_thread_create(write_transport_thread, t)) {
+ fatal_errno("cannot create write_transport thread");
}
- if (!adb_thread_create(output_thread, t)) {
- fatal_errno("cannot create output thread");
+ if (!adb_thread_create(read_transport_thread, t)) {
+ fatal_errno("cannot create read_transport thread");
}
}
@@ -570,7 +574,7 @@
if(adb_socketpair(s)){
fatal_errno("cannot open transport registration socketpair");
}
- D("socketpair: (%d,%d)\n", s[0], s[1]);
+ D("socketpair: (%d,%d)", s[0], s[1]);
transport_registration_send = s[0];
transport_registration_recv = s[1];
@@ -589,7 +593,7 @@
tmsg m;
m.transport = transport;
m.action = 1;
- D("transport: %s registered\n", transport->serial);
+ D("transport: %s registered", transport->serial);
if(transport_write_action(transport_registration_send, &m)) {
fatal_errno("cannot write transport registration socket\n");
}
@@ -600,7 +604,7 @@
tmsg m;
m.transport = transport;
m.action = 0;
- D("transport: %s removed\n", transport->serial);
+ D("transport: %s removed", transport->serial);
if(transport_write_action(transport_registration_send, &m)) {
fatal_errno("cannot write transport registration socket\n");
}
@@ -613,12 +617,12 @@
CHECK_GT(t->ref_count, 0u);
t->ref_count--;
if (t->ref_count == 0) {
- D("transport: %s unref (kicking and closing)\n", t->serial);
+ D("transport: %s unref (kicking and closing)", t->serial);
kick_transport_locked(t);
t->close(t);
remove_transport(t);
} else {
- D("transport: %s unref (count=%zu)\n", t->serial, t->ref_count);
+ D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
}
adb_mutex_unlock(&transport_lock);
}
@@ -885,7 +889,7 @@
serial = buf;
}
- D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
+ D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
if (init_socket_transport(t, s, port, local) < 0) {
delete t;
return -1;
@@ -937,9 +941,9 @@
for (auto& t : transport_list) {
// TCP/IP devices have adb_port == 0.
if (t->type == kTransportLocal && t->adb_port == 0) {
- // Kicking breaks the output thread of this transport out of any read, then
- // the output thread will notify the main thread to make this transport
- // offline. Then the main thread will notify the input thread to exit.
+ // Kicking breaks the read_transport thread of this transport out of any read, then
+ // the read_transport thread will notify the main thread to make this transport
+ // offline. Then the main thread will notify the write_transport thread to exit.
// Finally, this transport will be closed and freed in the main thread.
kick_transport_locked(t);
}
@@ -953,7 +957,7 @@
const char* devpath, unsigned writeable) {
atransport* t = new atransport();
- D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
+ D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
serial ? serial : "");
init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
if(serial) {
@@ -986,12 +990,12 @@
int check_header(apacket *p, atransport *t)
{
if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
- D("check_header(): invalid magic\n");
+ D("check_header(): invalid magic");
return -1;
}
if(p->msg.data_length > t->get_max_payload()) {
- D("check_header(): %u > atransport::max_payload = %zu\n",
+ D("check_header(): %u > atransport::max_payload = %zu",
p->msg.data_length, t->get_max_payload());
return -1;
}
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 6821cfc..0c4315a 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -51,22 +51,22 @@
static int remote_read(apacket *p, atransport *t)
{
if(!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))){
- D("remote local: read terminated (message)\n");
+ D("remote local: read terminated (message)");
return -1;
}
if(check_header(p, t)) {
- D("bad header: terminated (data)\n");
+ D("bad header: terminated (data)");
return -1;
}
if(!ReadFdExactly(t->sfd, p->data, p->msg.data_length)){
- D("remote local: terminated (data)\n");
+ D("remote local: terminated (data)");
return -1;
}
if(check_data(p)) {
- D("bad data: terminated (data)\n");
+ D("bad data: terminated (data)");
return -1;
}
@@ -78,7 +78,7 @@
int length = p->msg.data_length;
if(!WriteFdExactly(t->sfd, &p->msg, sizeof(amessage) + length)) {
- D("remote local: write terminated\n");
+ D("remote local: write terminated");
return -1;
}
@@ -108,7 +108,7 @@
}
if (fd >= 0) {
- D("client: connected on remote on fd %d\n", fd);
+ D("client: connected on remote on fd %d", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
std::string serial = android::base::StringPrintf("emulator-%d", console_port);
@@ -124,7 +124,7 @@
static void *client_socket_thread(void *x)
{
adb_thread_setname("client_socket_thread");
- D("transport: client_socket_thread() starting\n");
+ D("transport: client_socket_thread() starting");
while (true) {
int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
int count = ADB_LOCAL_TRANSPORT_MAX;
@@ -148,14 +148,14 @@
int port = (int) (uintptr_t) arg;
adb_thread_setname("server socket");
- D("transport: server_socket_thread() starting\n");
+ D("transport: server_socket_thread() starting");
serverfd = -1;
for(;;) {
if(serverfd == -1) {
std::string error;
serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
if(serverfd < 0) {
- D("server: cannot bind socket yet: %s\n", error.c_str());
+ D("server: cannot bind socket yet: %s", error.c_str());
adb_sleep_ms(1000);
continue;
}
@@ -163,16 +163,16 @@
}
alen = sizeof(addr);
- D("server: trying to get new connection from %d\n", port);
+ D("server: trying to get new connection from %d", port);
fd = adb_socket_accept(serverfd, &addr, &alen);
if(fd >= 0) {
- D("server: new connection on fd %d\n", fd);
+ D("server: new connection on fd %d", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
register_socket_transport(fd, "host", port, 1);
}
}
- D("transport: server_socket_thread() exiting\n");
+ D("transport: server_socket_thread() exiting");
return 0;
}
@@ -234,7 +234,7 @@
char con_name[32];
adb_thread_setname("qemu socket");
- D("transport: qemu_socket_thread() starting\n");
+ D("transport: qemu_socket_thread() starting");
/* adb QEMUD service connection request. */
snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port);
@@ -244,7 +244,7 @@
if (fd < 0) {
/* This could be an older version of the emulator, that doesn't
* implement adb QEMUD service. Fall back to the old TCP way. */
- D("adb service is not available. Falling back to TCP socket.\n");
+ D("adb service is not available. Falling back to TCP socket.");
adb_thread_create(server_socket_thread, arg);
return 0;
}
@@ -261,7 +261,7 @@
* or 'ko' on failure. */
res = adb_read(fd, tmp, sizeof(tmp));
if (res != 2 || memcmp(tmp, _ok_resp, 2)) {
- D("Accepting ADB host connection has failed.\n");
+ D("Accepting ADB host connection has failed.");
adb_close(fd);
} else {
/* Host is connected. Register the transport, and start the
@@ -273,15 +273,15 @@
/* Prepare for accepting of the next ADB host connection. */
fd = qemu_pipe_open(con_name);
if (fd < 0) {
- D("adb service become unavailable.\n");
+ D("adb service become unavailable.");
return 0;
}
} else {
- D("Unable to send the '%s' request to ADB service.\n", _accept_req);
+ D("Unable to send the '%s' request to ADB service.", _accept_req);
return 0;
}
}
- D("transport: qemu_socket_thread() exiting\n");
+ D("transport: qemu_socket_thread() exiting");
return 0;
}
#endif // !ADB_HOST
@@ -309,7 +309,7 @@
debug_name = "server";
#endif // !ADB_HOST
- D("transport: local %s init\n", debug_name);
+ D("transport: local %s init", debug_name);
if (!adb_thread_create(func, (void *) (uintptr_t) port)) {
fatal_errno("cannot create local socket %s thread", debug_name);
}
@@ -410,12 +410,12 @@
find_emulator_transport_by_adb_port_locked(adb_port);
int index = get_available_local_transport_index_locked();
if (existing_transport != NULL) {
- D("local transport for port %d already registered (%p)?\n",
+ D("local transport for port %d already registered (%p)?",
adb_port, existing_transport);
fail = -1;
} else if (index < 0) {
// Too many emulators.
- D("cannot register more emulators. Maximum is %d\n",
+ D("cannot register more emulators. Maximum is %d",
ADB_LOCAL_TRANSPORT_MAX);
fail = -1;
} else {
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 96ccdad..b520607 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -28,24 +28,24 @@
static int remote_read(apacket *p, atransport *t)
{
if(usb_read(t->usb, &p->msg, sizeof(amessage))){
- D("remote usb: read terminated (message)\n");
+ D("remote usb: read terminated (message)");
return -1;
}
if(check_header(p, t)) {
- D("remote usb: check_header failed\n");
+ D("remote usb: check_header failed");
return -1;
}
if(p->msg.data_length) {
if(usb_read(t->usb, p->data, p->msg.data_length)){
- D("remote usb: terminated (data)\n");
+ D("remote usb: terminated (data)");
return -1;
}
}
if(check_data(p)) {
- D("remote usb: check_data failed\n");
+ D("remote usb: check_data failed");
return -1;
}
@@ -57,12 +57,12 @@
unsigned size = p->msg.data_length;
if(usb_write(t->usb, &p->msg, sizeof(amessage))) {
- D("remote usb: 1 - write terminated\n");
+ D("remote usb: 1 - write terminated");
return -1;
}
if(p->msg.data_length == 0) return 0;
if(usb_write(t->usb, &p->data, size)) {
- D("remote usb: 2 - write terminated\n");
+ D("remote usb: 2 - write terminated");
return -1;
}
@@ -82,7 +82,7 @@
void init_usb_transport(atransport *t, usb_handle *h, ConnectionState state)
{
- D("transport: usb\n");
+ D("transport: usb");
t->close = remote_close;
t->kick = remote_kick;
t->read_from_remote = remote_read;
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 6ccc8e2..f2b9820 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -159,7 +159,7 @@
// should have device and configuration descriptors, and atleast two endpoints
if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
- D("desclength %zu is too small\n", desclength);
+ D("desclength %zu is too small", desclength);
unix_close(fd);
continue;
}
@@ -180,7 +180,7 @@
config = (struct usb_config_descriptor *)bufptr;
bufptr += USB_DT_CONFIG_SIZE;
if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
- D("usb_config_descriptor not found\n");
+ D("usb_config_descriptor not found");
unix_close(fd);
continue;
}
@@ -195,7 +195,7 @@
bufptr += length;
if (length != USB_DT_INTERFACE_SIZE) {
- D("interface descriptor has wrong size\n");
+ D("interface descriptor has wrong size");
break;
}
@@ -237,14 +237,14 @@
ep1->bDescriptorType != USB_DT_ENDPOINT ||
ep2->bLength != USB_DT_ENDPOINT_SIZE ||
ep2->bDescriptorType != USB_DT_ENDPOINT) {
- D("endpoints not found\n");
+ D("endpoints not found");
break;
}
// both endpoints should be bulk
if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
- D("bulk endpoints not found\n");
+ D("bulk endpoints not found");
continue;
}
/* aproto 01 needs 0 termination */
@@ -295,7 +295,7 @@
static int usb_bulk_write(usb_handle* h, const void* data, int len) {
std::unique_lock<std::mutex> lock(h->mutex);
- D("++ usb_bulk_write ++\n");
+ D("++ usb_bulk_write ++");
usbdevfs_urb* urb = &h->urb_out;
memset(urb, 0, sizeof(*urb));
@@ -334,7 +334,7 @@
static int usb_bulk_read(usb_handle* h, void* data, int len) {
std::unique_lock<std::mutex> lock(h->mutex);
- D("++ usb_bulk_read ++\n");
+ D("++ usb_bulk_read ++");
usbdevfs_urb* urb = &h->urb_in;
memset(urb, 0, sizeof(*urb));
@@ -355,7 +355,7 @@
h->urb_in_busy = true;
while (true) {
- D("[ reap urb - wait ]\n");
+ D("[ reap urb - wait ]");
h->reaper_thread = pthread_self();
int fd = h->fd;
lock.unlock();
@@ -375,14 +375,14 @@
if (saved_errno == EINTR) {
continue;
}
- D("[ reap urb - error ]\n");
+ D("[ reap urb - error ]");
errno = saved_errno;
return -1;
}
- D("[ urb @%p status = %d, actual = %d ]\n", out, out->status, out->actual_length);
+ D("[ urb @%p status = %d, actual = %d ]", out, out->status, out->actual_length);
if (out == &h->urb_in) {
- D("[ reap urb - IN complete ]\n");
+ D("[ reap urb - IN complete ]");
h->urb_in_busy = false;
if (urb->status != 0) {
errno = -urb->status;
@@ -391,7 +391,7 @@
return urb->actual_length;
}
if (out == &h->urb_out) {
- D("[ reap urb - OUT compelete ]\n");
+ D("[ reap urb - OUT compelete ]");
h->urb_out_busy = false;
h->cv.notify_all();
}
@@ -401,12 +401,12 @@
int usb_write(usb_handle *h, const void *_data, int len)
{
- D("++ usb_write ++\n");
+ D("++ usb_write ++");
unsigned char *data = (unsigned char*) _data;
int n = usb_bulk_write(h, data, len);
if (n != len) {
- D("ERROR: n = %d, errno = %d (%s)\n", n, errno, strerror(errno));
+ D("ERROR: n = %d, errno = %d (%s)", n, errno, strerror(errno));
return -1;
}
@@ -416,7 +416,7 @@
return usb_bulk_write(h, _data, 0);
}
- D("-- usb_write --\n");
+ D("-- usb_write --");
return 0;
}
@@ -425,23 +425,23 @@
unsigned char *data = (unsigned char*) _data;
int n;
- D("++ usb_read ++\n");
+ D("++ usb_read ++");
while(len > 0) {
int xfer = len;
- D("[ usb read %d fd = %d], path=%s\n", xfer, h->fd, h->path.c_str());
+ D("[ usb read %d fd = %d], path=%s", xfer, h->fd, h->path.c_str());
n = usb_bulk_read(h, data, xfer);
- D("[ usb read %d ] = %d, path=%s\n", xfer, n, h->path.c_str());
+ D("[ usb read %d ] = %d, path=%s", xfer, n, h->path.c_str());
if(n != xfer) {
if((errno == ETIMEDOUT) && (h->fd != -1)) {
- D("[ timeout ]\n");
+ D("[ timeout ]");
if(n > 0){
data += n;
len -= n;
}
continue;
}
- D("ERROR: n = %d, errno = %d (%s)\n",
+ D("ERROR: n = %d, errno = %d (%s)",
n, errno, strerror(errno));
return -1;
}
@@ -450,13 +450,13 @@
data += xfer;
}
- D("-- usb_read --\n");
+ D("-- usb_read --");
return 0;
}
void usb_kick(usb_handle* h) {
std::lock_guard<std::mutex> lock(h->mutex);
- D("[ kicking %p (fd = %d) ]\n", h, h->fd);
+ D("[ kicking %p (fd = %d) ]", h, h->fd);
if (!h->dead) {
h->dead = true;
@@ -491,7 +491,7 @@
std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
g_usb_handles.remove(h);
- D("-- usb close %p (fd = %d) --\n", h, h->fd);
+ D("-- usb close %p (fd = %d) --", h, h->fd);
delete h;
@@ -518,7 +518,7 @@
}
}
- D("[ usb located new device %s (%d/%d/%d) ]\n", dev_name, ep_in, ep_out, interface);
+ D("[ usb located new device %s (%d/%d/%d) ]", dev_name, ep_in, ep_out, interface);
std::unique_ptr<usb_handle> usb(new usb_handle);
usb->path = dev_name;
usb->ep_in = ep_in;
@@ -533,18 +533,18 @@
// Opening RW failed, so see if we have RO access.
usb->fd = unix_open(usb->path.c_str(), O_RDONLY | O_CLOEXEC);
if (usb->fd == -1) {
- D("[ usb open %s failed: %s]\n", usb->path.c_str(), strerror(errno));
+ D("[ usb open %s failed: %s]", usb->path.c_str(), strerror(errno));
return;
}
usb->writeable = 0;
}
- D("[ usb opened %s%s, fd=%d]\n",
+ D("[ usb opened %s%s, fd=%d]",
usb->path.c_str(), (usb->writeable ? "" : " (read-only)"), usb->fd);
if (usb->writeable) {
if (ioctl(usb->fd, USBDEVFS_CLAIMINTERFACE, &interface) != 0) {
- D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]\n", usb->fd, strerror(errno));
+ D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]", usb->fd, strerror(errno));
return;
}
}
@@ -554,7 +554,7 @@
"/sys/bus/usb/devices/%s/serial", dev_path + 4);
std::string serial;
if (!android::base::ReadFileToString(serial_path, &serial)) {
- D("[ usb read %s failed: %s ]\n", serial_path.c_str(), strerror(errno));
+ D("[ usb read %s failed: %s ]", serial_path.c_str(), strerror(errno));
// We don't actually want to treat an unknown serial as an error because
// devices aren't able to communicate a serial number in early bringup.
// http://b/20883914
@@ -573,7 +573,7 @@
static void* device_poll_thread(void* unused) {
adb_thread_setname("device poll");
- D("Created device thread\n");
+ D("Created device thread");
while (true) {
// TODO: Use inotify.
find_usb_device("/dev/bus/usb", register_device);
@@ -592,6 +592,6 @@
sigaction(SIGALRM, &actions, nullptr);
if (!adb_thread_create(device_poll_thread, nullptr)) {
- fatal_errno("cannot create input thread");
+ fatal_errno("cannot create device_poll thread");
}
}
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index e1d7594..c7a9b58 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -218,7 +218,7 @@
adb_cond_wait(&usb->notify, &usb->lock);
adb_mutex_unlock(&usb->lock);
- D("[ usb_thread - opening device ]\n");
+ D("[ usb_thread - opening device ]");
do {
/* XXX use inotify? */
fd = unix_open("/dev/android_adb", O_RDWR);
@@ -230,12 +230,12 @@
adb_sleep_ms(1000);
}
} while (fd < 0);
- D("[ opening device succeeded ]\n");
+ D("[ opening device succeeded ]");
close_on_exec(fd);
usb->fd = fd;
- D("[ usb_thread - registering device ]\n");
+ D("[ usb_thread - registering device ]");
register_usb_transport(usb, 0, 0, 1);
}
@@ -247,20 +247,20 @@
{
int n;
- D("about to write (fd=%d, len=%d)\n", h->fd, len);
+ D("about to write (fd=%d, len=%d)", h->fd, len);
n = unix_write(h->fd, data, len);
if(n != len) {
- D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
+ D("ERROR: fd = %d, n = %d, errno = %d (%s)",
h->fd, n, errno, strerror(errno));
return -1;
}
- D("[ done fd=%d ]\n", h->fd);
+ D("[ done fd=%d ]", h->fd);
return 0;
}
static int usb_adb_read(usb_handle *h, void *data, int len)
{
- D("about to read (fd=%d, len=%d)\n", h->fd, len);
+ D("about to read (fd=%d, len=%d)", h->fd, len);
while (len > 0) {
// The kernel implementation of adb_read in f_adb.c doesn't support
// reads larger then 4096 bytes. Read the data in 4096 byte chunks to
@@ -268,20 +268,20 @@
int bytes_to_read = len < 4096 ? len : 4096;
int n = unix_read(h->fd, data, bytes_to_read);
if (n != bytes_to_read) {
- D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
+ D("ERROR: fd = %d, n = %d, errno = %d (%s)",
h->fd, n, errno, strerror(errno));
return -1;
}
len -= n;
data = ((char*)data) + n;
}
- D("[ done fd=%d ]\n", h->fd);
+ D("[ done fd=%d ]", h->fd);
return 0;
}
static void usb_adb_kick(usb_handle *h)
{
- D("usb_kick\n");
+ D("usb_kick");
adb_mutex_lock(&h->lock);
unix_close(h->fd);
h->fd = -1;
@@ -311,12 +311,12 @@
// and when we are not.
int fd = unix_open("/dev/android_adb_enable", O_RDWR);
if (fd < 0) {
- D("failed to open /dev/android_adb_enable\n");
+ D("failed to open /dev/android_adb_enable");
} else {
close_on_exec(fd);
}
- D("[ usb_init - starting thread ]\n");
+ D("[ usb_init - starting thread ]");
if (!adb_thread_create(usb_adb_open_thread, h)) {
fatal_errno("cannot create usb thread");
}
@@ -341,10 +341,10 @@
v2_descriptor.ss_descs = ss_descriptors;
if (h->control < 0) { // might have already done this before
- D("OPENING %s\n", USB_FFS_ADB_EP0);
+ D("OPENING %s", USB_FFS_ADB_EP0);
h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
if (h->control < 0) {
- D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno);
+ D("[ %s: cannot open control endpoint: errno=%d]", USB_FFS_ADB_EP0, errno);
goto err;
}
@@ -356,30 +356,30 @@
v1_descriptor.header.hs_count = 3;
v1_descriptor.fs_descs = fs_descriptors;
v1_descriptor.hs_descs = hs_descriptors;
- D("[ %s: Switching to V1_descriptor format errno=%d ]\n", USB_FFS_ADB_EP0, errno);
+ D("[ %s: Switching to V1_descriptor format errno=%d ]", USB_FFS_ADB_EP0, errno);
ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor));
if (ret < 0) {
- D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno);
+ D("[ %s: write descriptors failed: errno=%d ]", USB_FFS_ADB_EP0, errno);
goto err;
}
}
ret = adb_write(h->control, &strings, sizeof(strings));
if (ret < 0) {
- D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno);
+ D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
goto err;
}
}
h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
if (h->bulk_out < 0) {
- D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno);
+ D("[ %s: cannot open bulk-out ep: errno=%d ]", USB_FFS_ADB_OUT, errno);
goto err;
}
h->bulk_in = adb_open(USB_FFS_ADB_IN, O_RDWR);
if (h->bulk_in < 0) {
- D("[ %s: cannot open bulk-in ep: errno=%d ]\n", USB_FFS_ADB_IN, errno);
+ D("[ %s: cannot open bulk-in ep: errno=%d ]", USB_FFS_ADB_IN, errno);
goto err;
}
@@ -424,7 +424,7 @@
}
property_set("sys.usb.ffs.ready", "1");
- D("[ usb_thread - registering device ]\n");
+ D("[ usb_thread - registering device ]");
register_usb_transport(usb, 0, 0, 1);
}
@@ -442,19 +442,19 @@
count += ret;
}
- D("[ bulk_write done fd=%d ]\n", bulk_in);
+ D("[ bulk_write done fd=%d ]", bulk_in);
return count;
}
static int usb_ffs_write(usb_handle* h, const void* data, int len)
{
- D("about to write (fd=%d, len=%d)\n", h->bulk_in, 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\n", h->bulk_in, n, strerror(errno));
+ D("ERROR: fd = %d, n = %d: %s", h->bulk_in, n, strerror(errno));
return -1;
}
- D("[ done fd=%d ]\n", h->bulk_in);
+ D("[ done fd=%d ]", h->bulk_in);
return 0;
}
@@ -465,7 +465,7 @@
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 ]\n", bulk_out, length, count);
+ D("[ bulk_read failed fd=%d length=%zu count=%zu ]", bulk_out, length, count);
return -1;
}
count += ret;
@@ -476,13 +476,13 @@
static int usb_ffs_read(usb_handle* h, void* data, int len)
{
- D("about to read (fd=%d, len=%d)\n", h->bulk_out, 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\n", h->bulk_out, n, strerror(errno));
+ D("ERROR: fd = %d, n = %d: %s", h->bulk_out, n, strerror(errno));
return -1;
}
- D("[ done fd=%d ]\n", h->bulk_out);
+ D("[ done fd=%d ]", h->bulk_out);
return 0;
}
@@ -492,11 +492,11 @@
err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT);
if (err < 0)
- D("[ kick: source (fd=%d) clear halt failed (%d) ]\n", h->bulk_in, errno);
+ D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in, errno);
err = ioctl(h->bulk_out, FUNCTIONFS_CLEAR_HALT);
if (err < 0)
- D("[ kick: sink (fd=%d) clear halt failed (%d) ]\n", h->bulk_out, errno);
+ D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno);
adb_mutex_lock(&h->lock);
@@ -514,7 +514,7 @@
static void usb_ffs_init()
{
- D("[ usb_init - using FunctionFS ]\n");
+ D("[ usb_init - using FunctionFS ]");
usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
if (h == nullptr) fatal("couldn't allocate usb_handle");
@@ -529,7 +529,7 @@
adb_cond_init(&h->notify, 0);
adb_mutex_init(&h->lock, 0);
- D("[ usb_init - starting thread ]\n");
+ D("[ usb_init - starting thread ]");
if (!adb_thread_create(usb_ffs_open_thread, h)) {
fatal_errno("[ cannot create usb thread ]\n");
}
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index d9e2fb2..8037606 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -439,7 +439,7 @@
adb_cond_init(&start_cond, NULL);
if (!adb_thread_create(RunLoopThread, nullptr)) {
- fatal_errno("cannot create input thread");
+ fatal_errno("cannot create RunLoop thread");
}
// Wait for initialization to finish
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index ab36475..5bb0100 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -172,7 +172,7 @@
void* device_poll_thread(void* unused) {
adb_thread_setname("Device Poll");
- D("Created device thread\n");
+ D("Created device thread");
while(1) {
find_devices();
@@ -208,7 +208,7 @@
// heavyweight WMI APIs to get power notifications. But for the common case
// of a developer's interactive session, a window message pump is more
// appropriate.
- D("Created power notification thread\n");
+ D("Created power notification thread");
adb_thread_setname("Power Notifier");
// Window class names are process specific.
@@ -252,7 +252,7 @@
// do that, but it might be possible for that to occur when logging off or
// shutting down. Not a big deal since the whole process will be going away
// soon anyway.
- D("Power notification thread exiting\n");
+ D("Power notification thread exiting");
return NULL;
}
@@ -272,7 +272,7 @@
// Allocate our handle
usb_handle* ret = (usb_handle*)calloc(1, sizeof(usb_handle));
if (NULL == ret) {
- D("Could not allocate %u bytes for usb_handle: %s\n", sizeof(usb_handle),
+ D("Could not allocate %u bytes for usb_handle: %s", sizeof(usb_handle),
strerror(errno));
goto fail;
}
@@ -284,7 +284,7 @@
// Create interface.
ret->adb_interface = AdbCreateInterfaceByName(interface_name);
if (NULL == ret->adb_interface) {
- D("AdbCreateInterfaceByName failed: %s\n",
+ D("AdbCreateInterfaceByName failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
}
@@ -295,7 +295,7 @@
AdbOpenAccessTypeReadWrite,
AdbOpenSharingModeReadWrite);
if (NULL == ret->adb_read_pipe) {
- D("AdbOpenDefaultBulkReadEndpoint failed: %s\n",
+ D("AdbOpenDefaultBulkReadEndpoint failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
}
@@ -306,7 +306,7 @@
AdbOpenAccessTypeReadWrite,
AdbOpenSharingModeReadWrite);
if (NULL == ret->adb_write_pipe) {
- D("AdbOpenDefaultBulkWriteEndpoint failed: %s\n",
+ D("AdbOpenDefaultBulkWriteEndpoint failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
}
@@ -318,14 +318,14 @@
&name_len,
true);
if (0 == name_len) {
- D("AdbGetInterfaceName returned name length of zero: %s\n",
+ D("AdbGetInterfaceName returned name length of zero: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
}
ret->interface_name = (char*)malloc(name_len);
if (NULL == ret->interface_name) {
- D("Could not allocate %lu bytes for interface_name: %s\n", name_len,
+ D("Could not allocate %lu bytes for interface_name: %s", name_len,
strerror(errno));
goto fail;
}
@@ -335,7 +335,7 @@
ret->interface_name,
&name_len,
true)) {
- D("AdbGetInterfaceName failed: %s\n",
+ D("AdbGetInterfaceName failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
}
@@ -357,9 +357,9 @@
unsigned long written = 0;
int err = 0;
- D("usb_write %d\n", len);
+ D("usb_write %d", len);
if (NULL == handle) {
- D("usb_write was passed NULL handle\n");
+ D("usb_write was passed NULL handle");
err = EINVAL;
goto fail;
}
@@ -370,18 +370,18 @@
(unsigned long)len,
&written,
time_out)) {
- D("AdbWriteEndpointSync failed: %s\n",
+ D("AdbWriteEndpointSync failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
err = EIO;
goto fail;
}
// Make sure that we've written what we were asked to write
- D("usb_write got: %ld, expected: %d\n", written, len);
+ D("usb_write got: %ld, expected: %d", written, len);
if (written != (unsigned long)len) {
// If this occurs, this code should be changed to repeatedly call
// AdbWriteEndpointSync() until all bytes are written.
- D("AdbWriteEndpointSync was supposed to write %d, but only wrote %ld\n",
+ D("AdbWriteEndpointSync was supposed to write %d, but only wrote %ld",
len, written);
err = EIO;
goto fail;
@@ -394,7 +394,7 @@
0,
&written,
time_out)) {
- D("AdbWriteEndpointSync of zero length packet failed: %s\n",
+ D("AdbWriteEndpointSync of zero length packet failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
err = EIO;
goto fail;
@@ -407,11 +407,11 @@
// Any failure should cause us to kick the device instead of leaving it a
// zombie state with potential to hang.
if (NULL != handle) {
- D("Kicking device due to error in usb_write\n");
+ D("Kicking device due to error in usb_write");
usb_kick(handle);
}
- D("usb_write failed\n");
+ D("usb_write failed");
errno = err;
return -1;
}
@@ -421,9 +421,9 @@
unsigned long read = 0;
int err = 0;
- D("usb_read %d\n", len);
+ D("usb_read %d", len);
if (NULL == handle) {
- D("usb_read was passed NULL handle\n");
+ D("usb_read was passed NULL handle");
err = EINVAL;
goto fail;
}
@@ -431,12 +431,12 @@
while (len > 0) {
if (!AdbReadEndpointSync(handle->adb_read_pipe, data, len, &read,
time_out)) {
- D("AdbReadEndpointSync failed: %s\n",
+ D("AdbReadEndpointSync failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
err = EIO;
goto fail;
}
- D("usb_read got: %ld, expected: %d\n", read, len);
+ D("usb_read got: %ld, expected: %d", read, len);
data = (char *)data + read;
len -= read;
@@ -448,11 +448,11 @@
// Any failure should cause us to kick the device instead of leaving it a
// zombie state with potential to hang.
if (NULL != handle) {
- D("Kicking device due to error in usb_read\n");
+ D("Kicking device due to error in usb_read");
usb_kick(handle);
}
- D("usb_read failed\n");
+ D("usb_read failed");
errno = err;
return -1;
}
@@ -460,13 +460,13 @@
// Wrapper around AdbCloseHandle() that logs diagnostics.
static void _adb_close_handle(ADBAPIHANDLE adb_handle) {
if (!AdbCloseHandle(adb_handle)) {
- D("AdbCloseHandle(%p) failed: %s\n", adb_handle,
+ D("AdbCloseHandle(%p) failed: %s", adb_handle,
SystemErrorCodeToString(GetLastError()).c_str());
}
}
void usb_cleanup_handle(usb_handle* handle) {
- D("usb_cleanup_handle\n");
+ D("usb_cleanup_handle");
if (NULL != handle) {
if (NULL != handle->interface_name)
free(handle->interface_name);
@@ -494,7 +494,7 @@
}
void usb_kick(usb_handle* handle) {
- D("usb_kick\n");
+ D("usb_kick");
if (NULL != handle) {
adb_mutex_lock(&usb_lock);
@@ -507,7 +507,7 @@
}
int usb_close(usb_handle* handle) {
- D("usb_close\n");
+ D("usb_close");
if (NULL != handle) {
// Remove handle from the list
@@ -539,7 +539,7 @@
if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
&device_desc)) {
- D("AdbGetUsbDeviceDescriptor failed: %s\n",
+ D("AdbGetUsbDeviceDescriptor failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
return 0;
}
@@ -549,7 +549,7 @@
if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
&interf_desc)) {
- D("AdbGetUsbInterfaceDescriptor failed: %s\n",
+ D("AdbGetUsbInterfaceDescriptor failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
return 0;
}
@@ -567,9 +567,9 @@
// assuming zero is a valid bulk endpoint ID
if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) {
handle->zero_mask = endpoint_info.max_packet_size - 1;
- D("device zero_mask: 0x%x\n", handle->zero_mask);
+ D("device zero_mask: 0x%x", handle->zero_mask);
} else {
- D("AdbGetEndpointInformation failed: %s\n",
+ D("AdbGetEndpointInformation failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
}
}
@@ -593,7 +593,7 @@
AdbEnumInterfaces(usb_class_id, true, true, true);
if (NULL == enum_handle) {
- D("AdbEnumInterfaces failed: %s\n",
+ D("AdbEnumInterfaces failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
return;
}
@@ -617,7 +617,7 @@
if (NULL != handle) {
// Lets see if this interface (device) belongs to us
if (recognized_device(handle)) {
- D("adding a new device %s\n", interf_name);
+ D("adding a new device %s", interf_name);
char serial_number[512];
unsigned long serial_number_len = sizeof(serial_number);
if (AdbGetSerialNumber(handle->adb_interface,
@@ -628,12 +628,12 @@
if (register_new_device(handle)) {
register_usb_transport(handle, serial_number, NULL, 1);
} else {
- D("register_new_device failed for %s\n", interf_name);
+ D("register_new_device failed for %s", interf_name);
usb_cleanup_handle(handle);
free(handle);
}
} else {
- D("cannot get serial number: %s\n",
+ D("cannot get serial number: %s",
SystemErrorCodeToString(GetLastError()).c_str());
usb_cleanup_handle(handle);
free(handle);
@@ -650,7 +650,7 @@
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
// Only ERROR_NO_MORE_ITEMS is expected at the end of enumeration.
- D("AdbNextInterface failed: %s\n",
+ D("AdbNextInterface failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
}
diff --git a/base/Android.mk b/base/Android.mk
index 4e135f6..51dd736 100644
--- a/base/Android.mk
+++ b/base/Android.mk
@@ -68,6 +68,7 @@
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := libcutils
LOCAL_MULTILIB := both
+LOCAL_MODULE_HOST_OS := darwin linux windows
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
diff --git a/base/file.cpp b/base/file.cpp
index 9a340b7..3468dcf 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -28,6 +28,10 @@
#include "cutils/log.h"
#include "utils/Compat.h"
+#if !defined(_WIN32)
+#define O_BINARY 0
+#endif
+
namespace android {
namespace base {
@@ -45,8 +49,7 @@
bool ReadFileToString(const std::string& path, std::string* content) {
content->clear();
- int fd =
- TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_BINARY));
if (fd == -1) {
return false;
}
@@ -80,9 +83,8 @@
#if !defined(_WIN32)
bool WriteStringToFile(const std::string& content, const std::string& path,
mode_t mode, uid_t owner, gid_t group) {
- int fd = TEMP_FAILURE_RETRY(
- open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
- mode));
+ int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
+ int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
if (fd == -1) {
ALOGE("android::WriteStringToFile open failed: %s", strerror(errno));
return false;
@@ -108,9 +110,8 @@
#endif
bool WriteStringToFile(const std::string& content, const std::string& path) {
- int fd = TEMP_FAILURE_RETRY(
- open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
- DEFFILEMODE));
+ int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
+ int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE));
if (fd == -1) {
return false;
}
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index b0c5a12..22641e7 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -37,9 +37,9 @@
return -1;
}
// Use open() to match the close() that TemporaryFile's destructor does.
- // Note that on Windows, this does CR/LF translation and _setmode() should
- // be used to change that if appropriate.
- return open(template_name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
+ // Use O_BINARY to match base file APIs.
+ return open(template_name, O_CREAT | O_EXCL | O_RDWR | O_BINARY,
+ S_IRUSR | S_IWUSR);
}
char* mkdtemp(char* template_name) {
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
index 23bd342..72eeeda 100644
--- a/crash_reporter/crash_reporter.cc
+++ b/crash_reporter/crash_reporter.cc
@@ -25,6 +25,7 @@
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/flag_helper.h>
+#include <chromeos/process.h>
#include <chromeos/syslog_logging.h>
#include <metrics/metrics_library.h>
@@ -85,27 +86,32 @@
static void CountUserCrash() {
SendCrashMetrics(kCrashKindUser, "user");
- std::string command = StringPrintf(
- "/system/bin/dbus-send --type=signal --system / \"%s\" &",
- kUserCrashSignal);
// Announce through D-Bus whenever a user crash happens. This is
// used by the metrics daemon to log active use time between
// crashes.
//
- // This could be done more efficiently by explicit fork/exec or
- // using a dbus library directly. However, this should run
- // relatively rarely and longer term we may need to implement a
- // better way to do this that doesn't rely on D-Bus.
- //
- // We run in the background in case dbus daemon itself is crashed
+ // We run in the background in case dbus-daemon itself is crashed
// and not responding. This allows us to not block and potentially
// deadlock on a dbus-daemon crash. If dbus-daemon crashes without
// restarting, each crash will fork off a lot of dbus-send
// processes. Such a system is in a unusable state and will need
// to be restarted anyway.
+ //
+ // Note: This will mean that the dbus-send process will become a zombie and
+ // reparent to init for reaping, but that's OK -- see above.
- int status = system(command.c_str());
- LOG_IF(WARNING, status != 0) << "dbus-send running failed";
+ chromeos::ProcessImpl dbus_send;
+ dbus_send.AddArg("/system/bin/dbus-send");
+ dbus_send.AddArg("--type=signal");
+ dbus_send.AddArg("--system");
+ dbus_send.AddArg("/");
+ dbus_send.AddArg(kUserCrashSignal);
+ bool status = dbus_send.Start();
+ if (status) {
+ dbus_send.Release();
+ } else {
+ PLOG(WARNING) << "Sending UserCrash DBus signal failed";
+ }
}
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index ce8e15f..3f201ec 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -24,38 +24,25 @@
LOCAL_SRC_FILES := protocol.cpp engine.cpp bootimg_utils.cpp fastboot.cpp util.cpp fs.cpp
LOCAL_MODULE := fastboot
LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_CONLYFLAGS += -std=gnu99
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
LOCAL_CFLAGS += -DFASTBOOT_REVISION='"$(fastboot_version)"'
-ifeq ($(HOST_OS),linux)
- LOCAL_SRC_FILES += usb_linux.cpp util_linux.cpp
-endif
+LOCAL_SRC_FILES_linux := usb_linux.cpp util_linux.cpp
-ifeq ($(HOST_OS),darwin)
- LOCAL_SRC_FILES += usb_osx.cpp util_osx.cpp
- LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
- LOCAL_CFLAGS += -Wno-unused-parameter
-endif
+LOCAL_SRC_FILES_darwin := usb_osx.cpp util_osx.cpp
+LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
+LOCAL_CFLAGS_darwin := -Wno-unused-parameter
-ifeq ($(HOST_OS),windows)
- LOCAL_SRC_FILES += usb_windows.cpp util_windows.cpp
- EXTRA_STATIC_LIBS := AdbWinApi
- ifneq ($(strip $(USE_CYGWIN)),)
- # Pure cygwin case
- LOCAL_LDLIBS += -lpthread
- endif
- ifneq ($(strip $(USE_MINGW)),)
- # MinGW under Linux case
- LOCAL_LDLIBS += -lws2_32
- USE_SYSDEPS_WIN32 := 1
- endif
- LOCAL_C_INCLUDES += development/host/windows/usb/api
-endif
+LOCAL_SRC_FILES_windows := usb_windows.cpp util_windows.cpp
+LOCAL_STATIC_LIBRARIES_windows := AdbWinApi
+LOCAL_REQUIRED_MODULES_windows := AdbWinApi
+LOCAL_LDLIBS_windows := -lws2_32
+LOCAL_C_INCLUDES_windows := development/host/windows/usb/api
LOCAL_STATIC_LIBRARIES := \
- $(EXTRA_STATIC_LIBS) \
libziparchive-host \
libext4_utils_host \
libsparse_host \
@@ -64,24 +51,18 @@
libz \
libbase
-ifneq ($(HOST_OS),windows)
-LOCAL_STATIC_LIBRARIES += libselinux
-endif # HOST_OS != windows
+LOCAL_STATIC_LIBRARIES_darwin := libselinux
+LOCAL_STATIC_LIBRARIES_linux := libselinux
-ifeq ($(HOST_OS),linux)
# libf2fs_dlutils_host will dlopen("libf2fs_fmt_host_dyn")
-LOCAL_CFLAGS += -DUSE_F2FS
-LOCAL_LDFLAGS += -ldl -rdynamic -Wl,-rpath,.
-LOCAL_REQUIRED_MODULES := libf2fs_fmt_host_dyn
+LOCAL_CFLAGS_linux := -DUSE_F2FS
+LOCAL_LDFLAGS_linux := -ldl -rdynamic -Wl,-rpath,.
+LOCAL_REQUIRED_MODULES_linux := libf2fs_fmt_host_dyn
# The following libf2fs_* are from system/extras/f2fs_utils,
# and do not use code in external/f2fs-tools.
-LOCAL_STATIC_LIBRARIES += libf2fs_utils_host libf2fs_ioutils_host libf2fs_dlutils_host
-endif
+LOCAL_STATIC_LIBRARIES_linux += libf2fs_utils_host libf2fs_ioutils_host libf2fs_dlutils_host
-# libc++ not available on windows yet
-ifneq ($(HOST_OS),windows)
- LOCAL_CXX_STL := libc++_static
-endif
+LOCAL_CXX_STL := libc++_static
# Don't add anything here, we don't want additional shared dependencies
# on the host fastboot tool, and shared libraries that link against libc++
@@ -104,7 +85,3 @@
LOCAL_CFLAGS := -Werror
include $(BUILD_HOST_EXECUTABLE)
endif
-
-ifeq ($(HOST_OS),windows)
-$(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll
-endif
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 8b0f714..d77d41f 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -20,6 +20,8 @@
#include <string.h>
#include <sys/mount.h>
+#include <cutils/properties.h>
+
#include "fs_mgr_priv.h"
struct fs_mgr_flag_values {
@@ -70,6 +72,7 @@
{ "zramsize=", MF_ZRAMSIZE },
{ "verify", MF_VERIFY },
{ "noemulatedsd", MF_NOEMULATEDSD },
+ { "slotselect", MF_SLOTSELECT },
{ "defaults", 0 },
{ 0, 0 },
};
@@ -307,6 +310,23 @@
fstab->recs[cnt].partnum = flag_vals.partnum;
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
fstab->recs[cnt].zram_size = flag_vals.zram_size;
+
+ /* If an A/B partition, modify block device to be the real block device */
+ if (fstab->recs[cnt].fs_mgr_flags & MF_SLOTSELECT) {
+ char propbuf[PROPERTY_VALUE_MAX];
+ char *tmp;
+
+ /* use the kernel parameter if set */
+ property_get("ro.boot.slot_suffix", propbuf, "");
+
+ if (asprintf(&tmp, "%s%s", fstab->recs[cnt].blk_device, propbuf) > 0) {
+ free(fstab->recs[cnt].blk_device);
+ fstab->recs[cnt].blk_device = tmp;
+ } else {
+ ERROR("Error updating block device name\n");
+ goto err;
+ }
+ }
cnt++;
}
fclose(fstab_file);
@@ -448,3 +468,8 @@
{
return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
}
+
+int fs_mgr_is_slotselect(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_SLOTSELECT;
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index d56111a..cc02bac 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -77,6 +77,7 @@
#define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only
external storage */
#define MF_FILEENCRYPTION 0x2000
+#define MF_SLOTSELECT 0x8000
#define DM_BUF_SIZE 4096
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index 9c077d6..087a0c4 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -68,7 +68,8 @@
#define ATRACE_TAG_BIONIC (1<<16)
#define ATRACE_TAG_POWER (1<<17)
#define ATRACE_TAG_PACKAGE_MANAGER (1<<18)
-#define ATRACE_TAG_LAST ATRACE_TAG_PACKAGE_MANAGER
+#define ATRACE_TAG_SYSTEM_SERVER (1<<19)
+#define ATRACE_TAG_LAST ATRACE_TAG_SYSTEM_SERVER
// Reserved for initialization.
#define ATRACE_TAG_NOT_READY (1ULL<<63)
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 7047e0f..3e8d62a 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -32,6 +32,8 @@
#include "android_filesystem_capability.h"
#endif
+#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name))
+
/* This is the master Users and Groups config for the platform.
* DO NOT EVER RENUMBER
*/
diff --git a/init/Android.mk b/init/Android.mk
index 58bff58..7670951 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -45,6 +45,7 @@
LOCAL_CPPFLAGS := $(init_cflags)
LOCAL_SRC_FILES:= \
action.cpp \
+ import_parser.cpp \
init_parser.cpp \
log.cpp \
parser.cpp \
diff --git a/init/action.cpp b/init/action.cpp
index dd366d3..c6cbc2e 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -21,46 +21,27 @@
#include <base/strings.h>
#include <base/stringprintf.h>
+#include "builtins.h"
#include "error.h"
#include "init_parser.h"
#include "log.h"
#include "property_service.h"
#include "util.h"
-class Action::Command
-{
-public:
- Command(int (*f)(const std::vector<std::string>& args),
- const std::vector<std::string>& args,
- const std::string& filename,
- int line);
+using android::base::Join;
+using android::base::StringPrintf;
- int InvokeFunc() const;
- std::string BuildCommandString() const;
- std::string BuildSourceString() const;
-
-private:
- int (*func_)(const std::vector<std::string>& args);
- const std::vector<std::string> args_;
- const std::string filename_;
- int line_;
-};
-
-Action::Command::Command(int (*f)(const std::vector<std::string>& args),
- const std::vector<std::string>& args,
- const std::string& filename,
- int line) :
- func_(f), args_(args), filename_(filename), line_(line)
-{
+Command::Command(BuiltinFunction f, const std::vector<std::string>& args,
+ const std::string& filename, int line)
+ : func_(f), args_(args), filename_(filename), line_(line) {
}
-int Action::Command::InvokeFunc() const
-{
+int Command::InvokeFunc() const {
std::vector<std::string> expanded_args;
expanded_args.resize(args_.size());
expanded_args[0] = args_[0];
for (std::size_t i = 1; i < args_.size(); ++i) {
- if (expand_props(args_[i], &expanded_args[i]) == -1) {
+ if (!expand_props(args_[i], &expanded_args[i])) {
ERROR("%s: cannot expand '%s'\n", args_[0].c_str(), args_[i].c_str());
return -EINVAL;
}
@@ -69,51 +50,71 @@
return func_(expanded_args);
}
-std::string Action::Command::BuildCommandString() const
-{
- return android::base::Join(args_, ' ');
+std::string Command::BuildCommandString() const {
+ return Join(args_, ' ');
}
-std::string Action::Command::BuildSourceString() const
-{
+std::string Command::BuildSourceString() const {
if (!filename_.empty()) {
- return android::base::StringPrintf(" (%s:%d)", filename_.c_str(), line_);
+ return StringPrintf(" (%s:%d)", filename_.c_str(), line_);
} else {
return std::string();
}
}
-Action::Action()
-{
+Action::Action(bool oneshot) : oneshot_(oneshot) {
}
-void Action::AddCommand(int (*f)(const std::vector<std::string>& args),
+const KeywordMap<BuiltinFunction>* Action::function_map_ = nullptr;
+
+bool Action::AddCommand(const std::vector<std::string>& args,
+ const std::string& filename, int line, std::string* err) {
+ if (!function_map_) {
+ *err = "no function map available";
+ return false;
+ }
+
+ if (args.empty()) {
+ *err = "command needed, but not provided";
+ return false;
+ }
+
+ auto function = function_map_->FindFunction(args[0], args.size() - 1, err);
+ if (!function) {
+ return false;
+ }
+
+ AddCommand(function, args, filename, line);
+ return true;
+}
+
+void Action::AddCommand(BuiltinFunction f,
const std::vector<std::string>& args,
- const std::string& filename, int line)
-{
- Action::Command* cmd = new Action::Command(f, args, filename, line);
- commands_.push_back(cmd);
+ const std::string& filename, int line) {
+ commands_.emplace_back(f, args, filename, line);
}
-std::size_t Action::NumCommands() const
-{
- return commands_.size();
-}
-
-void Action::ExecuteOneCommand(std::size_t command) const
-{
- ExecuteCommand(*commands_[command]);
-}
-
-void Action::ExecuteAllCommands() const
-{
- for (const auto& c : commands_) {
- ExecuteCommand(*c);
+void Action::CombineAction(const Action& action) {
+ for (const auto& c : action.commands_) {
+ commands_.emplace_back(c);
}
}
-void Action::ExecuteCommand(const Command& command) const
-{
+std::size_t Action::NumCommands() const {
+ return commands_.size();
+}
+
+void Action::ExecuteOneCommand(std::size_t command) const {
+ ExecuteCommand(commands_[command]);
+}
+
+void Action::ExecuteAllCommands() const {
+ for (const auto& c : commands_) {
+ ExecuteCommand(c);
+ }
+}
+
+void Action::ExecuteCommand(const Command& command) const {
Timer t;
int result = command.InvokeFunc();
@@ -128,8 +129,7 @@
}
}
-bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err)
-{
+bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) {
const static std::string prop_str("property:");
std::string prop_name(trigger.substr(prop_str.length()));
size_t equal_pos = prop_name.find('=');
@@ -149,8 +149,7 @@
return true;
}
-bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err)
-{
+bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err) {
const static std::string prop_str("property:");
for (std::size_t i = 0; i < args.size(); ++i) {
if (i % 2) {
@@ -179,21 +178,26 @@
return true;
}
-bool Action::InitSingleTrigger(const std::string& trigger)
-{
+bool Action::InitSingleTrigger(const std::string& trigger) {
std::vector<std::string> name_vector{trigger};
std::string err;
return InitTriggers(name_vector, &err);
}
+// This function checks that all property triggers are satisfied, that is
+// for each (name, value) in property_triggers_, check that the current
+// value of the property 'name' == value.
+//
+// It takes an optional (name, value) pair, which if provided must
+// be present in property_triggers_; it skips the check of the current
+// property value for this pair.
bool Action::CheckPropertyTriggers(const std::string& name,
- const std::string& value) const
-{
- bool found = name.empty();
+ const std::string& value) const {
if (property_triggers_.empty()) {
return true;
}
+ bool found = name.empty();
for (const auto& t : property_triggers_) {
const auto& trigger_name = t.first;
const auto& trigger_value = t.second;
@@ -214,27 +218,23 @@
return found;
}
-bool Action::CheckEventTrigger(const std::string& trigger) const
-{
+bool Action::CheckEventTrigger(const std::string& trigger) const {
return !event_trigger_.empty() &&
trigger == event_trigger_ &&
CheckPropertyTriggers();
}
bool Action::CheckPropertyTrigger(const std::string& name,
- const std::string& value) const
-{
+ const std::string& value) const {
return event_trigger_.empty() && CheckPropertyTriggers(name, value);
}
-bool Action::TriggersEqual(const class Action& other) const
-{
+bool Action::TriggersEqual(const Action& other) const {
return property_triggers_ == other.property_triggers_ &&
event_trigger_ == other.event_trigger_;
}
-std::string Action::BuildTriggersString() const
-{
+std::string Action::BuildTriggersString() const {
std::string result;
for (const auto& t : property_triggers_) {
@@ -251,28 +251,26 @@
return result;
}
-void Action::DumpState() const
-{
+void Action::DumpState() const {
std::string trigger_name = BuildTriggersString();
INFO("on %s\n", trigger_name.c_str());
for (const auto& c : commands_) {
- std::string cmd_str = c->BuildCommandString();
+ std::string cmd_str = c.BuildCommandString();
INFO(" %s\n", cmd_str.c_str());
}
INFO("\n");
}
-
class EventTrigger : public Trigger {
public:
EventTrigger(const std::string& trigger) : trigger_(trigger) {
}
- bool CheckTriggers(const Action* action) override {
- return action->CheckEventTrigger(trigger_);
+ bool CheckTriggers(const Action& action) const override {
+ return action.CheckEventTrigger(trigger_);
}
private:
- std::string trigger_;
+ const std::string trigger_;
};
class PropertyTrigger : public Trigger {
@@ -280,27 +278,26 @@
PropertyTrigger(const std::string& name, const std::string& value)
: name_(name), value_(value) {
}
- bool CheckTriggers(const Action* action) override {
- return action->CheckPropertyTrigger(name_, value_);
+ bool CheckTriggers(const Action& action) const override {
+ return action.CheckPropertyTrigger(name_, value_);
}
private:
- std::string name_;
- std::string value_;
+ const std::string name_;
+ const std::string value_;
};
class BuiltinTrigger : public Trigger {
public:
BuiltinTrigger(Action* action) : action_(action) {
}
- bool CheckTriggers(const Action* action) override {
- return action == action_;
+ bool CheckTriggers(const Action& action) const override {
+ return action_ == &action;
}
private:
- Action* action_;
+ const Action* action_;
};
-ActionManager::ActionManager() : current_command_(0)
-{
+ActionManager::ActionManager() : current_command_(0) {
}
ActionManager& ActionManager::GetInstance() {
@@ -308,45 +305,56 @@
return instance;
}
-void ActionManager::QueueEventTrigger(const std::string& trigger)
-{
+void ActionManager::AddAction(std::unique_ptr<Action> action) {
+ auto old_action_it =
+ std::find_if(actions_.begin(), actions_.end(),
+ [&action] (std::unique_ptr<Action>& a) {
+ return action->TriggersEqual(*a);
+ });
+
+ if (old_action_it != actions_.end()) {
+ (*old_action_it)->CombineAction(*action);
+ } else {
+ actions_.emplace_back(std::move(action));
+ }
+}
+
+void ActionManager::QueueEventTrigger(const std::string& trigger) {
trigger_queue_.push(std::make_unique<EventTrigger>(trigger));
}
void ActionManager::QueuePropertyTrigger(const std::string& name,
- const std::string& value)
-{
+ const std::string& value) {
trigger_queue_.push(std::make_unique<PropertyTrigger>(name, value));
}
-void ActionManager::QueueAllPropertyTriggers()
-{
+void ActionManager::QueueAllPropertyTriggers() {
QueuePropertyTrigger("", "");
}
-void ActionManager::QueueBuiltinAction(int (*func)(const std::vector<std::string>& args),
- const std::string& name)
-{
- Action* act = new Action();
+void ActionManager::QueueBuiltinAction(BuiltinFunction func,
+ const std::string& name) {
+ auto action = std::make_unique<Action>(true);
std::vector<std::string> name_vector{name};
- if (!act->InitSingleTrigger(name)) {
+ if (!action->InitSingleTrigger(name)) {
return;
}
- act->AddCommand(func, name_vector);
+ action->AddCommand(func, name_vector);
- actions_.push_back(act);
- trigger_queue_.push(std::make_unique<BuiltinTrigger>(act));
+ trigger_queue_.push(std::make_unique<BuiltinTrigger>(action.get()));
+ actions_.emplace_back(std::move(action));
}
void ActionManager::ExecuteOneCommand() {
+ // Loop through the trigger queue until we have an action to execute
while (current_executing_actions_.empty() && !trigger_queue_.empty()) {
- std::copy_if(actions_.begin(), actions_.end(),
- std::back_inserter(current_executing_actions_),
- [this] (Action* act) {
- return trigger_queue_.front()->CheckTriggers(act);
- });
+ for (const auto& action : actions_) {
+ if (trigger_queue_.front()->CheckTriggers(*action)) {
+ current_executing_actions_.emplace(action.get());
+ }
+ }
trigger_queue_.pop();
}
@@ -354,59 +362,67 @@
return;
}
- Action* action = current_executing_actions_.back();
- if (!action->NumCommands()) {
- current_executing_actions_.pop_back();
- return;
- }
+ auto action = current_executing_actions_.front();
if (current_command_ == 0) {
std::string trigger_name = action->BuildTriggersString();
- INFO("processing action %p (%s)\n", action, trigger_name.c_str());
+ INFO("processing action (%s)\n", trigger_name.c_str());
}
- action->ExecuteOneCommand(current_command_++);
+ action->ExecuteOneCommand(current_command_);
+
+ // If this was the last command in the current action, then remove
+ // the action from the executing list.
+ // If this action was oneshot, then also remove it from actions_.
+ ++current_command_;
if (current_command_ == action->NumCommands()) {
+ current_executing_actions_.pop();
current_command_ = 0;
- current_executing_actions_.pop_back();
+ if (action->oneshot()) {
+ auto eraser = [&action] (std::unique_ptr<Action>& a) {
+ return a.get() == action;
+ };
+ actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
+ }
}
}
-bool ActionManager::HasMoreCommands() const
-{
+bool ActionManager::HasMoreCommands() const {
return !current_executing_actions_.empty() || !trigger_queue_.empty();
}
-Action* ActionManager::AddNewAction(const std::vector<std::string>& triggers,
- std::string* err)
-{
- if (triggers.size() < 1) {
- *err = "actions must have a trigger\n";
- return nullptr;
- }
-
- Action* act = new Action();
- if (!act->InitTriggers(triggers, err)) {
- return nullptr;
- }
-
- auto old_act_it =
- std::find_if(actions_.begin(), actions_.end(),
- [&act] (Action* a) { return act->TriggersEqual(*a); });
-
- if (old_act_it != actions_.end()) {
- delete act;
- return *old_act_it;
- }
-
- actions_.push_back(act);
- return act;
-}
-
-void ActionManager::DumpState() const
-{
+void ActionManager::DumpState() const {
for (const auto& a : actions_) {
a->DumpState();
}
INFO("\n");
}
+
+bool ActionParser::ParseSection(const std::vector<std::string>& args,
+ std::string* err) {
+ std::vector<std::string> triggers(args.begin() + 1, args.end());
+ if (triggers.size() < 1) {
+ *err = "actions must have a trigger";
+ return false;
+ }
+
+ auto action = std::make_unique<Action>(false);
+ if (!action->InitTriggers(triggers, err)) {
+ return false;
+ }
+
+ action_ = std::move(action);
+ return true;
+}
+
+bool ActionParser::ParseLineSection(const std::vector<std::string>& args,
+ const std::string& filename, int line,
+ std::string* err) const {
+ return action_ ? action_->AddCommand(args, filename, line, err) : false;
+}
+
+void ActionParser::EndSection() {
+ if (action_ && action_->NumCommands() > 0) {
+ ActionManager::GetInstance().AddAction(std::move(action_));
+ }
+}
diff --git a/init/action.h b/init/action.h
index 5088c71..6dee2d0 100644
--- a/init/action.h
+++ b/init/action.h
@@ -22,13 +22,36 @@
#include <string>
#include <vector>
+#include "builtins.h"
+#include "init_parser.h"
+#include "keyword_map.h"
+
+class Command {
+public:
+ Command(BuiltinFunction f, const std::vector<std::string>& args,
+ const std::string& filename, int line);
+
+ int InvokeFunc() const;
+ std::string BuildCommandString() const;
+ std::string BuildSourceString() const;
+
+private:
+ BuiltinFunction func_;
+ std::vector<std::string> args_;
+ std::string filename_;
+ int line_;
+};
+
class Action {
public:
- Action();
+ Action(bool oneshot = false);
- void AddCommand(int (*f)(const std::vector<std::string>& args),
+ bool AddCommand(const std::vector<std::string>& args,
+ const std::string& filename, int line, std::string* err);
+ void AddCommand(BuiltinFunction f,
const std::vector<std::string>& args,
const std::string& filename = "", int line = 0);
+ void CombineAction(const Action& action);
bool InitTriggers(const std::vector<std::string>& args, std::string* err);
bool InitSingleTrigger(const std::string& trigger);
std::size_t NumCommands() const;
@@ -37,13 +60,17 @@
bool CheckEventTrigger(const std::string& trigger) const;
bool CheckPropertyTrigger(const std::string& name,
const std::string& value) const;
- bool TriggersEqual(const class Action& other) const;
+ bool TriggersEqual(const Action& other) const;
std::string BuildTriggersString() const;
void DumpState() const;
-private:
- class Command;
+ bool oneshot() const { return oneshot_; }
+ static void set_function_map(const KeywordMap<BuiltinFunction>* function_map) {
+ function_map_ = function_map;
+ }
+
+private:
void ExecuteCommand(const Command& command) const;
bool CheckPropertyTriggers(const std::string& name = "",
const std::string& value = "") const;
@@ -51,27 +78,28 @@
std::map<std::string, std::string> property_triggers_;
std::string event_trigger_;
- std::vector<Command*> commands_;
+ std::vector<Command> commands_;
+ bool oneshot_;
+ static const KeywordMap<BuiltinFunction>* function_map_;
};
class Trigger {
public:
virtual ~Trigger() { }
- virtual bool CheckTriggers(const Action* action) = 0;
+ virtual bool CheckTriggers(const Action& action) const = 0;
};
class ActionManager {
public:
static ActionManager& GetInstance();
+
+ void AddAction(std::unique_ptr<Action> action);
void QueueEventTrigger(const std::string& trigger);
void QueuePropertyTrigger(const std::string& name, const std::string& value);
void QueueAllPropertyTriggers();
- void QueueBuiltinAction(int (*func)(const std::vector<std::string>& args),
- const std::string& name);
+ void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
void ExecuteOneCommand();
bool HasMoreCommands() const;
- Action* AddNewAction(const std::vector<std::string>& triggers,
- std::string* err);
void DumpState() const;
private:
@@ -80,10 +108,26 @@
ActionManager(ActionManager const&) = delete;
void operator=(ActionManager const&) = delete;
- std::vector<Action*> actions_;
+ std::vector<std::unique_ptr<Action>> actions_;
std::queue<std::unique_ptr<Trigger>> trigger_queue_;
- std::vector<Action*> current_executing_actions_;
+ std::queue<const Action*> current_executing_actions_;
std::size_t current_command_;
};
+class ActionParser : public SectionParser {
+public:
+ ActionParser() : action_(nullptr) {
+ }
+ bool ParseSection(const std::vector<std::string>& args,
+ std::string* err) override;
+ bool ParseLineSection(const std::vector<std::string>& args,
+ const std::string& filename, int line,
+ std::string* err) const override;
+ void EndSection() override;
+ void EndFile(const std::string&) override {
+ }
+private:
+ std::unique_ptr<Action> action_;
+};
+
#endif
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index efaee1c..a768762 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -15,7 +15,6 @@
*/
#include "bootchart.h"
-#include "keywords.h"
#include "log.h"
#include "property_service.h"
@@ -32,6 +31,7 @@
#include <memory>
#include <string>
+#include <vector>
#include <base/file.h>
diff --git a/init/bootchart.h b/init/bootchart.h
index cf61d83..47eda7a 100644
--- a/init/bootchart.h
+++ b/init/bootchart.h
@@ -17,6 +17,10 @@
#ifndef _BOOTCHART_H
#define _BOOTCHART_H
+#include <string>
+#include <vector>
+
+int do_bootchart_init(const std::vector<std::string>& args);
void bootchart_sample(int* timeout);
#endif /* _BOOTCHART_H */
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 97151c0..3ffa2e8 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "builtins.h"
+
#include <errno.h>
#include <fcntl.h>
#include <mntent.h>
@@ -44,10 +46,10 @@
#include <private/android_filesystem_config.h>
#include "action.h"
+#include "bootchart.h"
#include "devices.h"
#include "init.h"
#include "init_parser.h"
-#include "keywords.h"
#include "log.h"
#include "property_service.h"
#include "service.h"
@@ -60,8 +62,7 @@
// System call provided by bionic but not in any header file.
extern "C" int init_module(void *, unsigned long, const char *);
-static int insmod(const char *filename, const char *options)
-{
+static int insmod(const char *filename, const char *options) {
std::string module;
if (!read_file(filename, &module)) {
return -1;
@@ -71,8 +72,7 @@
return init_module(&module[0], module.size(), options);
}
-static int __ifupdown(const char *interface, int up)
-{
+static int __ifupdown(const char *interface, int up) {
struct ifreq ifr;
int s, ret;
@@ -99,8 +99,7 @@
return ret;
}
-static void unmount_and_fsck(const struct mntent *entry)
-{
+static void unmount_and_fsck(const struct mntent *entry) {
if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4"))
return;
@@ -160,8 +159,7 @@
}
}
-int do_class_start(const std::vector<std::string>& args)
-{
+static int do_class_start(const std::vector<std::string>& args) {
/* Starting a class does not start services
* which are explicitly disabled. They must
* be started individually.
@@ -171,27 +169,23 @@
return 0;
}
-int do_class_stop(const std::vector<std::string>& args)
-{
+static int do_class_stop(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->Stop(); });
return 0;
}
-int do_class_reset(const std::vector<std::string>& args)
-{
+static int do_class_reset(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->Reset(); });
return 0;
}
-int do_domainname(const std::vector<std::string>& args)
-{
+static int do_domainname(const std::vector<std::string>& args) {
return write_file("/proc/sys/kernel/domainname", args[1].c_str());
}
-int do_enable(const std::vector<std::string>& args)
-{
+static int do_enable(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
return -1;
@@ -199,7 +193,7 @@
return svc->Enable();
}
-int do_exec(const std::vector<std::string>& args) {
+static int do_exec(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().MakeExecOneshotService(args);
if (!svc) {
return -1;
@@ -211,23 +205,19 @@
return 0;
}
-int do_export(const std::vector<std::string>& args)
-{
+static int do_export(const std::vector<std::string>& args) {
return add_environment(args[1].c_str(), args[2].c_str());
}
-int do_hostname(const std::vector<std::string>& args)
-{
+static int do_hostname(const std::vector<std::string>& args) {
return write_file("/proc/sys/kernel/hostname", args[1].c_str());
}
-int do_ifup(const std::vector<std::string>& args)
-{
+static int do_ifup(const std::vector<std::string>& args) {
return __ifupdown(args[1].c_str(), 1);
}
-int do_insmod(const std::vector<std::string>& args)
-{
+static int do_insmod(const std::vector<std::string>& args) {
std::string options;
if (args.size() > 2) {
@@ -241,8 +231,7 @@
return insmod(args[1].c_str(), options.c_str());
}
-int do_mkdir(const std::vector<std::string>& args)
-{
+static int do_mkdir(const std::vector<std::string>& args) {
mode_t mode = 0755;
int ret;
@@ -310,8 +299,7 @@
#define DATA_MNT_POINT "/data"
/* mount <type> <device> <path> <flags ...> <options> */
-int do_mount(const std::vector<std::string>& args)
-{
+static int do_mount(const std::vector<std::string>& args) {
char tmp[64];
const char *source, *target, *system;
const char *options = NULL;
@@ -411,8 +399,7 @@
}
-static int wipe_data_via_recovery()
-{
+static int wipe_data_via_recovery() {
mkdir("/cache/recovery", 0700);
int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0600);
if (fd >= 0) {
@@ -427,16 +414,16 @@
while (1) { pause(); } // never reached
}
-void import_late()
-{
+static void import_late() {
static const std::vector<std::string> init_directories = {
"/system/etc/init",
"/vendor/etc/init",
"/odm/etc/init"
};
+ Parser& parser = Parser::GetInstance();
for (const auto& dir : init_directories) {
- init_parse_config(dir.c_str());
+ parser.ParseConfig(dir.c_str());
}
}
@@ -444,17 +431,13 @@
* This function might request a reboot, in which case it will
* not return.
*/
-int do_mount_all(const std::vector<std::string>& args)
-{
+static int do_mount_all(const std::vector<std::string>& args) {
pid_t pid;
int ret = -1;
int child_ret = -1;
int status;
struct fstab *fstab;
- if (args.size() != 2) {
- return -1;
- }
const char* fstabfile = args[1].c_str();
/*
* Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and
@@ -535,8 +518,7 @@
return ret;
}
-int do_swapon_all(const std::vector<std::string>& args)
-{
+static int do_swapon_all(const std::vector<std::string>& args) {
struct fstab *fstab;
int ret;
@@ -547,16 +529,14 @@
return ret;
}
-int do_setprop(const std::vector<std::string>& args)
-{
+static int do_setprop(const std::vector<std::string>& args) {
const char* name = args[1].c_str();
const char* value = args[2].c_str();
property_set(name, value);
return 0;
}
-int do_setrlimit(const std::vector<std::string>& args)
-{
+static int do_setrlimit(const std::vector<std::string>& args) {
struct rlimit limit;
int resource;
resource = std::stoi(args[1]);
@@ -565,8 +545,7 @@
return setrlimit(resource, &limit);
}
-int do_start(const std::vector<std::string>& args)
-{
+static int do_start(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
ERROR("do_start: Service %s not found\n", args[1].c_str());
@@ -577,8 +556,7 @@
return 0;
}
-int do_stop(const std::vector<std::string>& args)
-{
+static int do_stop(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
ERROR("do_stop: Service %s not found\n", args[1].c_str());
@@ -588,8 +566,7 @@
return 0;
}
-int do_restart(const std::vector<std::string>& args)
-{
+static int do_restart(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
ERROR("do_restart: Service %s not found\n", args[1].c_str());
@@ -599,8 +576,7 @@
return 0;
}
-int do_powerctl(const std::vector<std::string>& args)
-{
+static int do_powerctl(const std::vector<std::string>& args) {
const char* command = args[1].c_str();
int len = 0;
unsigned int cmd = 0;
@@ -636,34 +612,26 @@
callback_on_ro_remount);
}
-int do_trigger(const std::vector<std::string>& args)
-{
+static int do_trigger(const std::vector<std::string>& args) {
ActionManager::GetInstance().QueueEventTrigger(args[1]);
return 0;
}
-int do_symlink(const std::vector<std::string>& args)
-{
+static int do_symlink(const std::vector<std::string>& args) {
return symlink(args[1].c_str(), args[2].c_str());
}
-int do_rm(const std::vector<std::string>& args)
-{
+static int do_rm(const std::vector<std::string>& args) {
return unlink(args[1].c_str());
}
-int do_rmdir(const std::vector<std::string>& args)
-{
+static int do_rmdir(const std::vector<std::string>& args) {
return rmdir(args[1].c_str());
}
-int do_sysclktz(const std::vector<std::string>& args)
-{
+static int do_sysclktz(const std::vector<std::string>& args) {
struct timezone tz;
- if (args.size() != 2)
- return -1;
-
memset(&tz, 0, sizeof(tz));
tz.tz_minuteswest = std::stoi(args[1]);
if (settimeofday(NULL, &tz))
@@ -671,7 +639,7 @@
return 0;
}
-int do_verity_load_state(const std::vector<std::string>& args) {
+static int do_verity_load_state(const std::vector<std::string>& args) {
int mode = -1;
int rc = fs_mgr_load_verity_state(&mode);
if (rc == 0 && mode == VERITY_MODE_LOGGING) {
@@ -680,24 +648,23 @@
return rc;
}
-static void verity_update_property(fstab_rec *fstab, const char *mount_point, int mode, int status) {
+static void verity_update_property(fstab_rec *fstab, const char *mount_point,
+ int mode, int status) {
property_set(android::base::StringPrintf("partition.%s.verified", mount_point).c_str(),
android::base::StringPrintf("%d", mode).c_str());
}
-int do_verity_update_state(const std::vector<std::string>& args) {
+static int do_verity_update_state(const std::vector<std::string>& args) {
return fs_mgr_update_verity_state(verity_update_property);
}
-int do_write(const std::vector<std::string>& args)
-{
+static int do_write(const std::vector<std::string>& args) {
const char* path = args[1].c_str();
const char* value = args[2].c_str();
return write_file(path, value);
}
-int do_copy(const std::vector<std::string>& args)
-{
+static int do_copy(const std::vector<std::string>& args) {
char *buffer = NULL;
int rc = 0;
int fd1 = -1, fd2 = -1;
@@ -705,9 +672,6 @@
int brtw, brtr;
char *p;
- if (args.size() != 3)
- return -1;
-
if (stat(args[1].c_str(), &info) < 0)
return -1;
@@ -758,7 +722,7 @@
return rc;
}
-int do_chown(const std::vector<std::string>& args) {
+static int do_chown(const std::vector<std::string>& args) {
/* GID is optional. */
if (args.size() == 3) {
if (lchown(args[2].c_str(), decode_uid(args[1].c_str()), -1) == -1)
@@ -786,7 +750,7 @@
return mode;
}
-int do_chmod(const std::vector<std::string>& args) {
+static int do_chmod(const std::vector<std::string>& args) {
mode_t mode = get_mode(args[1].c_str());
if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
return -errno;
@@ -794,7 +758,7 @@
return 0;
}
-int do_restorecon(const std::vector<std::string>& args) {
+static int do_restorecon(const std::vector<std::string>& args) {
int ret = 0;
for (auto it = std::next(args.begin()); it != args.end(); ++it) {
@@ -804,7 +768,7 @@
return ret;
}
-int do_restorecon_recursive(const std::vector<std::string>& args) {
+static int do_restorecon_recursive(const std::vector<std::string>& args) {
int ret = 0;
for (auto it = std::next(args.begin()); it != args.end(); ++it) {
@@ -814,12 +778,7 @@
return ret;
}
-int do_loglevel(const std::vector<std::string>& args) {
- if (args.size() != 2) {
- ERROR("loglevel: missing argument\n");
- return -EINVAL;
- }
-
+static int do_loglevel(const std::vector<std::string>& args) {
int log_level = std::stoi(args[1]);
if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) {
ERROR("loglevel: invalid log level'%d'\n", log_level);
@@ -830,23 +789,16 @@
}
int do_load_persist_props(const std::vector<std::string>& args) {
- if (args.size() == 1) {
- load_persist_props();
- return 0;
- }
- return -1;
+ load_persist_props();
+ return 0;
}
-int do_load_all_props(const std::vector<std::string>& args) {
- if (args.size() == 1) {
- load_all_props();
- return 0;
- }
- return -1;
+static int do_load_all_props(const std::vector<std::string>& args) {
+ load_all_props();
+ return 0;
}
-int do_wait(const std::vector<std::string>& args)
-{
+static int do_wait(const std::vector<std::string>& args) {
if (args.size() == 2) {
return wait_for_file(args[1].c_str(), COMMAND_RETRY_TIMEOUT);
} else if (args.size() == 3) {
@@ -858,8 +810,7 @@
/*
* Callback to make a directory from the ext4 code
*/
-static int do_installkeys_ensure_dir_exists(const char* dir)
-{
+static int do_installkeys_ensure_dir_exists(const char* dir) {
if (make_dir(dir, 0700) && errno != EEXIST) {
return -1;
}
@@ -867,12 +818,7 @@
return 0;
}
-int do_installkey(const std::vector<std::string>& args)
-{
- if (args.size() != 2) {
- return -1;
- }
-
+static int do_installkey(const std::vector<std::string>& args) {
std::string prop_value = property_get("ro.crypto.type");
if (prop_value != "file") {
return 0;
@@ -881,3 +827,49 @@
return e4crypt_create_device_key(args[1].c_str(),
do_installkeys_ensure_dir_exists);
}
+
+BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
+ constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
+ static const Map builtin_functions = {
+ {"bootchart_init", {0, 0, do_bootchart_init}},
+ {"chmod", {2, 2, do_chmod}},
+ {"chown", {2, 3, do_chown}},
+ {"class_reset", {1, 1, do_class_reset}},
+ {"class_start", {1, 1, do_class_start}},
+ {"class_stop", {1, 1, do_class_stop}},
+ {"copy", {2, 2, do_copy}},
+ {"domainname", {1, 1, do_domainname}},
+ {"enable", {1, 1, do_enable}},
+ {"exec", {1, kMax, do_exec}},
+ {"export", {2, 2, do_export}},
+ {"hostname", {1, 1, do_hostname}},
+ {"ifup", {1, 1, do_ifup}},
+ {"insmod", {1, kMax, do_insmod}},
+ {"installkey", {1, 1, do_installkey}},
+ {"load_all_props", {0, 0, do_load_all_props}},
+ {"load_persist_props", {0, 0, do_load_persist_props}},
+ {"loglevel", {1, 1, do_loglevel}},
+ {"mkdir", {1, 4, do_mkdir}},
+ {"mount_all", {1, 1, do_mount_all}},
+ {"mount", {3, kMax, do_mount}},
+ {"powerctl", {1, 1, do_powerctl}},
+ {"restart", {1, 1, do_restart}},
+ {"restorecon", {1, kMax, do_restorecon}},
+ {"restorecon_recursive", {1, kMax, do_restorecon_recursive}},
+ {"rm", {1, 1, do_rm}},
+ {"rmdir", {1, 1, do_rmdir}},
+ {"setprop", {2, 2, do_setprop}},
+ {"setrlimit", {3, 3, do_setrlimit}},
+ {"start", {1, 1, do_start}},
+ {"stop", {1, 1, do_stop}},
+ {"swapon_all", {1, 1, do_swapon_all}},
+ {"symlink", {2, 2, do_symlink}},
+ {"sysclktz", {1, 1, do_sysclktz}},
+ {"trigger", {1, 1, do_trigger}},
+ {"verity_load_state", {0, 0, do_verity_load_state}},
+ {"verity_update_state", {0, 0, do_verity_update_state}},
+ {"wait", {1, 2, do_wait}},
+ {"write", {2, 2, do_write}},
+ };
+ return builtin_functions;
+}
diff --git a/init/builtins.h b/init/builtins.h
new file mode 100644
index 0000000..53f4a71
--- /dev/null
+++ b/init/builtins.h
@@ -0,0 +1,35 @@
+/*
+ * 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 _INIT_BUILTINS_H
+#define _INIT_BUILTINS_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "keyword_map.h"
+
+using BuiltinFunction = int (*) (const std::vector<std::string>& args);
+class BuiltinFunctionMap : public KeywordMap<BuiltinFunction> {
+public:
+ BuiltinFunctionMap() {
+ }
+private:
+ Map& map() const override;
+};
+
+#endif
diff --git a/init/import_parser.cpp b/init/import_parser.cpp
new file mode 100644
index 0000000..e2a0f83
--- /dev/null
+++ b/init/import_parser.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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 "import_parser.h"
+
+#include "errno.h"
+
+#include <string>
+#include <vector>
+
+#include "log.h"
+#include "util.h"
+
+bool ImportParser::ParseSection(const std::vector<std::string>& args,
+ std::string* err) {
+ if (args.size() != 2) {
+ *err = "single argument needed for import\n";
+ return false;
+ }
+
+ std::string conf_file;
+ bool ret = expand_props(args[1], &conf_file);
+ if (!ret) {
+ *err = "error while expanding import";
+ return false;
+ }
+
+ INFO("Added '%s' to import list\n", conf_file.c_str());
+ imports_.emplace_back(std::move(conf_file));
+ return true;
+}
+
+void ImportParser::EndFile(const std::string& filename) {
+ auto current_imports = std::move(imports_);
+ imports_.clear();
+ for (const auto& s : current_imports) {
+ if (!Parser::GetInstance().ParseConfig(s)) {
+ ERROR("could not import file '%s' from '%s': %s\n",
+ s.c_str(), filename.c_str(), strerror(errno));
+ }
+ }
+}
diff --git a/init/import_parser.h b/init/import_parser.h
new file mode 100644
index 0000000..0e91025
--- /dev/null
+++ b/init/import_parser.h
@@ -0,0 +1,43 @@
+/*
+ * 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 _INIT_IMPORT_PARSER_H
+#define _INIT_IMPORT_PARSER_H
+
+#include "init_parser.h"
+
+#include <string>
+#include <vector>
+
+class ImportParser : public SectionParser {
+public:
+ ImportParser() {
+ }
+ bool ParseSection(const std::vector<std::string>& args,
+ std::string* err) override;
+ bool ParseLineSection(const std::vector<std::string>& args,
+ const std::string& filename, int line,
+ std::string* err) const override {
+ return true;
+ }
+ void EndSection() override {
+ }
+ void EndFile(const std::string& filename) override;
+private:
+ std::vector<std::string> imports_;
+};
+
+#endif
diff --git a/init/init.cpp b/init/init.cpp
index c94a6fe..ee1351d 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -55,6 +55,7 @@
#include "action.h"
#include "bootchart.h"
#include "devices.h"
+#include "import_parser.h"
#include "init.h"
#include "init_parser.h"
#include "keychords.h"
@@ -604,7 +605,14 @@
property_load_boot_defaults();
start_property_service();
- init_parse_config("/init.rc");
+ const BuiltinFunctionMap function_map;
+ Action::set_function_map(&function_map);
+
+ Parser& parser = Parser::GetInstance();
+ parser.AddSectionParser("service",std::make_unique<ServiceParser>());
+ parser.AddSectionParser("on", std::make_unique<ActionParser>());
+ parser.AddSectionParser("import", std::make_unique<ImportParser>());
+ parser.ParseConfig("/init.rc");
ActionManager& am = ActionManager::GetInstance();
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 12f44f7..02b3985 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -14,387 +14,117 @@
* limitations under the License.
*/
-#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
#include "action.h"
-#include "init.h"
#include "init_parser.h"
#include "log.h"
#include "parser.h"
-#include "property_service.h"
#include "service.h"
#include "util.h"
#include <base/stringprintf.h>
-#include <cutils/iosched_policy.h>
-#include <cutils/list.h>
-static list_declare(service_list);
-
-struct import {
- struct listnode list;
- const char *filename;
-};
-
-static void *parse_service(struct parse_state *state, int nargs, char **args);
-static void parse_line_service(struct parse_state *state, int nargs, char **args);
-
-static void *parse_action(struct parse_state *state, int nargs, char **args);
-static void parse_line_action(struct parse_state *state, int nargs, char **args);
-
-#define SECTION 0x01
-#define COMMAND 0x02
-#define OPTION 0x04
-
-#include "keywords.h"
-
-#define KEYWORD(symbol, flags, nargs, func) \
- [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },
-
-static struct {
- const char *name;
- int (*func)(const std::vector<std::string>& args);
- size_t nargs;
- unsigned char flags;
-} keyword_info[KEYWORD_COUNT] = {
- [ K_UNKNOWN ] = { "unknown", 0, 0, 0 },
-#include "keywords.h"
-};
-#undef KEYWORD
-
-#define kw_is(kw, type) (keyword_info[kw].flags & (type))
-#define kw_name(kw) (keyword_info[kw].name)
-#define kw_func(kw) (keyword_info[kw].func)
-#define kw_nargs(kw) (keyword_info[kw].nargs)
-
-void dump_parser_state() {
- ServiceManager::GetInstance().DumpState();
- ActionManager::GetInstance().DumpState();
+Parser::Parser() {
}
-static int lookup_keyword(const char *s)
-{
- switch (*s++) {
- case 'b':
- if (!strcmp(s, "ootchart_init")) return K_bootchart_init;
- break;
- case 'c':
- if (!strcmp(s, "opy")) return K_copy;
- if (!strcmp(s, "lass")) return K_class;
- if (!strcmp(s, "lass_start")) return K_class_start;
- if (!strcmp(s, "lass_stop")) return K_class_stop;
- if (!strcmp(s, "lass_reset")) return K_class_reset;
- if (!strcmp(s, "onsole")) return K_console;
- if (!strcmp(s, "hown")) return K_chown;
- if (!strcmp(s, "hmod")) return K_chmod;
- if (!strcmp(s, "ritical")) return K_critical;
- break;
- case 'd':
- if (!strcmp(s, "isabled")) return K_disabled;
- if (!strcmp(s, "omainname")) return K_domainname;
- break;
- case 'e':
- if (!strcmp(s, "nable")) return K_enable;
- if (!strcmp(s, "xec")) return K_exec;
- if (!strcmp(s, "xport")) return K_export;
- break;
- case 'g':
- if (!strcmp(s, "roup")) return K_group;
- break;
- case 'h':
- if (!strcmp(s, "ostname")) return K_hostname;
- break;
- case 'i':
- if (!strcmp(s, "oprio")) return K_ioprio;
- if (!strcmp(s, "fup")) return K_ifup;
- if (!strcmp(s, "nsmod")) return K_insmod;
- if (!strcmp(s, "mport")) return K_import;
- if (!strcmp(s, "nstallkey")) return K_installkey;
- break;
- case 'k':
- if (!strcmp(s, "eycodes")) return K_keycodes;
- break;
- case 'l':
- if (!strcmp(s, "oglevel")) return K_loglevel;
- if (!strcmp(s, "oad_persist_props")) return K_load_persist_props;
- if (!strcmp(s, "oad_all_props")) return K_load_all_props;
- break;
- case 'm':
- if (!strcmp(s, "kdir")) return K_mkdir;
- if (!strcmp(s, "ount_all")) return K_mount_all;
- if (!strcmp(s, "ount")) return K_mount;
- break;
- case 'o':
- if (!strcmp(s, "n")) return K_on;
- if (!strcmp(s, "neshot")) return K_oneshot;
- if (!strcmp(s, "nrestart")) return K_onrestart;
- break;
- case 'p':
- if (!strcmp(s, "owerctl")) return K_powerctl;
- break;
- case 'r':
- if (!strcmp(s, "estart")) return K_restart;
- if (!strcmp(s, "estorecon")) return K_restorecon;
- if (!strcmp(s, "estorecon_recursive")) return K_restorecon_recursive;
- if (!strcmp(s, "mdir")) return K_rmdir;
- if (!strcmp(s, "m")) return K_rm;
- break;
- case 's':
- if (!strcmp(s, "eclabel")) return K_seclabel;
- if (!strcmp(s, "ervice")) return K_service;
- if (!strcmp(s, "etenv")) return K_setenv;
- if (!strcmp(s, "etprop")) return K_setprop;
- if (!strcmp(s, "etrlimit")) return K_setrlimit;
- if (!strcmp(s, "ocket")) return K_socket;
- if (!strcmp(s, "tart")) return K_start;
- if (!strcmp(s, "top")) return K_stop;
- if (!strcmp(s, "wapon_all")) return K_swapon_all;
- if (!strcmp(s, "ymlink")) return K_symlink;
- if (!strcmp(s, "ysclktz")) return K_sysclktz;
- break;
- case 't':
- if (!strcmp(s, "rigger")) return K_trigger;
- break;
- case 'u':
- if (!strcmp(s, "ser")) return K_user;
- break;
- case 'v':
- if (!strcmp(s, "erity_load_state")) return K_verity_load_state;
- if (!strcmp(s, "erity_update_state")) return K_verity_update_state;
- break;
- case 'w':
- if (!strcmp(s, "rite")) return K_write;
- if (!strcmp(s, "ritepid")) return K_writepid;
- if (!strcmp(s, "ait")) return K_wait;
- break;
- }
- return K_UNKNOWN;
+Parser& Parser::GetInstance() {
+ static Parser instance;
+ return instance;
}
-static void parse_line_no_op(struct parse_state*, int, char**) {
+void Parser::AddSectionParser(const std::string& name,
+ std::unique_ptr<SectionParser> parser) {
+ section_parsers_[name] = std::move(parser);
}
-int expand_props(const std::string& src, std::string* dst) {
- const char *src_ptr = src.c_str();
-
- if (!dst) {
- return -1;
- }
-
- /* - variables can either be $x.y or ${x.y}, in case they are only part
- * of the string.
- * - will accept $$ as a literal $.
- * - no nested property expansion, i.e. ${foo.${bar}} is not supported,
- * bad things will happen
- */
- while (*src_ptr) {
- const char *c;
-
- c = strchr(src_ptr, '$');
- if (!c) {
- dst->append(src_ptr);
- break;
- }
-
- dst->append(src_ptr, c);
- c++;
-
- if (*c == '$') {
- dst->push_back(*(c++));
- src_ptr = c;
- continue;
- } else if (*c == '\0') {
- break;
- }
-
- std::string prop_name;
- if (*c == '{') {
- c++;
- const char* end = strchr(c, '}');
- if (!end) {
- // failed to find closing brace, abort.
- ERROR("unexpected end of string in '%s', looking for }\n", src.c_str());
- goto err;
- }
- prop_name = std::string(c, end);
- c = end + 1;
- } else {
- prop_name = c;
- ERROR("using deprecated syntax for specifying property '%s', use ${name} instead\n",
- c);
- c += prop_name.size();
- }
-
- if (prop_name.empty()) {
- ERROR("invalid zero-length prop name in '%s'\n", src.c_str());
- goto err;
- }
-
- std::string prop_val = property_get(prop_name.c_str());
- if (prop_val.empty()) {
- ERROR("property '%s' doesn't exist while expanding '%s'\n",
- prop_name.c_str(), src.c_str());
- goto err;
- }
-
- dst->append(prop_val);
- src_ptr = c;
- continue;
- }
-
- return 0;
-err:
- return -1;
-}
-
-static void parse_import(struct parse_state *state, int nargs, char **args)
-{
- if (nargs != 2) {
- ERROR("single argument needed for import\n");
- return;
- }
-
- std::string conf_file;
- int ret = expand_props(args[1], &conf_file);
- if (ret) {
- ERROR("error while handling import on line '%d' in '%s'\n",
- state->line, state->filename);
- return;
- }
-
- struct import* import = (struct import*) calloc(1, sizeof(struct import));
- import->filename = strdup(conf_file.c_str());
-
- struct listnode *import_list = (listnode*) state->priv;
- list_add_tail(import_list, &import->list);
- INFO("Added '%s' to import list\n", import->filename);
-}
-
-static void parse_new_section(struct parse_state *state, int kw,
- int nargs, char **args)
-{
- printf("[ %s %s ]\n", args[0],
- nargs > 1 ? args[1] : "");
- switch(kw) {
- case K_service:
- state->context = parse_service(state, nargs, args);
- if (state->context) {
- state->parse_line = parse_line_service;
- return;
- }
- break;
- case K_on:
- state->context = parse_action(state, nargs, args);
- if (state->context) {
- state->parse_line = parse_line_action;
- return;
- }
- break;
- case K_import:
- parse_import(state, nargs, args);
- break;
- }
- state->parse_line = parse_line_no_op;
-}
-
-static void parse_config(const char *fn, const std::string& data)
-{
- struct listnode import_list;
- struct listnode *node;
- char *args[INIT_PARSER_MAXARGS];
-
- int nargs = 0;
-
+void Parser::ParseData(const std::string& filename, const std::string& data) {
//TODO: Use a parser with const input and remove this copy
std::vector<char> data_copy(data.begin(), data.end());
data_copy.push_back('\0');
parse_state state;
- state.filename = fn;
+ state.filename = filename.c_str();
state.line = 0;
state.ptr = &data_copy[0];
state.nexttoken = 0;
- state.parse_line = parse_line_no_op;
- list_init(&import_list);
- state.priv = &import_list;
+ SectionParser* section_parser = nullptr;
+ std::vector<std::string> args;
for (;;) {
switch (next_token(&state)) {
case T_EOF:
- state.parse_line(&state, 0, 0);
- goto parser_done;
+ if (section_parser) {
+ section_parser->EndSection();
+ }
+ return;
case T_NEWLINE:
state.line++;
- if (nargs) {
- int kw = lookup_keyword(args[0]);
- if (kw_is(kw, SECTION)) {
- state.parse_line(&state, 0, 0);
- parse_new_section(&state, kw, nargs, args);
- } else {
- state.parse_line(&state, nargs, args);
- }
- nargs = 0;
+ if (args.empty()) {
+ break;
}
+ if (section_parsers_.count(args[0])) {
+ if (section_parser) {
+ section_parser->EndSection();
+ }
+ section_parser = section_parsers_[args[0]].get();
+ std::string ret_err;
+ if (!section_parser->ParseSection(args, &ret_err)) {
+ parse_error(&state, "%s\n", ret_err.c_str());
+ section_parser = nullptr;
+ }
+ } else if (section_parser) {
+ std::string ret_err;
+ if (!section_parser->ParseLineSection(args, state.filename,
+ state.line, &ret_err)) {
+ parse_error(&state, "%s\n", ret_err.c_str());
+ }
+ }
+ args.clear();
break;
case T_TEXT:
- if (nargs < INIT_PARSER_MAXARGS) {
- args[nargs++] = state.text;
- }
+ args.emplace_back(state.text);
break;
}
}
-
-parser_done:
- list_for_each(node, &import_list) {
- struct import* import = node_to_item(node, struct import, list);
- if (!init_parse_config(import->filename)) {
- ERROR("could not import file '%s' from '%s': %s\n",
- import->filename, fn, strerror(errno));
- }
- }
}
-static bool init_parse_config_file(const char* path) {
- INFO("Parsing file %s...\n", path);
+bool Parser::ParseConfigFile(const std::string& path) {
+ INFO("Parsing file %s...\n", path.c_str());
Timer t;
std::string data;
- if (!read_file(path, &data)) {
+ if (!read_file(path.c_str(), &data)) {
return false;
}
data.push_back('\n'); // TODO: fix parse_config.
- parse_config(path, data);
- dump_parser_state();
+ ParseData(path, data);
+ for (const auto& sp : section_parsers_) {
+ sp.second->EndFile(path);
+ }
+ DumpState();
- NOTICE("(Parsing %s took %.2fs.)\n", path, t.duration());
+ NOTICE("(Parsing %s took %.2fs.)\n", path.c_str(), t.duration());
return true;
}
-static bool init_parse_config_dir(const char* path) {
- INFO("Parsing directory %s...\n", path);
- std::unique_ptr<DIR, int(*)(DIR*)> config_dir(opendir(path), closedir);
+bool Parser::ParseConfigDir(const std::string& path) {
+ INFO("Parsing directory %s...\n", path.c_str());
+ std::unique_ptr<DIR, int(*)(DIR*)> config_dir(opendir(path.c_str()), closedir);
if (!config_dir) {
- ERROR("Could not import directory '%s'\n", path);
+ ERROR("Could not import directory '%s'\n", path.c_str());
return false;
}
dirent* current_file;
while ((current_file = readdir(config_dir.get()))) {
std::string current_path =
- android::base::StringPrintf("%s/%s", path, current_file->d_name);
+ android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
// Ignore directories and only process regular files.
if (current_file->d_type == DT_REG) {
- if (!init_parse_config_file(current_path.c_str())) {
+ if (!ParseConfigFile(current_path)) {
ERROR("could not import file '%s'\n", current_path.c_str());
}
}
@@ -402,97 +132,14 @@
return true;
}
-bool init_parse_config(const char* path) {
- if (is_dir(path)) {
- return init_parse_config_dir(path);
+bool Parser::ParseConfig(const std::string& path) {
+ if (is_dir(path.c_str())) {
+ return ParseConfigDir(path);
}
- return init_parse_config_file(path);
+ return ParseConfigFile(path);
}
-static void *parse_service(struct parse_state *state, int nargs, char **args)
-{
- if (nargs < 3) {
- parse_error(state, "services must have a name and a program\n");
- return nullptr;
- }
- std::vector<std::string> str_args(args + 2, args + nargs);
- std::string ret_err;
- Service* svc = ServiceManager::GetInstance().AddNewService(args[1], "default",
- str_args, &ret_err);
-
- if (!svc) {
- parse_error(state, "%s\n", ret_err.c_str());
- }
-
- return svc;
-}
-
-static void parse_line_service(struct parse_state *state, int nargs, char **args)
-{
- if (nargs == 0) {
- return;
- }
-
- Service* svc = static_cast<Service*>(state->context);
- int kw = lookup_keyword(args[0]);
- std::vector<std::string> str_args(args, args + nargs);
- std::string ret_err;
- bool ret = svc->HandleLine(kw, str_args, &ret_err);
-
- if (!ret) {
- parse_error(state, "%s\n", ret_err.c_str());
- }
-}
-
-static void *parse_action(struct parse_state* state, int nargs, char **args)
-{
- std::string ret_err;
- std::vector<std::string> triggers(args + 1, args + nargs);
- Action* ret = ActionManager::GetInstance().AddNewAction(triggers, &ret_err);
-
- if (!ret) {
- parse_error(state, "%s\n", ret_err.c_str());
- }
-
- return ret;
-}
-
-bool add_command_to_action(Action* action, const std::vector<std::string>& args,
- const std::string& filename, int line, std::string* err)
-{
- int kw;
- size_t n;
-
- kw = lookup_keyword(args[0].c_str());
- if (!kw_is(kw, COMMAND)) {
- *err = android::base::StringPrintf("invalid command '%s'\n", args[0].c_str());
- return false;
- }
-
- n = kw_nargs(kw);
- if (args.size() < n) {
- *err = android::base::StringPrintf("%s requires %zu %s\n",
- args[0].c_str(), n - 1,
- n > 2 ? "arguments" : "argument");
- return false;
- }
-
- action->AddCommand(kw_func(kw), args, filename, line);
- return true;
-}
-
-static void parse_line_action(struct parse_state* state, int nargs, char **args)
-{
- if (nargs == 0) {
- return;
- }
-
- Action* action = static_cast<Action*>(state->context);
- std::vector<std::string> str_args(args, args + nargs);
- std::string ret_err;
- bool ret = add_command_to_action(action, str_args, state->filename,
- state->line, &ret_err);
- if (!ret) {
- parse_error(state, "%s\n", ret_err.c_str());
- }
+void Parser::DumpState() const {
+ ServiceManager::GetInstance().DumpState();
+ ActionManager::GetInstance().DumpState();
}
diff --git a/init/init_parser.h b/init/init_parser.h
index 709dca8..5ed30ad 100644
--- a/init/init_parser.h
+++ b/init/init_parser.h
@@ -17,16 +17,39 @@
#ifndef _INIT_INIT_PARSER_H_
#define _INIT_INIT_PARSER_H_
+#include <map>
#include <string>
#include <vector>
-#define INIT_PARSER_MAXARGS 64
+class SectionParser {
+public:
+ virtual ~SectionParser() {
+ }
+ virtual bool ParseSection(const std::vector<std::string>& args,
+ std::string* err) = 0;
+ virtual bool ParseLineSection(const std::vector<std::string>& args,
+ const std::string& filename, int line,
+ std::string* err) const = 0;
+ virtual void EndSection() = 0;
+ virtual void EndFile(const std::string& filename) = 0;
+};
-class Action;
+class Parser {
+public:
+ static Parser& GetInstance();
+ void DumpState() const;
+ bool ParseConfig(const std::string& path);
+ void AddSectionParser(const std::string& name,
+ std::unique_ptr<SectionParser> parser);
-bool init_parse_config(const char* path);
-int expand_props(const std::string& src, std::string* dst);
-bool add_command_to_action(Action* action, const std::vector<std::string>& args,
- const std::string& filename, int line, std::string* err);
+private:
+ Parser();
+
+ void ParseData(const std::string& filename, const std::string& data);
+ bool ParseConfigFile(const std::string& path);
+ bool ParseConfigDir(const std::string& path);
+
+ std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
+};
#endif
diff --git a/init/keyword_map.h b/init/keyword_map.h
new file mode 100644
index 0000000..dc2357b
--- /dev/null
+++ b/init/keyword_map.h
@@ -0,0 +1,77 @@
+/*
+ * 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 _INIT_KEYWORD_MAP_H_
+#define _INIT_KEYWORD_MAP_H_
+
+#include <map>
+#include <string>
+
+#include <base/stringprintf.h>
+
+template <typename Function>
+class KeywordMap {
+public:
+ using FunctionInfo = std::tuple<std::size_t, std::size_t, Function>;
+ using Map = const std::map<std::string, FunctionInfo>;
+
+ virtual ~KeywordMap() {
+ }
+
+ const Function FindFunction(const std::string& keyword,
+ size_t num_args,
+ std::string* err) const {
+ using android::base::StringPrintf;
+
+ auto function_info_it = map().find(keyword);
+ if (function_info_it == map().end()) {
+ *err = StringPrintf("invalid keyword '%s'", keyword.c_str());
+ return nullptr;
+ }
+
+ auto function_info = function_info_it->second;
+
+ auto min_args = std::get<0>(function_info);
+ auto max_args = std::get<1>(function_info);
+ if (min_args == max_args && num_args != min_args) {
+ *err = StringPrintf("%s requires %zu argument%s",
+ keyword.c_str(), min_args,
+ (min_args > 1 || min_args == 0) ? "s" : "");
+ return nullptr;
+ }
+
+ if (num_args < min_args || num_args > max_args) {
+ if (max_args == std::numeric_limits<decltype(max_args)>::max()) {
+ *err = StringPrintf("%s requires at least %zu argument%s",
+ keyword.c_str(), min_args,
+ min_args > 1 ? "s" : "");
+ } else {
+ *err = StringPrintf("%s requires between %zu and %zu arguments",
+ keyword.c_str(), min_args, max_args);
+ }
+ return nullptr;
+ }
+
+ return std::get<Function>(function_info);
+ }
+
+private:
+//Map of keyword ->
+//(minimum number of arguments, maximum number of arguments, function pointer)
+ virtual Map& map() const = 0;
+};
+
+#endif
diff --git a/init/keywords.h b/init/keywords.h
deleted file mode 100644
index 922feee..0000000
--- a/init/keywords.h
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef KEYWORD
-#include <string>
-#include <vector>
-int do_bootchart_init(const std::vector<std::string>& args);
-int do_class_start(const std::vector<std::string>& args);
-int do_class_stop(const std::vector<std::string>& args);
-int do_class_reset(const std::vector<std::string>& args);
-int do_domainname(const std::vector<std::string>& args);
-int do_enable(const std::vector<std::string>& args);
-int do_exec(const std::vector<std::string>& args);
-int do_export(const std::vector<std::string>& args);
-int do_hostname(const std::vector<std::string>& args);
-int do_ifup(const std::vector<std::string>& args);
-int do_insmod(const std::vector<std::string>& args);
-int do_installkey(const std::vector<std::string>& args);
-int do_mkdir(const std::vector<std::string>& args);
-int do_mount_all(const std::vector<std::string>& args);
-int do_mount(const std::vector<std::string>& args);
-int do_powerctl(const std::vector<std::string>& args);
-int do_restart(const std::vector<std::string>& args);
-int do_restorecon(const std::vector<std::string>& args);
-int do_restorecon_recursive(const std::vector<std::string>& args);
-int do_rm(const std::vector<std::string>& args);
-int do_rmdir(const std::vector<std::string>& args);
-int do_setprop(const std::vector<std::string>& args);
-int do_setrlimit(const std::vector<std::string>& args);
-int do_start(const std::vector<std::string>& args);
-int do_stop(const std::vector<std::string>& args);
-int do_swapon_all(const std::vector<std::string>& args);
-int do_trigger(const std::vector<std::string>& args);
-int do_symlink(const std::vector<std::string>& args);
-int do_sysclktz(const std::vector<std::string>& args);
-int do_write(const std::vector<std::string>& args);
-int do_copy(const std::vector<std::string>& args);
-int do_chown(const std::vector<std::string>& args);
-int do_chmod(const std::vector<std::string>& args);
-int do_loglevel(const std::vector<std::string>& args);
-int do_load_persist_props(const std::vector<std::string>& args);
-int do_load_all_props(const std::vector<std::string>& args);
-int do_verity_load_state(const std::vector<std::string>& args);
-int do_verity_update_state(const std::vector<std::string>& args);
-int do_wait(const std::vector<std::string>& args);
-#define __MAKE_KEYWORD_ENUM__
-#define KEYWORD(symbol, flags, nargs, func) K_##symbol,
-enum {
- K_UNKNOWN,
-#endif
- KEYWORD(bootchart_init, COMMAND, 0, do_bootchart_init)
- KEYWORD(chmod, COMMAND, 2, do_chmod)
- KEYWORD(chown, COMMAND, 2, do_chown)
- KEYWORD(class, OPTION, 0, 0)
- KEYWORD(class_reset, COMMAND, 1, do_class_reset)
- KEYWORD(class_start, COMMAND, 1, do_class_start)
- KEYWORD(class_stop, COMMAND, 1, do_class_stop)
- KEYWORD(console, OPTION, 0, 0)
- KEYWORD(copy, COMMAND, 2, do_copy)
- KEYWORD(critical, OPTION, 0, 0)
- KEYWORD(disabled, OPTION, 0, 0)
- KEYWORD(domainname, COMMAND, 1, do_domainname)
- KEYWORD(enable, COMMAND, 1, do_enable)
- KEYWORD(exec, COMMAND, 1, do_exec)
- KEYWORD(export, COMMAND, 2, do_export)
- KEYWORD(group, OPTION, 0, 0)
- KEYWORD(hostname, COMMAND, 1, do_hostname)
- KEYWORD(ifup, COMMAND, 1, do_ifup)
- KEYWORD(import, SECTION, 1, 0)
- KEYWORD(insmod, COMMAND, 1, do_insmod)
- KEYWORD(installkey, COMMAND, 1, do_installkey)
- KEYWORD(ioprio, OPTION, 0, 0)
- KEYWORD(keycodes, OPTION, 0, 0)
- KEYWORD(load_all_props, COMMAND, 0, do_load_all_props)
- KEYWORD(load_persist_props, COMMAND, 0, do_load_persist_props)
- KEYWORD(loglevel, COMMAND, 1, do_loglevel)
- KEYWORD(mkdir, COMMAND, 1, do_mkdir)
- KEYWORD(mount_all, COMMAND, 1, do_mount_all)
- KEYWORD(mount, COMMAND, 3, do_mount)
- KEYWORD(oneshot, OPTION, 0, 0)
- KEYWORD(onrestart, OPTION, 0, 0)
- KEYWORD(on, SECTION, 0, 0)
- KEYWORD(powerctl, COMMAND, 1, do_powerctl)
- KEYWORD(restart, COMMAND, 1, do_restart)
- KEYWORD(restorecon, COMMAND, 1, do_restorecon)
- KEYWORD(restorecon_recursive, COMMAND, 1, do_restorecon_recursive)
- KEYWORD(rm, COMMAND, 1, do_rm)
- KEYWORD(rmdir, COMMAND, 1, do_rmdir)
- KEYWORD(seclabel, OPTION, 0, 0)
- KEYWORD(service, SECTION, 0, 0)
- KEYWORD(setenv, OPTION, 2, 0)
- KEYWORD(setprop, COMMAND, 2, do_setprop)
- KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
- KEYWORD(socket, OPTION, 0, 0)
- KEYWORD(start, COMMAND, 1, do_start)
- KEYWORD(stop, COMMAND, 1, do_stop)
- KEYWORD(swapon_all, COMMAND, 1, do_swapon_all)
- KEYWORD(symlink, COMMAND, 1, do_symlink)
- KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
- KEYWORD(trigger, COMMAND, 1, do_trigger)
- KEYWORD(user, OPTION, 0, 0)
- KEYWORD(verity_load_state, COMMAND, 0, do_verity_load_state)
- KEYWORD(verity_update_state, COMMAND, 0, do_verity_update_state)
- KEYWORD(wait, COMMAND, 1, do_wait)
- KEYWORD(write, COMMAND, 2, do_write)
- KEYWORD(writepid, OPTION, 0, 0)
-#ifdef __MAKE_KEYWORD_ENUM__
- KEYWORD_COUNT,
-};
-#undef __MAKE_KEYWORD_ENUM__
-#undef KEYWORD
-#endif
diff --git a/init/readme.txt b/init/readme.txt
index d70c6f3..bf440c2 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -2,8 +2,8 @@
Android Init Language
---------------------
-The Android Init Language consists of four broad classes of statements,
-which are Actions, Commands, Services, and Options.
+The Android Init Language consists of five broad classes of statements,
+which are Actions, Commands, Services, Options, and Imports.
All of these are line-oriented, consisting of tokens separated by
whitespace. The c-style backslash escapes may be used to insert
@@ -17,9 +17,37 @@
or options belong to the section most recently declared. Commands
or options before the first section are ignored.
-Actions and Services have unique names. If a second Action or Service
-is declared with the same name as an existing one, it is ignored as
-an error. (??? should we override instead)
+Actions and Services have unique names. If a second Action is defined
+with the same name as an existing one, its commands are appended to
+the commands of the existing action. If a second Service is defined
+with the same name as an existing one, it is ignored and an error
+message is logged.
+
+
+Init .rc Files
+--------------
+The init language is used in plaintext files that take the .rc file
+extension. These are typically multiple of these in multiple
+locations on the system, described below.
+
+/init.rc is the primary .rc file and is loaded by the init executable
+at the beginning of its execution. It is responsible for the initial
+set up of the system. It imports /init.${ro.hardware}.rc which is the
+primary vendor supplied .rc file.
+
+During the mount_all command, the init executable loads all of the
+files contained within the /{system,vendor,odm}/etc/init/ directories.
+These directories are intended for all Actions and Services used after
+file system mounting.
+
+The intention of these directories is as follows
+ 1) /system/etc/init/ is for core system items such as
+ SurfaceFlinger and MediaService.
+ 2) /vendor/etc/init/ is for SoC vendor items such as actions or
+ daemons needed for core SoC functionality.
+ 3) /odm/etc/init/ is for device manufacturer items such as
+ actions or daemons needed for motion sensor or other peripheral
+ functionality.
Actions
@@ -37,7 +65,7 @@
Actions take the form of:
-on <trigger>
+on <trigger> [&& <trigger>]*
<command>
<command>
<command>
@@ -117,25 +145,36 @@
Triggers
--------
-Triggers are strings which can be used to match certain kinds
-of events and used to cause an action to occur.
+Triggers are strings which can be used to match certain kinds of
+events and used to cause an action to occur.
-boot
- This is the first trigger that will occur when init starts
- (after /init.conf is loaded)
+Triggers are subdivided into event triggers and property triggers.
-<name>=<value>
- Triggers of this form occur when the property <name> is set
- to the specific value <value>.
+Event triggers are strings triggered by the 'trigger' command or by
+the QueueEventTrigger() function within the init executable. These
+take the form of a simple string such as 'boot' or 'late-init'.
- One can also test multiple properties to execute a group
- of commands. For example:
+Property triggers are strings triggered when a named property changes
+value to a given new value or when a named property changes value to
+any new value. These take the form of 'property:<name>=<value>' and
+'property:<name>=*' respectively. Property triggers are additionally
+evaluated and triggered accordingly during the initial boot phase of
+init.
- on property:test.a=1 && property:test.b=1
- setprop test.c 1
+An Action can have multiple property triggers but may only have one
+event trigger.
- The above stub sets test.c to 1 only when
- both test.a=1 and test.b=1
+For example:
+'on boot && property:a=b' defines an action that is only executed when
+the 'boot' event trigger happens and the property a equals b.
+
+'on property:a=b && property:c=d' defines an action that is executed
+at three times,
+ 1) During initial boot if property a=b and property c=d
+ 2) Any time that property a transitions to value b, while property
+ c already equals d.
+ 3) Any time that property c transitions to value d, while property
+ a already equals b.
Commands
@@ -197,12 +236,6 @@
ifup <interface>
Bring the network interface <interface> online.
-import <path>
- Parse an init config file, extending the current configuration.
- If <path> is a directory, each file in the directory is parsed as
- a config file. It is not recursive, nested directories will
- not be parsed.
-
insmod <path>
Install the module at <path>
@@ -304,19 +337,30 @@
it will be truncated. Properties are expanded within <content>.
+Imports
+-------
+The import keyword is not a command, but rather its own section and is
+handled immediately after the .rc file that contains it has finished
+being parsed. It takes the below form:
+
+import <path>
+ Parse an init config file, extending the current configuration.
+ If <path> is a directory, each file in the directory is parsed as
+ a config file. It is not recursive, nested directories will
+ not be parsed.
+
+There are only two times where the init executable imports .rc files,
+ 1) When it imports /init.rc during initial boot
+ 2) When it imports /{system,vendor,odm}/etc/init/ during mount_all
+
+
Properties
----------
-Init updates some system properties to provide some insight into
-what it's doing:
-
-init.action
- Equal to the name of the action currently being executed or "" if none
-
-init.command
- Equal to the command being executed or "" if none.
+Init provides information about the services that it is responsible
+for via the below properties.
init.svc.<name>
- State of a named service ("stopped", "running", "restarting")
+ State of a named service ("stopped", "stopping", "running", "restarting")
Bootcharting
diff --git a/init/service.cpp b/init/service.cpp
index a370d25..a3c5ca4 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -32,11 +32,13 @@
#include "action.h"
#include "init.h"
#include "init_parser.h"
-#include "keywords.h"
#include "log.h"
#include "property_service.h"
#include "util.h"
+using android::base::StringPrintf;
+using android::base::WriteStringToFile;
+
#define CRITICAL_CRASH_THRESHOLD 4 // if we crash >4 times ...
#define CRITICAL_CRASH_WINDOW (4*60) // ... in 4 minutes, goto recovery
@@ -84,7 +86,7 @@
return;
}
- std::string prop_name = android::base::StringPrintf("init.svc.%s", name_.c_str());
+ std::string prop_name = StringPrintf("init.svc.%s", name_.c_str());
if (prop_name.length() >= PROP_NAME_MAX) {
// If the property name would be too long, we can't set it.
ERROR("Property name \"init.svc.%s\" too long; not setting to %s\n",
@@ -104,8 +106,7 @@
// Remove any sockets we may have created.
for (const auto& si : sockets_) {
- std::string tmp = android::base::StringPrintf(ANDROID_SOCKET_DIR "/%s",
- si.name.c_str());
+ std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str());
unlink(tmp.c_str());
}
@@ -168,148 +169,156 @@
}
}
-bool Service::HandleLine(int kw, const std::vector<std::string>& args, std::string* err) {
- std::vector<std::string> str_args;
+bool Service::HandleClass(const std::vector<std::string>& args, std::string* err) {
+ classname_ = args[1];
+ return true;
+}
- ioprio_class_ = IoSchedClass_NONE;
+bool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) {
+ flags_ |= SVC_CONSOLE;
+ return true;
+}
- switch (kw) {
- case K_class:
- if (args.size() != 2) {
- *err = "class option requires a classname\n";
- return false;
- } else {
- classname_ = args[1];
- }
- break;
- case K_console:
- flags_ |= SVC_CONSOLE;
- break;
- case K_disabled:
- flags_ |= SVC_DISABLED;
- flags_ |= SVC_RC_DISABLED;
- break;
- case K_ioprio:
- if (args.size() != 3) {
- *err = "ioprio optin usage: ioprio <rt|be|idle> <ioprio 0-7>\n";
- return false;
- } else {
- ioprio_pri_ = std::stoul(args[2], 0, 8);
+bool Service::HandleCritical(const std::vector<std::string>& args, std::string* err) {
+ flags_ |= SVC_CRITICAL;
+ return true;
+}
- if (ioprio_pri_ < 0 || ioprio_pri_ > 7) {
- *err = "priority value must be range 0 - 7\n";
- return false;
- }
+bool Service::HandleDisabled(const std::vector<std::string>& args, std::string* err) {
+ flags_ |= SVC_DISABLED;
+ flags_ |= SVC_RC_DISABLED;
+ return true;
+}
- if (args[1] == "rt") {
- ioprio_class_ = IoSchedClass_RT;
- } else if (args[1] == "be") {
- ioprio_class_ = IoSchedClass_BE;
- } else if (args[1] == "idle") {
- ioprio_class_ = IoSchedClass_IDLE;
- } else {
- *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>\n";
- return false;
- }
- }
- break;
- case K_group:
- if (args.size() < 2) {
- *err = "group option requires a group id\n";
- return false;
- } else if (args.size() > NR_SVC_SUPP_GIDS + 2) {
- *err = android::base::StringPrintf("group option accepts at most %d supp. groups\n",
- NR_SVC_SUPP_GIDS);
- return false;
- } else {
- gid_ = decode_uid(args[1].c_str());
- for (std::size_t n = 2; n < args.size(); n++) {
- supp_gids_.push_back(decode_uid(args[n].c_str()));
- }
- }
- break;
- case K_keycodes:
- if (args.size() < 2) {
- *err = "keycodes option requires atleast one keycode\n";
- return false;
- } else {
- for (std::size_t i = 1; i < args.size(); i++) {
- keycodes_.push_back(std::stoi(args[i]));
- }
- }
- break;
- case K_oneshot:
- flags_ |= SVC_ONESHOT;
- break;
- case K_onrestart:
- if (args.size() < 2) {
- return false;
- }
- str_args.assign(args.begin() + 1, args.end());
- add_command_to_action(&onrestart_, str_args, "", 0, err);
- break;
- case K_critical:
- flags_ |= SVC_CRITICAL;
- break;
- case K_setenv: { /* name value */
- if (args.size() < 3) {
- *err = "setenv option requires name and value arguments\n";
- return false;
- }
-
- envvars_.push_back({args[1], args[2]});
- break;
- }
- case K_socket: {/* name type perm [ uid gid context ] */
- if (args.size() < 4) {
- *err = "socket option requires name, type, perm arguments\n";
- return false;
- }
- if (args[2] != "dgram" && args[2] != "stream" &&
- args[2] != "seqpacket") {
- *err = "socket type must be 'dgram', 'stream' or 'seqpacket'\n";
- return false;
- }
-
- int perm = std::stoul(args[3], 0, 8);
- uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
- gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
- std::string socketcon = args.size() > 6 ? args[6] : "";
-
- sockets_.push_back({args[1], args[2], uid, gid, perm, socketcon});
- break;
- }
- case K_user:
- if (args.size() != 2) {
- *err = "user option requires a user id\n";
- return false;
- } else {
- uid_ = decode_uid(args[1].c_str());
- }
- break;
- case K_seclabel:
- if (args.size() != 2) {
- *err = "seclabel option requires a label string\n";
- return false;
- } else {
- seclabel_ = args[1];
- }
- break;
- case K_writepid:
- if (args.size() < 2) {
- *err = "writepid option requires at least one filename\n";
- return false;
- }
- writepid_files_.assign(args.begin() + 1, args.end());
- break;
-
- default:
- *err = android::base::StringPrintf("invalid option '%s'\n", args[0].c_str());
- return false;
+bool Service::HandleGroup(const std::vector<std::string>& args, std::string* err) {
+ gid_ = decode_uid(args[1].c_str());
+ for (std::size_t n = 2; n < args.size(); n++) {
+ supp_gids_.emplace_back(decode_uid(args[n].c_str()));
}
return true;
}
+bool Service::HandleIoprio(const std::vector<std::string>& args, std::string* err) {
+ ioprio_pri_ = std::stoul(args[2], 0, 8);
+
+ if (ioprio_pri_ < 0 || ioprio_pri_ > 7) {
+ *err = "priority value must be range 0 - 7";
+ return false;
+ }
+
+ if (args[1] == "rt") {
+ ioprio_class_ = IoSchedClass_RT;
+ } else if (args[1] == "be") {
+ ioprio_class_ = IoSchedClass_BE;
+ } else if (args[1] == "idle") {
+ ioprio_class_ = IoSchedClass_IDLE;
+ } else {
+ *err = "ioprio option usage: ioprio <rt|be|idle> <0-7>";
+ return false;
+ }
+
+ return true;
+}
+
+bool Service::HandleKeycodes(const std::vector<std::string>& args, std::string* err) {
+ for (std::size_t i = 1; i < args.size(); i++) {
+ keycodes_.emplace_back(std::stoi(args[i]));
+ }
+ return true;
+}
+
+bool Service::HandleOneshot(const std::vector<std::string>& args, std::string* err) {
+ flags_ |= SVC_ONESHOT;
+ return true;
+}
+
+bool Service::HandleOnrestart(const std::vector<std::string>& args, std::string* err) {
+ std::vector<std::string> str_args(args.begin() + 1, args.end());
+ onrestart_.AddCommand(str_args, "", 0, err);
+ return true;
+}
+
+bool Service::HandleSeclabel(const std::vector<std::string>& args, std::string* err) {
+ seclabel_ = args[1];
+ return true;
+}
+
+bool Service::HandleSetenv(const std::vector<std::string>& args, std::string* err) {
+ envvars_.emplace_back(args[1], args[2]);
+ return true;
+}
+
+/* name type perm [ uid gid context ] */
+bool Service::HandleSocket(const std::vector<std::string>& args, std::string* err) {
+ if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") {
+ *err = "socket type must be 'dgram', 'stream' or 'seqpacket'";
+ return false;
+ }
+
+ int perm = std::stoul(args[3], 0, 8);
+ uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0;
+ gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0;
+ std::string socketcon = args.size() > 6 ? args[6] : "";
+
+ sockets_.emplace_back(args[1], args[2], uid, gid, perm, socketcon);
+ return true;
+}
+
+bool Service::HandleUser(const std::vector<std::string>& args, std::string* err) {
+ uid_ = decode_uid(args[1].c_str());
+ return true;
+}
+
+bool Service::HandleWritepid(const std::vector<std::string>& args, std::string* err) {
+ writepid_files_.assign(args.begin() + 1, args.end());
+ return true;
+}
+
+class Service::OptionHandlerMap : public KeywordMap<OptionHandler> {
+public:
+ OptionHandlerMap() {
+ }
+private:
+ Map& map() const override;
+};
+
+Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
+ constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
+ static const Map option_handlers = {
+ {"class", {1, 1, &Service::HandleClass}},
+ {"console", {0, 0, &Service::HandleConsole}},
+ {"critical", {0, 0, &Service::HandleCritical}},
+ {"disabled", {0, 0, &Service::HandleDisabled}},
+ {"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
+ {"ioprio", {2, 2, &Service::HandleIoprio}},
+ {"keycodes", {1, kMax, &Service::HandleKeycodes}},
+ {"oneshot", {0, 0, &Service::HandleOneshot}},
+ {"onrestart", {1, kMax, &Service::HandleOnrestart}},
+ {"seclabel", {1, 1, &Service::HandleSeclabel}},
+ {"setenv", {2, 2, &Service::HandleSetenv}},
+ {"socket", {3, 6, &Service::HandleSocket}},
+ {"user", {1, 1, &Service::HandleUser}},
+ {"writepid", {1, kMax, &Service::HandleWritepid}},
+ };
+ return option_handlers;
+}
+
+bool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {
+ if (args.empty()) {
+ *err = "option needed, but not provided";
+ return false;
+ }
+
+ static const OptionHandlerMap handler_map;
+ auto handler = handler_map.FindFunction(args[0], args.size() - 1, err);
+
+ if (!handler) {
+ return false;
+ }
+
+ return (this->*handler)(args, err);
+}
+
bool Service::Start(const std::vector<std::string>& dynamic_args) {
// Starting a service removes it from the disabled or reset state and
// immediately takes it out of the restarting state if it was in there.
@@ -396,7 +405,7 @@
umask(077);
if (properties_initialized()) {
get_property_workspace(&fd, &sz);
- std::string tmp = android::base::StringPrintf("%d,%d", dup(fd), sz);
+ std::string tmp = StringPrintf("%d,%d", dup(fd), sz);
add_environment("ANDROID_PROPERTY_WORKSPACE", tmp.c_str());
}
@@ -418,9 +427,9 @@
}
}
- std::string pid_str = android::base::StringPrintf("%d", pid);
+ std::string pid_str = StringPrintf("%d", pid);
for (const auto& file : writepid_files_) {
- if (!android::base::WriteStringToFile(pid_str, file)) {
+ if (!WriteStringToFile(pid_str, file)) {
ERROR("couldn't write %s to %s: %s\n",
pid_str.c_str(), file.c_str(), strerror(errno));
}
@@ -609,9 +618,8 @@
}
void Service::PublishSocket(const std::string& name, int fd) const {
- std::string key = android::base::StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s",
- name.c_str());
- std::string val = android::base::StringPrintf("%d", fd);
+ std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
+ std::string val = StringPrintf("%d", fd);
add_environment(key.c_str(), val.c_str());
/* make sure we don't close-on-exec */
@@ -628,31 +636,14 @@
return instance;
}
-Service* ServiceManager::AddNewService(const std::string& name,
- const std::string& classname,
- const std::vector<std::string>& args,
- std::string* err) {
- if (!IsValidName(name)) {
- *err = android::base::StringPrintf("invalid service name '%s'\n", name.c_str());
- return nullptr;
+void ServiceManager::AddService(std::unique_ptr<Service> service) {
+ Service* old_service = FindServiceByName(service->name());
+ if (old_service) {
+ ERROR("ignored duplicate definition of service '%s'",
+ service->name().c_str());
+ return;
}
-
- Service* svc = ServiceManager::GetInstance().FindServiceByName(name);
- if (svc) {
- *err = android::base::StringPrintf("ignored duplicate definition of service '%s'\n",
- name.c_str());
- return nullptr;
- }
-
- std::unique_ptr<Service> svc_p(new Service(name, classname, args));
- if (!svc_p) {
- ERROR("Couldn't allocate service for service '%s'", name.c_str());
- return nullptr;
- }
- svc = svc_p.get();
- services_.push_back(std::move(svc_p));
-
- return svc;
+ services_.emplace_back(std::move(service));
}
Service* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) {
@@ -677,8 +668,7 @@
std::vector<std::string> str_args(args.begin() + command_arg, args.end());
exec_count_++;
- std::string name = android::base::StringPrintf("exec %d (%s)", exec_count_,
- str_args[0].c_str());
+ std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
unsigned flags = SVC_EXEC | SVC_ONESHOT;
std::string seclabel = "";
@@ -770,8 +760,7 @@
}
}
-void ServiceManager::RemoveService(const Service& svc)
-{
+void ServiceManager::RemoveService(const Service& svc) {
auto svc_it = std::find_if(services_.begin(), services_.end(),
[&svc] (const std::unique_ptr<Service>& s) {
return svc.name() == s->name();
@@ -783,8 +772,44 @@
services_.erase(svc_it);
}
-bool ServiceManager::IsValidName(const std::string& name) const
-{
+void ServiceManager::DumpState() const {
+ for (const auto& s : services_) {
+ s->DumpState();
+ }
+ INFO("\n");
+}
+
+bool ServiceParser::ParseSection(const std::vector<std::string>& args,
+ std::string* err) {
+ if (args.size() < 3) {
+ *err = "services must have a name and a program";
+ return false;
+ }
+
+ const std::string& name = args[1];
+ if (!IsValidName(name)) {
+ *err = StringPrintf("invalid service name '%s'", name.c_str());
+ return false;
+ }
+
+ std::vector<std::string> str_args(args.begin() + 2, args.end());
+ service_ = std::make_unique<Service>(name, "default", str_args);
+ return true;
+}
+
+bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
+ const std::string& filename, int line,
+ std::string* err) const {
+ return service_ ? service_->HandleLine(args, err) : false;
+}
+
+void ServiceParser::EndSection() {
+ if (service_) {
+ ServiceManager::GetInstance().AddService(std::move(service_));
+ }
+}
+
+bool ServiceParser::IsValidName(const std::string& name) const {
if (name.size() > 16) {
return false;
}
@@ -795,11 +820,3 @@
}
return true;
}
-
-void ServiceManager::DumpState() const
-{
- for (const auto& s : services_) {
- s->DumpState();
- }
- INFO("\n");
-}
diff --git a/init/service.h b/init/service.h
index 1ecf78a..10eb736 100644
--- a/init/service.h
+++ b/init/service.h
@@ -26,6 +26,8 @@
#include <vector>
#include "action.h"
+#include "init_parser.h"
+#include "keyword_map.h"
#define SVC_DISABLED 0x001 // do not autostart with class
#define SVC_ONESHOT 0x002 // do not restart on exit
@@ -73,7 +75,7 @@
unsigned flags, uid_t uid, gid_t gid, const std::vector<gid_t>& supp_gids,
const std::string& seclabel, const std::vector<std::string>& args);
- bool HandleLine(int kw, const std::vector<std::string>& args, std::string* err);
+ bool HandleLine(const std::vector<std::string>& args, std::string* err);
bool Start(const std::vector<std::string>& dynamic_args);
bool Start();
bool StartIfNotDisabled();
@@ -99,12 +101,31 @@
const std::vector<std::string>& args() const { return args_; }
private:
+ using OptionHandler = bool (Service::*) (const std::vector<std::string>& args,
+ std::string* err);
+ class OptionHandlerMap;
+
void NotifyStateChange(const std::string& new_state) const;
void StopOrReset(int how);
void ZapStdio() const;
void OpenConsole() const;
void PublishSocket(const std::string& name, int fd) const;
+ bool HandleClass(const std::vector<std::string>& args, std::string* err);
+ bool HandleConsole(const std::vector<std::string>& args, std::string* err);
+ bool HandleCritical(const std::vector<std::string>& args, std::string* err);
+ bool HandleDisabled(const std::vector<std::string>& args, std::string* err);
+ bool HandleGroup(const std::vector<std::string>& args, std::string* err);
+ bool HandleIoprio(const std::vector<std::string>& args, std::string* err);
+ bool HandleKeycodes(const std::vector<std::string>& args, std::string* err);
+ bool HandleOneshot(const std::vector<std::string>& args, std::string* err);
+ bool HandleOnrestart(const std::vector<std::string>& args, std::string* err);
+ bool HandleSeclabel(const std::vector<std::string>& args, std::string* err);
+ bool HandleSetenv(const std::vector<std::string>& args, std::string* err);
+ bool HandleSocket(const std::vector<std::string>& args, std::string* err);
+ bool HandleUser(const std::vector<std::string>& args, std::string* err);
+ bool HandleWritepid(const std::vector<std::string>& args, std::string* err);
+
std::string name_;
std::string classname_;
@@ -141,9 +162,7 @@
public:
static ServiceManager& GetInstance();
- Service* AddNewService(const std::string& name, const std::string& classname,
- const std::vector<std::string>& args,
- std::string* err);
+ void AddService(std::unique_ptr<Service> service);
Service* MakeExecOneshotService(const std::vector<std::string>& args);
Service* FindServiceByName(const std::string& name) const;
Service* FindServiceByPid(pid_t pid) const;
@@ -155,13 +174,30 @@
void (*func)(Service* svc)) const;
void RemoveService(const Service& svc);
void DumpState() const;
+
private:
ServiceManager();
- bool IsValidName(const std::string& name) const;
-
static int exec_count_; // Every service needs a unique name.
std::vector<std::unique_ptr<Service>> services_;
};
+class ServiceParser : public SectionParser {
+public:
+ ServiceParser() : service_(nullptr) {
+ }
+ bool ParseSection(const std::vector<std::string>& args,
+ std::string* err) override;
+ bool ParseLineSection(const std::vector<std::string>& args,
+ const std::string& filename, int line,
+ std::string* err) const override;
+ void EndSection() override;
+ void EndFile(const std::string&) override {
+ }
+private:
+ bool IsValidName(const std::string& name) const;
+
+ std::unique_ptr<Service> service_;
+};
+
#endif
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index 497c606..09f4638 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -233,7 +233,6 @@
data.push_back('\n'); // TODO: fix parse_config.
parse_config(fn, data);
- dump_parser_state();
return 0;
}
diff --git a/init/util.cpp b/init/util.cpp
index f6131e3..1eb90e0 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -43,6 +43,7 @@
#include "init.h"
#include "log.h"
+#include "property_service.h"
#include "util.h"
/*
@@ -476,3 +477,73 @@
}
return S_ISDIR(info.st_mode);
}
+
+bool expand_props(const std::string& src, std::string* dst) {
+ const char* src_ptr = src.c_str();
+
+ if (!dst) {
+ return false;
+ }
+
+ /* - variables can either be $x.y or ${x.y}, in case they are only part
+ * of the string.
+ * - will accept $$ as a literal $.
+ * - no nested property expansion, i.e. ${foo.${bar}} is not supported,
+ * bad things will happen
+ */
+ while (*src_ptr) {
+ const char* c;
+
+ c = strchr(src_ptr, '$');
+ if (!c) {
+ dst->append(src_ptr);
+ return true;
+ }
+
+ dst->append(src_ptr, c);
+ c++;
+
+ if (*c == '$') {
+ dst->push_back(*(c++));
+ src_ptr = c;
+ continue;
+ } else if (*c == '\0') {
+ return true;
+ }
+
+ std::string prop_name;
+ if (*c == '{') {
+ c++;
+ const char* end = strchr(c, '}');
+ if (!end) {
+ // failed to find closing brace, abort.
+ ERROR("unexpected end of string in '%s', looking for }\n", src.c_str());
+ return false;
+ }
+ prop_name = std::string(c, end);
+ c = end + 1;
+ } else {
+ prop_name = c;
+ ERROR("using deprecated syntax for specifying property '%s', use ${name} instead\n",
+ c);
+ c += prop_name.size();
+ }
+
+ if (prop_name.empty()) {
+ ERROR("invalid zero-length prop name in '%s'\n", src.c_str());
+ return false;
+ }
+
+ std::string prop_val = property_get(prop_name.c_str());
+ if (prop_val.empty()) {
+ ERROR("property '%s' doesn't exist while expanding '%s'\n",
+ prop_name.c_str(), src.c_str());
+ return false;
+ }
+
+ dst->append(prop_val);
+ src_ptr = c;
+ }
+
+ return true;
+}
diff --git a/init/util.h b/init/util.h
index f08cb8d..a33209e 100644
--- a/init/util.h
+++ b/init/util.h
@@ -65,4 +65,5 @@
int restorecon_recursive(const char *pathname);
std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
bool is_dir(const char* pathname);
+bool expand_props(const std::string& src, std::string* dst);
#endif
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index f9060c4..015bd3f 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -37,19 +37,7 @@
# some files must not be compiled when building against Mingw
# they correspond to features not used by our host development tools
# which are also hard or even impossible to port to native Win32
-WINDOWS_HOST_ONLY :=
-ifeq ($(HOST_OS),windows)
- ifeq ($(strip $(USE_CYGWIN)),)
- WINDOWS_HOST_ONLY := 1
- endif
-endif
-# USE_MINGW is defined when we build against Mingw on Linux
-ifneq ($(strip $(USE_MINGW)),)
- WINDOWS_HOST_ONLY := 1
-endif
-
-ifneq ($(WINDOWS_HOST_ONLY),1)
- commonSources += \
+nonWindowsSources := \
fs.c \
multiuser.c \
socket_inaddr_any_server.c \
@@ -60,31 +48,32 @@
socket_network_client.c \
sockets.c \
- commonHostSources += \
+nonWindowsHostSources := \
ashmem-host.c \
trace-host.c
-endif
-
# Shared and static library for host
# ========================================================
LOCAL_MODULE := libcutils
-LOCAL_SRC_FILES := $(commonSources) $(commonHostSources) dlmalloc_stubs.c
+LOCAL_SRC_FILES := $(commonSources) dlmalloc_stubs.c
+LOCAL_SRC_FILES_darwin := $(nonWindowsSources) $(nonWindowsHostSources)
+LOCAL_SRC_FILES_linux := $(nonWindowsSources) $(nonWindowsHostSources)
LOCAL_STATIC_LIBRARIES := liblog
-ifneq ($(HOST_OS),windows)
-LOCAL_CFLAGS += -Werror -Wall -Wextra
-endif
+LOCAL_CFLAGS_darwin := -Werror -Wall -Wextra
+LOCAL_CFLAGS_linux := -Werror -Wall -Wextra
LOCAL_MULTILIB := both
+LOCAL_MODULE_HOST_OS := darwin linux windows
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcutils
-LOCAL_SRC_FILES := $(commonSources) $(commonHostSources) dlmalloc_stubs.c
+LOCAL_SRC_FILES := $(commonSources) dlmalloc_stubs.c
+LOCAL_SRC_FILES_darwin := $(nonWindowsSources) $(nonWindowsHostSources)
+LOCAL_SRC_FILES_linux := $(nonWindowsSources) $(nonWindowsHostSources)
LOCAL_SHARED_LIBRARIES := liblog
-ifneq ($(HOST_OS),windows)
-LOCAL_CFLAGS += -Werror -Wall -Wextra
-endif
+LOCAL_CFLAGS_darwin := -Werror -Wall -Wextra
+LOCAL_CFLAGS_linux := -Werror -Wall -Wextra
LOCAL_MULTILIB := both
include $(BUILD_HOST_SHARED_LIBRARY)
@@ -96,6 +85,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libcutils
LOCAL_SRC_FILES := $(commonSources) \
+ $(nonWindowsSources) \
android_reboot.c \
ashmem-dev.c \
debugger.c \
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 5f6f8f9..27981ff 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -135,8 +135,8 @@
{ 04770, AID_ROOT, AID_RADIO, 0, "system/bin/pppd-ril" },
/* the following files have enhanced capabilities and ARE included in user builds. */
- { 00750, AID_ROOT, AID_SHELL, (1ULL << CAP_SETUID) | (1ULL << CAP_SETGID), "system/bin/run-as" },
- { 00700, AID_SYSTEM, AID_SHELL, (1ULL << CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },
+ { 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) | CAP_MASK_LONG(CAP_SETGID), "system/bin/run-as" },
+ { 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/uncrypt" },
{ 00750, AID_ROOT, AID_ROOT, 0, "system/bin/install-recovery.sh" },
diff --git a/liblog/Android.mk b/liblog/Android.mk
index 5eed634..3a1a9db 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -24,41 +24,30 @@
# so make sure we do not regret hard-coding it as follows:
liblog_cflags := -DLIBLOG_LOG_TAG=1005
-liblog_sources := logd_write.c log_event_write.c
-
-# some files must not be compiled when building against Mingw
-# they correspond to features not used by our host development tools
-# which are also hard or even impossible to port to native Win32
-
-ifeq ($(strip $(USE_MINGW)),)
- liblog_sources += \
- event_tag_map.c
-else
- liblog_sources += \
- uio.c
-endif
-
-liblog_host_sources := $(liblog_sources) fake_log_device.c event.logtags
-liblog_target_sources := $(liblog_sources) log_time.cpp log_is_loggable.c
-ifeq ($(strip $(USE_MINGW)),)
+liblog_host_sources := logd_write.c log_event_write.c fake_log_device.c event.logtags
+liblog_target_sources := logd_write.c log_event_write.c event_tag_map.c log_time.cpp log_is_loggable.c
liblog_target_sources += logprint.c
-endif
liblog_target_sources += log_read.c
# Shared and static library for host
# ========================================================
LOCAL_MODULE := liblog
LOCAL_SRC_FILES := $(liblog_host_sources)
+# some files must not be compiled when building against Mingw
+# they correspond to features not used by our host development tools
+# which are also hard or even impossible to port to native Win32
+LOCAL_SRC_FILES_darwin := event_tag_map.c
+LOCAL_SRC_FILES_linux := event_tag_map.c
+LOCAL_SRC_FILES_windows := uio.c
LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror $(liblog_cflags)
LOCAL_MULTILIB := both
+LOCAL_MODULE_HOST_OS := darwin linux windows
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := liblog
LOCAL_WHOLE_STATIC_LIBRARIES := liblog
-ifeq ($(strip $(HOST_OS)),linux)
-LOCAL_LDLIBS := -lrt
-endif
+LOCAL_LDLIBS_linux := -lrt
LOCAL_MULTILIB := both
LOCAL_CXX_STL := none
include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/libsparse/Android.mk b/libsparse/Android.mk
index 925b98b..c77eba9 100644
--- a/libsparse/Android.mk
+++ b/libsparse/Android.mk
@@ -18,6 +18,7 @@
LOCAL_STATIC_LIBRARIES := libz
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Werror
+LOCAL_MODULE_HOST_OS := darwin linux windows
include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libutils/Android.mk b/libutils/Android.mk
index 8226db2..1039096 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -43,27 +43,19 @@
host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -Werror
-ifeq ($(HOST_OS),windows)
-ifeq ($(strip $(USE_CYGWIN),),)
-# Under MinGW, ctype.h doesn't need multi-byte support
-host_commonCflags += -DMB_CUR_MAX=1
-endif
-endif
-
# For the host
# =====================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= $(commonSources)
-ifeq ($(HOST_OS), linux)
-LOCAL_SRC_FILES += Looper.cpp
-endif
-ifeq ($(HOST_OS),darwin)
-LOCAL_CFLAGS += -Wno-unused-parameter
-endif
+LOCAL_SRC_FILES_linux := Looper.cpp
+LOCAL_CFLAGS_darwin := -Wno-unused-parameter
LOCAL_MODULE:= libutils
LOCAL_STATIC_LIBRARIES := liblog
LOCAL_CFLAGS += $(host_commonCflags)
+# Under MinGW, ctype.h doesn't need multi-byte support
+LOCAL_CFLAGS_windows := -DMB_CUR_MAX=1
LOCAL_MULTILIB := both
+LOCAL_MODULE_HOST_OS := darwin linux windows
include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk
index 559c48b..608ff1c 100644
--- a/libziparchive/Android.mk
+++ b/libziparchive/Android.mk
@@ -33,10 +33,9 @@
LOCAL_STATIC_LIBRARIES := libz libutils libbase
LOCAL_MODULE:= libziparchive-host
LOCAL_CFLAGS := -Werror
-ifneq ($(strip $(USE_MINGW)),)
- LOCAL_CFLAGS += -mno-ms-bitfields
-endif
+LOCAL_CFLAGS_windows := -mno-ms-bitfields
LOCAL_MULTILIB := both
+LOCAL_MODULE_HOST_OS := darwin linux windows
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index c609870..a93369e 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -413,6 +413,12 @@
it = f->second;
}
}
+ static const timespec too_old = {
+ EXPIRE_HOUR_THRESHOLD * 60 * 60, 0
+ };
+ LogBufferElementCollection::iterator lastt;
+ lastt = mLogElements.end();
+ --lastt;
LogBufferElementLast last;
while (it != mLogElements.end()) {
LogBufferElement *e = *it;
@@ -464,6 +470,11 @@
continue;
}
+ if ((e->getRealTime() < ((*lastt)->getRealTime() - too_old))
+ || (e->getRealTime() > (*lastt)->getRealTime())) {
+ break;
+ }
+
// unmerged drop message
if (dropped) {
last.add(e);
@@ -477,18 +488,6 @@
}
if (e->getUid() != worst) {
- if (leading) {
- static const timespec too_old = {
- EXPIRE_HOUR_THRESHOLD * 60 * 60, 0
- };
- LogBufferElementCollection::iterator last;
- last = mLogElements.end();
- --last;
- if ((e->getRealTime() < ((*last)->getRealTime() - too_old))
- || (e->getRealTime() > (*last)->getRealTime())) {
- break;
- }
- }
leading = false;
last.clear(e);
++it;
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index 89fa222..12dfa18 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -41,6 +41,28 @@
serialization/metric_sample.cc \
serialization/serialization_utils.cc
+metrics_tests_sources := \
+ metrics_daemon.cc \
+ metrics_daemon_test.cc \
+ metrics_library_test.cc \
+ persistent_integer.cc \
+ persistent_integer_test.cc \
+ serialization/metric_sample.cc \
+ serialization/serialization_utils.cc \
+ serialization/serialization_utils_unittest.cc \
+ timer.cc \
+ timer_test.cc \
+ uploader/metrics_hashes.cc \
+ uploader/metrics_hashes_unittest.cc \
+ uploader/metrics_log_base.cc \
+ uploader/metrics_log_base_unittest.cc \
+ uploader/metrics_log.cc \
+ uploader/mock/sender_mock.cc \
+ uploader/sender_http.cc \
+ uploader/system_profile_cache.cc \
+ uploader/upload_service.cc \
+ uploader/upload_service_test.cc \
+
metrics_CFLAGS := -Wall \
-Wno-char-subscripts \
-Wno-missing-field-initializers \
@@ -125,4 +147,25 @@
include $(BUILD_PREBUILT)
endif # INITRC_TEMPLATE
+# Unit tests for metrics.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := metrics_tests
+LOCAL_CFLAGS := $(metrics_CFLAGS)
+LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
+LOCAL_CPPFLAGS := $(metrics_CPPFLAGS) -Wno-sign-compare
+LOCAL_RTTI_FLAG := -frtti
+LOCAL_SHARED_LIBRARIES := $(metrics_shared_libraries) \
+ libmetrics \
+ libprotobuf-cpp-lite \
+ libchromeos-http \
+ libchromeos-dbus \
+ libcutils \
+ libdbus \
+
+LOCAL_SRC_FILES := $(metrics_tests_sources)
+LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metrics_daemon_protos
+
+include $(BUILD_NATIVE_TEST)
+
endif # HOST_OS == linux
diff --git a/metricsd/include/metrics/metrics_library.h b/metricsd/include/metrics/metrics_library.h
index 4917a7c..a956b69 100644
--- a/metricsd/include/metrics/metrics_library.h
+++ b/metricsd/include/metrics/metrics_library.h
@@ -129,6 +129,9 @@
FRIEND_TEST(MetricsLibraryTest, SendMessageToChrome);
FRIEND_TEST(MetricsLibraryTest, SendMessageToChromeUMAEventsBadFileLocation);
+ void InitForTest(const std::string& uma_events_file,
+ const std::string& consent_file);
+
// Sets |*result| to whether or not the |mounts_file| indicates that
// the |device_name| is currently mounted. Uses |buffer| of
// |buffer_size| to read the file. Returns false if any error.
diff --git a/metricsd/metrics_daemon.cc b/metricsd/metrics_daemon.cc
index 5855cee..2838119 100644
--- a/metricsd/metrics_daemon.cc
+++ b/metricsd/metrics_daemon.cc
@@ -51,8 +51,6 @@
namespace {
-#define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error")
-
const char kCrashReporterInterface[] = "org.chromium.CrashReporter";
const char kCrashReporterUserCrashSignal[] = "UserCrash";
const char kCrashReporterMatchRule[] =
@@ -73,63 +71,53 @@
const char kUncleanShutdownDetectedFile[] =
"/var/run/unclean-shutdown-detected";
-} // namespace
-
// disk stats metrics
// The {Read,Write}Sectors numbers are in sectors/second.
// A sector is usually 512 bytes.
-const char MetricsDaemon::kMetricReadSectorsLongName[] =
- "Platform.ReadSectorsLong";
-const char MetricsDaemon::kMetricWriteSectorsLongName[] =
- "Platform.WriteSectorsLong";
-const char MetricsDaemon::kMetricReadSectorsShortName[] =
- "Platform.ReadSectorsShort";
-const char MetricsDaemon::kMetricWriteSectorsShortName[] =
- "Platform.WriteSectorsShort";
+const char kMetricReadSectorsLongName[] = "Platform.ReadSectorsLong";
+const char kMetricWriteSectorsLongName[] = "Platform.WriteSectorsLong";
+const char kMetricReadSectorsShortName[] = "Platform.ReadSectorsShort";
+const char kMetricWriteSectorsShortName[] = "Platform.WriteSectorsShort";
-const int MetricsDaemon::kMetricStatsShortInterval = 1; // seconds
-const int MetricsDaemon::kMetricStatsLongInterval = 30; // seconds
-
-const int MetricsDaemon::kMetricMeminfoInterval = 30; // seconds
+const int kMetricStatsShortInterval = 1; // seconds
+const int kMetricStatsLongInterval = 30; // seconds
// Assume a max rate of 250Mb/s for reads (worse for writes) and 512 byte
// sectors.
-const int MetricsDaemon::kMetricSectorsIOMax = 500000; // sectors/second
-const int MetricsDaemon::kMetricSectorsBuckets = 50; // buckets
+const int kMetricSectorsIOMax = 500000; // sectors/second
+const int kMetricSectorsBuckets = 50; // buckets
// Page size is 4k, sector size is 0.5k. We're not interested in page fault
// rates that the disk cannot sustain.
-const int MetricsDaemon::kMetricPageFaultsMax = kMetricSectorsIOMax / 8;
-const int MetricsDaemon::kMetricPageFaultsBuckets = 50;
+const int kMetricPageFaultsMax = kMetricSectorsIOMax / 8;
+const int kMetricPageFaultsBuckets = 50;
// Major page faults, i.e. the ones that require data to be read from disk.
-const char MetricsDaemon::kMetricPageFaultsLongName[] =
- "Platform.PageFaultsLong";
-const char MetricsDaemon::kMetricPageFaultsShortName[] =
- "Platform.PageFaultsShort";
+const char kMetricPageFaultsLongName[] = "Platform.PageFaultsLong";
+const char kMetricPageFaultsShortName[] = "Platform.PageFaultsShort";
// Swap in and Swap out
-const char MetricsDaemon::kMetricSwapInLongName[] =
- "Platform.SwapInLong";
-const char MetricsDaemon::kMetricSwapInShortName[] =
- "Platform.SwapInShort";
+const char kMetricSwapInLongName[] = "Platform.SwapInLong";
+const char kMetricSwapInShortName[] = "Platform.SwapInShort";
-const char MetricsDaemon::kMetricSwapOutLongName[] =
- "Platform.SwapOutLong";
-const char MetricsDaemon::kMetricSwapOutShortName[] =
- "Platform.SwapOutShort";
+const char kMetricSwapOutLongName[] = "Platform.SwapOutLong";
+const char kMetricSwapOutShortName[] = "Platform.SwapOutShort";
-const char MetricsDaemon::kMetricsProcStatFileName[] = "/proc/stat";
-const int MetricsDaemon::kMetricsProcStatFirstLineItemsCount = 11;
+const char kMetricsProcStatFileName[] = "/proc/stat";
+const char kVmStatFileName[] = "/proc/vmstat";
+const char kMeminfoFileName[] = "/proc/meminfo";
+const int kMetricsProcStatFirstLineItemsCount = 11;
// Thermal CPU throttling.
-const char MetricsDaemon::kMetricScaledCpuFrequencyName[] =
+const char kMetricScaledCpuFrequencyName[] =
"Platform.CpuFrequencyThermalScaling";
+} // namespace
+
// Zram sysfs entries.
const char MetricsDaemon::kComprDataSizeName[] = "compr_data_size";
@@ -195,10 +183,10 @@
}
void MetricsDaemon::RunUploaderTest() {
- upload_service_.reset(new UploadService(new SystemProfileCache(true,
- config_root_),
- metrics_lib_,
- server_));
+ upload_service_.reset(new UploadService(
+ new SystemProfileCache(true, base::FilePath(config_root_)),
+ metrics_lib_,
+ server_));
upload_service_->Init(upload_interval_, metrics_file_);
upload_service_->UploadEvent();
}
@@ -227,18 +215,17 @@
bool uploader_active,
bool dbus_enabled,
MetricsLibraryInterface* metrics_lib,
- const string& vmstats_path,
const string& scaling_max_freq_path,
const string& cpuinfo_max_freq_path,
const base::TimeDelta& upload_interval,
const string& server,
const string& metrics_file,
const string& config_root) {
+ CHECK(metrics_lib);
testing_ = testing;
uploader_active_ = uploader_active;
dbus_enabled_ = dbus_enabled;
config_root_ = config_root;
- DCHECK(metrics_lib != nullptr);
metrics_lib_ = metrics_lib;
upload_interval_ = upload_interval;
@@ -286,7 +273,6 @@
weekly_cycle_.reset(new PersistentInteger("weekly.cycle"));
version_cycle_.reset(new PersistentInteger("version.cycle"));
- vmstats_path_ = vmstats_path;
scaling_max_freq_path_ = scaling_max_freq_path;
cpuinfo_max_freq_path_ = cpuinfo_max_freq_path;
}
@@ -510,48 +496,22 @@
bool MetricsDaemon::VmStatsParseStats(const char* stats,
struct VmstatRecord* record) {
- // a mapping of string name to field in VmstatRecord and whether we found it
- struct mapping {
- const string name;
- uint64_t* value_p;
- bool found;
- } map[] =
- { { .name = "pgmajfault",
- .value_p = &record->page_faults_,
- .found = false },
- { .name = "pswpin",
- .value_p = &record->swap_in_,
- .found = false },
- { .name = "pswpout",
- .value_p = &record->swap_out_,
- .found = false }, };
+ CHECK(stats);
+ CHECK(record);
+ base::StringPairs pairs;
+ base::SplitStringIntoKeyValuePairs(stats, ' ', '\n', &pairs);
- // Each line in the file has the form
- // <ID> <VALUE>
- // for instance:
- // nr_free_pages 213427
- vector<string> lines;
- Tokenize(stats, "\n", &lines);
- for (vector<string>::iterator it = lines.begin();
- it != lines.end(); ++it) {
- vector<string> tokens;
- base::SplitString(*it, ' ', &tokens);
- if (tokens.size() == 2) {
- for (unsigned int i = 0; i < sizeof(map)/sizeof(struct mapping); i++) {
- if (!tokens[0].compare(map[i].name)) {
- if (!base::StringToUint64(tokens[1], map[i].value_p))
- return false;
- map[i].found = true;
- }
- }
- } else {
- LOG(WARNING) << "unexpected vmstat format";
+ for (base::StringPairs::iterator it = pairs.begin(); it != pairs.end(); ++it) {
+ if (it->first == "pgmajfault" &&
+ !base::StringToUint64(it->second, &record->page_faults_)) {
+ return false;
}
- }
- // make sure we got all the stats
- for (unsigned i = 0; i < sizeof(map)/sizeof(struct mapping); i++) {
- if (map[i].found == false) {
- LOG(WARNING) << "vmstat missing " << map[i].name;
+ if (it->first == "pswpin" &&
+ !base::StringToUint64(it->second, &record->swap_in_)) {
+ return false;
+ }
+ if (it->first == "pswpout" &&
+ !base::StringToUint64(it->second, &record->swap_out_)) {
return false;
}
}
@@ -559,14 +519,12 @@
}
bool MetricsDaemon::VmStatsReadStats(struct VmstatRecord* stats) {
+ CHECK(stats);
string value_string;
- FilePath* path = new FilePath(vmstats_path_);
- if (!base::ReadFileToString(*path, &value_string)) {
- delete path;
- LOG(WARNING) << "cannot read " << vmstats_path_;
+ if (!base::ReadFileToString(base::FilePath(kVmStatFileName), &value_string)) {
+ LOG(WARNING) << "cannot read " << kVmStatFileName;
return false;
}
- delete path;
return VmStatsParseStats(value_string.c_str(), stats);
}
@@ -748,7 +706,7 @@
void MetricsDaemon::MeminfoCallback(base::TimeDelta wait) {
string meminfo_raw;
- const FilePath meminfo_path("/proc/meminfo");
+ const FilePath meminfo_path(kMeminfoFileName);
if (!base::ReadFileToString(meminfo_path, &meminfo_raw)) {
LOG(WARNING) << "cannot read " << meminfo_path.value().c_str();
return;
@@ -907,11 +865,8 @@
Tokenize(lines[iline], ": ", &tokens);
if (strcmp((*fields)[ifield].match, tokens[0].c_str()) == 0) {
// Name matches. Parse value and save.
- char* rest;
- (*fields)[ifield].value =
- static_cast<int>(strtol(tokens[1].c_str(), &rest, 10));
- if (*rest != '\0') {
- LOG(WARNING) << "missing meminfo value";
+ if (!base::StringToInt(tokens[1], &(*fields)[ifield].value)) {
+ LOG(WARNING) << "Cound not convert " << tokens[1] << " to int";
return false;
}
ifield++;
@@ -958,7 +913,7 @@
bool MetricsDaemon::MemuseCallbackWork() {
string meminfo_raw;
- const FilePath meminfo_path("/proc/meminfo");
+ const FilePath meminfo_path(kMeminfoFileName);
if (!base::ReadFileToString(meminfo_path, &meminfo_raw)) {
LOG(WARNING) << "cannot read " << meminfo_path.value().c_str();
return false;
diff --git a/metricsd/metrics_daemon.h b/metricsd/metrics_daemon.h
index 6f5a3bf..9180e23 100644
--- a/metricsd/metrics_daemon.h
+++ b/metricsd/metrics_daemon.h
@@ -45,7 +45,6 @@
bool uploader_active,
bool dbus_enabled,
MetricsLibraryInterface* metrics_lib,
- const std::string& vmstats_path,
const std::string& cpuinfo_max_freq_path,
const std::string& scaling_max_freq_path,
const base::TimeDelta& upload_interval,
@@ -101,14 +100,6 @@
kStatsLong, // final wait before new collection
};
- // Data record for aggregating daily usage.
- class UseRecord {
- public:
- UseRecord() : day_(0), seconds_(0) {}
- int day_;
- int seconds_;
- };
-
// Type of scale to use for meminfo histograms. For most of them we use
// percent of total RAM, but for some we use absolute numbers, usually in
// megabytes, on a log scale from 0 to 4000, and 0 to 8000 for compressed
@@ -135,30 +126,6 @@
uint64_t swap_out_; // pages swapped out
};
- // Metric parameters.
- static const char kMetricReadSectorsLongName[];
- static const char kMetricReadSectorsShortName[];
- static const char kMetricWriteSectorsLongName[];
- static const char kMetricWriteSectorsShortName[];
- static const char kMetricPageFaultsShortName[];
- static const char kMetricPageFaultsLongName[];
- static const char kMetricSwapInLongName[];
- static const char kMetricSwapInShortName[];
- static const char kMetricSwapOutLongName[];
- static const char kMetricSwapOutShortName[];
- static const char kMetricScaledCpuFrequencyName[];
- static const int kMetricStatsShortInterval;
- static const int kMetricStatsLongInterval;
- static const int kMetricMeminfoInterval;
- static const int kMetricSectorsIOMax;
- static const int kMetricSectorsBuckets;
- static const int kMetricPageFaultsMax;
- static const int kMetricPageFaultsBuckets;
- static const char kMetricsDiskStatsPath[];
- static const char kMetricsVmStatsPath[];
- static const char kMetricsProcStatFileName[];
- static const int kMetricsProcStatFirstLineItemsCount;
-
// Returns the active time since boot (uptime minus sleep time) in seconds.
double GetActiveTime();
@@ -167,13 +134,6 @@
DBusMessage* message,
void* user_data);
- // Updates the daily usage file, if necessary, by adding |seconds|
- // of active use to the |day| since Epoch. If there's usage data for
- // day in the past in the usage file, that data is sent to UMA and
- // removed from the file. If there's already usage data for |day| in
- // the usage file, the |seconds| are accumulated.
- void LogDailyUseRecord(int day, int seconds);
-
// Updates the active use time and logs time between user-space
// process crashes.
void ProcessUserCrash();
@@ -312,11 +272,6 @@
// The metrics library handle.
MetricsLibraryInterface* metrics_lib_;
- // Timestamps last network state update. This timestamp is used to
- // sample the time from the network going online to going offline so
- // TimeTicks ensures a monotonically increasing TimeDelta.
- base::TimeTicks network_state_last_;
-
// The last time that UpdateStats() was called.
base::TimeTicks last_update_stats_time_;
@@ -369,7 +324,6 @@
scoped_ptr<PersistentInteger> unclean_shutdowns_daily_count_;
scoped_ptr<PersistentInteger> unclean_shutdowns_weekly_count_;
- std::string vmstats_path_;
std::string scaling_max_freq_path_;
std::string cpuinfo_max_freq_path_;
diff --git a/metricsd/metrics_daemon_main.cc b/metricsd/metrics_daemon_main.cc
index c3d5cab..7f9ec43 100644
--- a/metricsd/metrics_daemon_main.cc
+++ b/metricsd/metrics_daemon_main.cc
@@ -75,7 +75,6 @@
FLAGS_uploader | FLAGS_uploader_test,
FLAGS_withdbus,
&metrics_lib,
- "/proc/vmstat",
kScalingMaxFreqPath,
kCpuinfoMaxFreqPath,
base::TimeDelta::FromSeconds(FLAGS_upload_interval_secs),
diff --git a/metricsd/metrics_daemon_test.cc b/metricsd/metrics_daemon_test.cc
index 9b5b58e..0d2229c 100644
--- a/metricsd/metrics_daemon_test.cc
+++ b/metricsd/metrics_daemon_test.cc
@@ -22,11 +22,12 @@
#include <base/at_exit.h>
#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
-#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>
+#include "constants.h"
#include "metrics_daemon.h"
#include "metrics_library_mock.h"
#include "persistent_integer_mock.h"
@@ -45,7 +46,6 @@
using ::testing::StrictMock;
using chromeos_metrics::PersistentIntegerMock;
-static const char kFakeDiskStatsName[] = "fake-disk-stats";
static const char kFakeDiskStatsFormat[] =
" 1793 1788 %" PRIu64 " 105580 "
" 196 175 %" PRIu64 " 30290 "
@@ -53,9 +53,6 @@
static const uint64_t kFakeReadSectors[] = {80000, 100000};
static const uint64_t kFakeWriteSectors[] = {3000, 4000};
-static const char kFakeVmStatsName[] = "fake-vm-stats";
-static const char kFakeScalingMaxFreqPath[] = "fake-scaling-max-freq";
-static const char kFakeCpuinfoMaxFreqPath[] = "fake-cpuinfo-max-freq";
class MetricsDaemonTest : public testing::Test {
protected:
@@ -63,78 +60,34 @@
std::string kFakeDiskStats1;
virtual void SetUp() {
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+ scaling_max_freq_path_ = temp_dir_.path().Append("scaling_max");
+ cpu_max_freq_path_ = temp_dir_.path().Append("cpu_freq_max");
+ disk_stats_path_ = temp_dir_.path().Append("disk_stats");
+
kFakeDiskStats0 = base::StringPrintf(kFakeDiskStatsFormat,
kFakeReadSectors[0],
kFakeWriteSectors[0]);
kFakeDiskStats1 = base::StringPrintf(kFakeDiskStatsFormat,
kFakeReadSectors[1],
kFakeWriteSectors[1]);
- CreateFakeDiskStatsFile(kFakeDiskStats0.c_str());
- CreateUint64ValueFile(base::FilePath(kFakeCpuinfoMaxFreqPath), 10000000);
- CreateUint64ValueFile(base::FilePath(kFakeScalingMaxFreqPath), 10000000);
- chromeos_metrics::PersistentInteger::SetTestingMode(true);
+ CreateFakeDiskStatsFile(kFakeDiskStats0);
+ CreateUint64ValueFile(cpu_max_freq_path_, 10000000);
+ CreateUint64ValueFile(scaling_max_freq_path_, 10000000);
+
+ chromeos_metrics::PersistentInteger::SetMetricsDirectory(
+ temp_dir_.path().value());
daemon_.Init(true,
false,
+ true,
&metrics_lib_,
- kFakeDiskStatsName,
- kFakeVmStatsName,
- kFakeScalingMaxFreqPath,
- kFakeCpuinfoMaxFreqPath,
+ scaling_max_freq_path_.value(),
+ cpu_max_freq_path_.value(),
base::TimeDelta::FromMinutes(30),
- kMetricsServer,
- kMetricsFilePath,
+ metrics::kMetricsServer,
+ metrics::kMetricsEventsFilePath,
"/");
-
- // Replace original persistent values with mock ones.
- daily_active_use_mock_ =
- new StrictMock<PersistentIntegerMock>("1.mock");
- daemon_.daily_active_use_.reset(daily_active_use_mock_);
-
- kernel_crash_interval_mock_ =
- new StrictMock<PersistentIntegerMock>("2.mock");
- daemon_.kernel_crash_interval_.reset(kernel_crash_interval_mock_);
-
- user_crash_interval_mock_ =
- new StrictMock<PersistentIntegerMock>("3.mock");
- daemon_.user_crash_interval_.reset(user_crash_interval_mock_);
-
- unclean_shutdown_interval_mock_ =
- new StrictMock<PersistentIntegerMock>("4.mock");
- daemon_.unclean_shutdown_interval_.reset(unclean_shutdown_interval_mock_);
- }
-
- virtual void TearDown() {
- EXPECT_EQ(0, unlink(kFakeDiskStatsName));
- EXPECT_EQ(0, unlink(kFakeScalingMaxFreqPath));
- EXPECT_EQ(0, unlink(kFakeCpuinfoMaxFreqPath));
- }
-
- // Adds active use aggregation counters update expectations that the
- // specified count will be added.
- void ExpectActiveUseUpdate(int count) {
- EXPECT_CALL(*daily_active_use_mock_, Add(count))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*kernel_crash_interval_mock_, Add(count))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*user_crash_interval_mock_, Add(count))
- .Times(1)
- .RetiresOnSaturation();
- }
-
- // As above, but ignore values of counter updates.
- void IgnoreActiveUseUpdate() {
- EXPECT_CALL(*daily_active_use_mock_, Add(_))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*kernel_crash_interval_mock_, Add(_))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*user_crash_interval_mock_, Add(_))
- .Times(1)
- .RetiresOnSaturation();
}
// Adds a metrics library mock expectation that the specified metric
@@ -177,19 +130,15 @@
}
// Creates or overwrites an input file containing fake disk stats.
- void CreateFakeDiskStatsFile(const char* fake_stats) {
- if (unlink(kFakeDiskStatsName) < 0) {
- EXPECT_EQ(errno, ENOENT);
- }
- FILE* f = fopen(kFakeDiskStatsName, "w");
- EXPECT_EQ(1, fwrite(fake_stats, strlen(fake_stats), 1, f));
- EXPECT_EQ(0, fclose(f));
+ void CreateFakeDiskStatsFile(const string& fake_stats) {
+ EXPECT_EQ(base::WriteFile(disk_stats_path_,
+ fake_stats.data(), fake_stats.size()),
+ fake_stats.size());
}
// Creates or overwrites the file in |path| so that it contains the printable
// representation of |value|.
void CreateUint64ValueFile(const base::FilePath& path, uint64_t value) {
- base::DeleteFile(path, false);
std::string value_string = base::Uint64ToString(value);
ASSERT_EQ(value_string.length(),
base::WriteFile(path, value_string.c_str(),
@@ -199,29 +148,19 @@
// The MetricsDaemon under test.
MetricsDaemon daemon_;
+ // Temporary directory used for tests.
+ base::ScopedTempDir temp_dir_;
+
+ // Path for the fake files.
+ base::FilePath scaling_max_freq_path_;
+ base::FilePath cpu_max_freq_path_;
+ base::FilePath disk_stats_path_;
+
// Mocks. They are strict mock so that all unexpected
// calls are marked as failures.
StrictMock<MetricsLibraryMock> metrics_lib_;
- StrictMock<PersistentIntegerMock>* daily_active_use_mock_;
- StrictMock<PersistentIntegerMock>* kernel_crash_interval_mock_;
- StrictMock<PersistentIntegerMock>* user_crash_interval_mock_;
- StrictMock<PersistentIntegerMock>* unclean_shutdown_interval_mock_;
};
-TEST_F(MetricsDaemonTest, CheckSystemCrash) {
- static const char kKernelCrashDetected[] = "test-kernel-crash-detected";
- EXPECT_FALSE(daemon_.CheckSystemCrash(kKernelCrashDetected));
-
- base::FilePath crash_detected(kKernelCrashDetected);
- base::WriteFile(crash_detected, "", 0);
- EXPECT_TRUE(base::PathExists(crash_detected));
- EXPECT_TRUE(daemon_.CheckSystemCrash(kKernelCrashDetected));
- EXPECT_FALSE(base::PathExists(crash_detected));
- EXPECT_FALSE(daemon_.CheckSystemCrash(kKernelCrashDetected));
- EXPECT_FALSE(base::PathExists(crash_detected));
- base::DeleteFile(crash_detected, false);
-}
-
TEST_F(MetricsDaemonTest, MessageFilter) {
// Ignore calls to SendToUMA.
EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AnyNumber());
@@ -232,7 +171,6 @@
EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
DeleteDBusMessage(msg);
- IgnoreActiveUseUpdate();
vector<string> signal_args;
msg = NewDBusSignalString("/",
"org.chromium.CrashReporter",
@@ -260,25 +198,6 @@
/* min */ 1, /* max */ 100, /* buckets */ 50);
}
-TEST_F(MetricsDaemonTest, ReportDiskStats) {
- uint64_t read_sectors_now, write_sectors_now;
- CreateFakeDiskStatsFile(kFakeDiskStats1.c_str());
- daemon_.DiskStatsReadStats(&read_sectors_now, &write_sectors_now);
- EXPECT_EQ(read_sectors_now, kFakeReadSectors[1]);
- EXPECT_EQ(write_sectors_now, kFakeWriteSectors[1]);
-
- MetricsDaemon::StatsState s_state = daemon_.stats_state_;
- EXPECT_CALL(metrics_lib_,
- SendToUMA(_, (kFakeReadSectors[1] - kFakeReadSectors[0]) / 30,
- _, _, _));
- EXPECT_CALL(metrics_lib_,
- SendToUMA(_, (kFakeWriteSectors[1] - kFakeWriteSectors[0]) / 30,
- _, _, _));
- EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, _, _)); // SendCpuThrottleMetrics
- daemon_.StatsCallback();
- EXPECT_TRUE(s_state != daemon_.stats_state_);
-}
-
TEST_F(MetricsDaemonTest, ProcessMeminfo) {
string meminfo =
"MemTotal: 2000000 kB\nMemFree: 500000 kB\n"
@@ -337,24 +256,24 @@
const int fake_max_freq = 2000000;
int scaled_freq = 0;
int max_freq = 0;
- CreateUint64ValueFile(base::FilePath(kFakeScalingMaxFreqPath),
- fake_scaled_freq);
- CreateUint64ValueFile(base::FilePath(kFakeCpuinfoMaxFreqPath), fake_max_freq);
+ CreateUint64ValueFile(scaling_max_freq_path_, fake_scaled_freq);
+ CreateUint64ValueFile(cpu_max_freq_path_, fake_max_freq);
EXPECT_TRUE(daemon_.testing_);
- EXPECT_TRUE(daemon_.ReadFreqToInt(kFakeScalingMaxFreqPath, &scaled_freq));
- EXPECT_TRUE(daemon_.ReadFreqToInt(kFakeCpuinfoMaxFreqPath, &max_freq));
+ EXPECT_TRUE(daemon_.ReadFreqToInt(scaling_max_freq_path_.value(),
+ &scaled_freq));
+ EXPECT_TRUE(daemon_.ReadFreqToInt(cpu_max_freq_path_.value(), &max_freq));
EXPECT_EQ(fake_scaled_freq, scaled_freq);
EXPECT_EQ(fake_max_freq, max_freq);
}
TEST_F(MetricsDaemonTest, SendCpuThrottleMetrics) {
- CreateUint64ValueFile(base::FilePath(kFakeCpuinfoMaxFreqPath), 2001000);
+ CreateUint64ValueFile(cpu_max_freq_path_, 2001000);
// Test the 101% and 100% cases.
- CreateUint64ValueFile(base::FilePath(kFakeScalingMaxFreqPath), 2001000);
+ CreateUint64ValueFile(scaling_max_freq_path_, 2001000);
EXPECT_TRUE(daemon_.testing_);
EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, 101, 101));
daemon_.SendCpuThrottleMetrics();
- CreateUint64ValueFile(base::FilePath(kFakeScalingMaxFreqPath), 2000000);
+ CreateUint64ValueFile(scaling_max_freq_path_, 2000000);
EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, 100, 101));
daemon_.SendCpuThrottleMetrics();
}
@@ -370,12 +289,14 @@
const uint64_t page_size = 4096;
const uint64_t zero_pages = 10 * 1000 * 1000 / page_size;
- CreateUint64ValueFile(base::FilePath(MetricsDaemon::kComprDataSizeName),
- compr_data_size);
- CreateUint64ValueFile(base::FilePath(MetricsDaemon::kOrigDataSizeName),
- orig_data_size);
- CreateUint64ValueFile(base::FilePath(MetricsDaemon::kZeroPagesName),
- zero_pages);
+ CreateUint64ValueFile(
+ temp_dir_.path().Append(MetricsDaemon::kComprDataSizeName),
+ compr_data_size);
+ CreateUint64ValueFile(
+ temp_dir_.path().Append(MetricsDaemon::kOrigDataSizeName),
+ orig_data_size);
+ CreateUint64ValueFile(
+ temp_dir_.path().Append(MetricsDaemon::kZeroPagesName), zero_pages);
const uint64_t real_orig_size = orig_data_size + zero_pages * page_size;
const uint64_t zero_ratio_percent =
@@ -390,11 +311,5 @@
EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_pages, _, _, _));
EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_ratio_percent, _, _, _));
- EXPECT_TRUE(daemon_.ReportZram(base::FilePath(".")));
-}
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
-
- return RUN_ALL_TESTS();
+ EXPECT_TRUE(daemon_.ReportZram(temp_dir_.path()));
}
diff --git a/metricsd/metrics_library.cc b/metricsd/metrics_library.cc
index c1998a6..5687f1b 100644
--- a/metricsd/metrics_library.cc
+++ b/metricsd/metrics_library.cc
@@ -140,6 +140,12 @@
uma_events_file_ = metrics::kMetricsEventsFilePath;
}
+void MetricsLibrary::InitForTest(const std::string& uma_events_file,
+ const std::string& consent_file) {
+ uma_events_file_ = uma_events_file;
+ consent_file_ = consent_file;
+}
+
bool MetricsLibrary::SendToUMA(const std::string& name,
int sample,
int min,
diff --git a/metricsd/metrics_library_test.cc b/metricsd/metrics_library_test.cc
index c58e3fb..7ade6ee 100644
--- a/metricsd/metrics_library_test.cc
+++ b/metricsd/metrics_library_test.cc
@@ -14,130 +14,52 @@
* limitations under the License.
*/
-#include <cstring>
#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <policy/mock_device_policy.h>
-#include <policy/libpolicy.h>
#include "metrics/c_metrics_library.h"
#include "metrics/metrics_library.h"
-using base::FilePath;
-using ::testing::_;
-using ::testing::Return;
-using ::testing::AnyNumber;
-
-static const FilePath kTestUMAEventsFile("test-uma-events");
-static const char kTestMounts[] = "test-mounts";
-
-ACTION_P(SetMetricsPolicy, enabled) {
- *arg0 = enabled;
- return true;
-}
class MetricsLibraryTest : public testing::Test {
protected:
virtual void SetUp() {
- EXPECT_TRUE(lib_.uma_events_file_.empty());
- lib_.Init();
- EXPECT_FALSE(lib_.uma_events_file_.empty());
- lib_.uma_events_file_ = kTestUMAEventsFile.value();
- EXPECT_EQ(0, WriteFile(kTestUMAEventsFile, "", 0));
- device_policy_ = new policy::MockDevicePolicy();
- EXPECT_CALL(*device_policy_, LoadPolicy())
- .Times(AnyNumber())
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*device_policy_, GetMetricsEnabled(_))
- .Times(AnyNumber())
- .WillRepeatedly(SetMetricsPolicy(true));
- provider_ = new policy::PolicyProvider(device_policy_);
- lib_.SetPolicyProvider(provider_);
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ consent_file_ = temp_dir_.path().Append("consent");
+ uma_events_file_ = temp_dir_.path().Append("events");
+ lib_.InitForTest(uma_events_file_.value(), consent_file_.value());
+ EXPECT_EQ(0, WriteFile(uma_events_file_, "", 0));
// Defeat metrics enabled caching between tests.
lib_.cached_enabled_time_ = 0;
}
- virtual void TearDown() {
- base::DeleteFile(FilePath(kTestMounts), false);
- base::DeleteFile(kTestUMAEventsFile, false);
+ void SetMetricsConsent(bool enabled) {
+ if (enabled) {
+ ASSERT_EQ(base::WriteFile(consent_file_, "", 0), 0);
+ } else {
+ ASSERT_TRUE(base::DeleteFile(consent_file_, false));
+ }
}
void VerifyEnabledCacheHit(bool to_value);
void VerifyEnabledCacheEviction(bool to_value);
MetricsLibrary lib_;
- policy::MockDevicePolicy* device_policy_;
- policy::PolicyProvider* provider_;
+ base::ScopedTempDir temp_dir_;
+ base::FilePath consent_file_;
+ base::FilePath uma_events_file_;
};
-TEST_F(MetricsLibraryTest, IsDeviceMounted) {
- static const char kTestContents[] =
- "0123456789abcde 0123456789abcde\nguestfs foo bar\n";
- char buffer[1024];
- int block_sizes[] = { 1, 2, 3, 4, 5, 6, 8, 12, 14, 16, 32, 1024 };
- bool result;
- EXPECT_FALSE(lib_.IsDeviceMounted("guestfs",
- "nonexistent",
- buffer,
- 1,
- &result));
- ASSERT_TRUE(base::WriteFile(base::FilePath(kTestMounts),
- kTestContents,
- strlen(kTestContents)));
- EXPECT_FALSE(lib_.IsDeviceMounted("guestfs",
- kTestMounts,
- buffer,
- 0,
- &result));
- for (size_t i = 0; i < arraysize(block_sizes); ++i) {
- EXPECT_TRUE(lib_.IsDeviceMounted("0123456789abcde",
- kTestMounts,
- buffer,
- block_sizes[i],
- &result));
- EXPECT_TRUE(result);
- EXPECT_TRUE(lib_.IsDeviceMounted("guestfs",
- kTestMounts,
- buffer,
- block_sizes[i],
- &result));
- EXPECT_TRUE(result);
- EXPECT_TRUE(lib_.IsDeviceMounted("0123456",
- kTestMounts,
- buffer,
- block_sizes[i],
- &result));
- EXPECT_FALSE(result);
- EXPECT_TRUE(lib_.IsDeviceMounted("9abcde",
- kTestMounts,
- buffer,
- block_sizes[i],
- &result));
- EXPECT_FALSE(result);
- EXPECT_TRUE(lib_.IsDeviceMounted("foo",
- kTestMounts,
- buffer,
- block_sizes[i],
- &result));
- EXPECT_FALSE(result);
- EXPECT_TRUE(lib_.IsDeviceMounted("bar",
- kTestMounts,
- buffer,
- block_sizes[i],
- &result));
- EXPECT_FALSE(result);
- }
-}
-
TEST_F(MetricsLibraryTest, AreMetricsEnabledFalse) {
- EXPECT_CALL(*device_policy_, GetMetricsEnabled(_))
- .WillOnce(SetMetricsPolicy(false));
+ SetMetricsConsent(false);
EXPECT_FALSE(lib_.AreMetricsEnabled());
}
TEST_F(MetricsLibraryTest, AreMetricsEnabledTrue) {
+ SetMetricsConsent(true);
EXPECT_TRUE(lib_.AreMetricsEnabled());
}
@@ -146,12 +68,12 @@
// times in a row.
for (int i = 0; i < 100; ++i) {
lib_.cached_enabled_time_ = 0;
- EXPECT_CALL(*device_policy_, GetMetricsEnabled(_))
- .WillOnce(SetMetricsPolicy(!to_value));
- ASSERT_EQ(!to_value, lib_.AreMetricsEnabled());
- ON_CALL(*device_policy_, GetMetricsEnabled(_))
- .WillByDefault(SetMetricsPolicy(to_value));
- if (lib_.AreMetricsEnabled() == !to_value)
+ SetMetricsConsent(to_value);
+ lib_.AreMetricsEnabled();
+ // If we check the metrics status twice in a row, we use the cached value
+ // the second time.
+ SetMetricsConsent(!to_value);
+ if (lib_.AreMetricsEnabled() == to_value)
return;
}
ADD_FAILURE() << "Did not see evidence of caching";
@@ -159,14 +81,12 @@
void MetricsLibraryTest::VerifyEnabledCacheEviction(bool to_value) {
lib_.cached_enabled_time_ = 0;
- EXPECT_CALL(*device_policy_, GetMetricsEnabled(_))
- .WillOnce(SetMetricsPolicy(!to_value));
+ SetMetricsConsent(!to_value);
ASSERT_EQ(!to_value, lib_.AreMetricsEnabled());
- EXPECT_CALL(*device_policy_, GetMetricsEnabled(_))
- .WillOnce(SetMetricsPolicy(to_value));
- ASSERT_LT(abs(static_cast<int>(time(nullptr) - lib_.cached_enabled_time_)),
- 5);
- // Sleep one second (or cheat to be faster).
+
+ SetMetricsConsent(to_value);
+ // Sleep one second (or cheat to be faster) and check that we are not using
+ // the cached value.
--lib_.cached_enabled_time_;
ASSERT_EQ(to_value, lib_.AreMetricsEnabled());
}
@@ -177,50 +97,3 @@
VerifyEnabledCacheEviction(false);
VerifyEnabledCacheEviction(true);
}
-
-class CMetricsLibraryTest : public testing::Test {
- protected:
- virtual void SetUp() {
- lib_ = CMetricsLibraryNew();
- MetricsLibrary& ml = *reinterpret_cast<MetricsLibrary*>(lib_);
- EXPECT_TRUE(ml.uma_events_file_.empty());
- CMetricsLibraryInit(lib_);
- EXPECT_FALSE(ml.uma_events_file_.empty());
- ml.uma_events_file_ = kTestUMAEventsFile.value();
- EXPECT_EQ(0, WriteFile(kTestUMAEventsFile, "", 0));
- device_policy_ = new policy::MockDevicePolicy();
- EXPECT_CALL(*device_policy_, LoadPolicy())
- .Times(AnyNumber())
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*device_policy_, GetMetricsEnabled(_))
- .Times(AnyNumber())
- .WillRepeatedly(SetMetricsPolicy(true));
- provider_ = new policy::PolicyProvider(device_policy_);
- ml.SetPolicyProvider(provider_);
- reinterpret_cast<MetricsLibrary*>(lib_)->cached_enabled_time_ = 0;
- }
-
- virtual void TearDown() {
- CMetricsLibraryDelete(lib_);
- base::DeleteFile(kTestUMAEventsFile, false);
- }
-
- CMetricsLibrary lib_;
- policy::MockDevicePolicy* device_policy_;
- policy::PolicyProvider* provider_;
-};
-
-TEST_F(CMetricsLibraryTest, AreMetricsEnabledFalse) {
- EXPECT_CALL(*device_policy_, GetMetricsEnabled(_))
- .WillOnce(SetMetricsPolicy(false));
- EXPECT_FALSE(CMetricsLibraryAreMetricsEnabled(lib_));
-}
-
-TEST_F(CMetricsLibraryTest, AreMetricsEnabledTrue) {
- EXPECT_TRUE(CMetricsLibraryAreMetricsEnabled(lib_));
-}
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/metricsd/persistent_integer.cc b/metricsd/persistent_integer.cc
index 9fa5c1e..e849f00 100644
--- a/metricsd/persistent_integer.cc
+++ b/metricsd/persistent_integer.cc
@@ -28,18 +28,14 @@
namespace chromeos_metrics {
// Static class member instantiation.
-bool PersistentInteger::testing_ = false;
+std::string PersistentInteger::metrics_directory_ = metrics::kMetricsDirectory;
PersistentInteger::PersistentInteger(const std::string& name) :
value_(0),
version_(kVersion),
name_(name),
synced_(false) {
- if (testing_) {
- backing_file_name_ = name_;
- } else {
- backing_file_name_ = metrics::kMetricsDirectory + name_;
- }
+ backing_file_name_ = metrics_directory_ + name_;
}
PersistentInteger::~PersistentInteger() {}
@@ -100,8 +96,8 @@
return read_succeeded;
}
-void PersistentInteger::SetTestingMode(bool testing) {
- testing_ = testing;
+void PersistentInteger::SetMetricsDirectory(const std::string& directory) {
+ metrics_directory_ = directory;
}
diff --git a/metricsd/persistent_integer.h b/metricsd/persistent_integer.h
index fec001f..ecef3d1 100644
--- a/metricsd/persistent_integer.h
+++ b/metricsd/persistent_integer.h
@@ -50,10 +50,9 @@
// Virtual only because of mock.
virtual void Add(int64_t x);
- // After calling with |testing| = true, changes some behavior for the purpose
- // of testing. For instance: instances created while testing use the current
- // directory for the backing files.
- static void SetTestingMode(bool testing);
+ // Sets the directory path for all persistent integers.
+ // This is used in unittests to change where the counters are stored.
+ static void SetMetricsDirectory(const std::string& directory);
private:
static const int kVersion = 1001;
@@ -70,8 +69,8 @@
int32_t version_;
std::string name_;
std::string backing_file_name_;
+ static std::string metrics_directory_;
bool synced_;
- static bool testing_;
};
} // namespace chromeos_metrics
diff --git a/metricsd/persistent_integer_test.cc b/metricsd/persistent_integer_test.cc
index 19801f9..5e2067f 100644
--- a/metricsd/persistent_integer_test.cc
+++ b/metricsd/persistent_integer_test.cc
@@ -19,6 +19,7 @@
#include <base/compiler_specific.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
#include "persistent_integer.h"
@@ -30,7 +31,9 @@
class PersistentIntegerTest : public testing::Test {
void SetUp() override {
// Set testing mode.
- chromeos_metrics::PersistentInteger::SetTestingMode(true);
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ chromeos_metrics::PersistentInteger::SetMetricsDirectory(
+ temp_dir_.path().value());
}
void TearDown() override {
@@ -45,6 +48,8 @@
base::DeleteFile(name, false);
}
}
+
+ base::ScopedTempDir temp_dir_;
};
TEST_F(PersistentIntegerTest, BasicChecks) {
@@ -71,8 +76,3 @@
pi.reset(new PersistentInteger(kBackingFileName));
EXPECT_EQ(0, pi->Get());
}
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/metricsd/uploader/metrics_log_base.cc b/metricsd/uploader/metrics_log_base.cc
index ee325ae..311e43a 100644
--- a/metricsd/uploader/metrics_log_base.cc
+++ b/metricsd/uploader/metrics_log_base.cc
@@ -73,7 +73,7 @@
// name. We can then use this logging to find out what histogram name was
// being hashed to a given MD5 value by just running the version of Chromium
// in question with --enable-logging.
- DVLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]";
+ VLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]";
return hash;
}
diff --git a/metricsd/uploader/mock/mock_system_profile_setter.h b/metricsd/uploader/mock/mock_system_profile_setter.h
index c714e9c..9b20291 100644
--- a/metricsd/uploader/mock/mock_system_profile_setter.h
+++ b/metricsd/uploader/mock/mock_system_profile_setter.h
@@ -26,7 +26,9 @@
// Mock profile setter used for testing.
class MockSystemProfileSetter : public SystemProfileSetter {
public:
- void Populate(metrics::ChromeUserMetricsExtension* profile_proto) override {}
+ bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) override {
+ return true;
+ }
};
#endif // METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/system_profile_cache.cc b/metricsd/uploader/system_profile_cache.cc
index 21ec229..8635fb0 100644
--- a/metricsd/uploader/system_profile_cache.cc
+++ b/metricsd/uploader/system_profile_cache.cc
@@ -61,7 +61,7 @@
}
SystemProfileCache::SystemProfileCache(bool testing,
- const std::string& config_root)
+ const base::FilePath& config_root)
: initialized_(false),
testing_(testing),
config_root_(config_root),
@@ -73,9 +73,7 @@
CHECK(!initialized_)
<< "this should be called only once in the metrics_daemon lifetime.";
- char property_value[PROPERTY_VALUE_MAX];
- property_get(metrics::kBuildTargetIdProperty, property_value, "");
- profile_.build_target_id = std::string(property_value);
+ profile_.build_target_id = GetProperty(metrics::kBuildTargetIdProperty);
if (profile_.build_target_id.empty()) {
LOG(ERROR) << "System property " << metrics::kBuildTargetIdProperty
@@ -83,11 +81,8 @@
return false;
}
- property_get(metrics::kChannelProperty, property_value, "");
- std::string channel(property_value);
-
- property_get(metrics::kProductVersionProperty, property_value, "");
- profile_.version = std::string(property_value);
+ std::string channel = GetProperty(metrics::kChannelProperty);
+ profile_.version = GetProperty(metrics::kProductVersionProperty);
if (channel.empty() || profile_.version.empty()) {
// If the channel or version is missing, the image is not official.
@@ -157,6 +152,18 @@
return guid;
}
+std::string SystemProfileCache::GetProperty(const std::string& name) {
+ if (testing_) {
+ std::string content;
+ base::ReadFileToString(config_root_.Append(name), &content);
+ return content;
+ } else {
+ char value[PROPERTY_VALUE_MAX];
+ property_get(name.data(), value, "");
+ return std::string(value);
+ }
+}
+
metrics::SystemProfileProto_Channel SystemProfileCache::ProtoChannelFromString(
const std::string& channel) {
if (channel == "stable") {
diff --git a/metricsd/uploader/system_profile_cache.h b/metricsd/uploader/system_profile_cache.h
index ac80b47..7157810 100644
--- a/metricsd/uploader/system_profile_cache.h
+++ b/metricsd/uploader/system_profile_cache.h
@@ -22,6 +22,7 @@
#include <string>
#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "persistent_integer.h"
@@ -49,7 +50,7 @@
public:
SystemProfileCache();
- SystemProfileCache(bool testing, const std::string& config_root);
+ SystemProfileCache(bool testing, const base::FilePath& config_root);
// Populates the ProfileSystem protobuf with system information.
bool Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
@@ -75,9 +76,14 @@
// Initializes |profile_| only if it has not been yet initialized.
bool InitializeOrCheck();
+ // Gets a system property as a string.
+ // When |testing_| is true, reads the value from |config_root_|/|name|
+ // instead.
+ std::string GetProperty(const std::string& name);
+
bool initialized_;
bool testing_;
- std::string config_root_;
+ base::FilePath config_root_;
scoped_ptr<chromeos_metrics::PersistentInteger> session_id_;
SystemProfile profile_;
};
diff --git a/metricsd/uploader/upload_service_test.cc b/metricsd/uploader/upload_service_test.cc
index cbb5277..40c235d 100644
--- a/metricsd/uploader/upload_service_test.cc
+++ b/metricsd/uploader/upload_service_test.cc
@@ -16,11 +16,13 @@
#include <gtest/gtest.h>
-#include "base/at_exit.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/sys_info.h"
+#include <base/at_exit.h>
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <base/logging.h>
+#include <base/sys_info.h>
+
+#include "constants.h"
#include "metrics_library_mock.h"
#include "serialization/metric_sample.h"
#include "uploader/metrics_log.h"
@@ -34,35 +36,35 @@
class UploadServiceTest : public testing::Test {
protected:
- UploadServiceTest()
- : cache_(true, "/"),
- upload_service_(new MockSystemProfileSetter(), &metrics_lib_,
- kMetricsServer, true),
- exit_manager_(new base::AtExitManager()) {
- sender_ = new SenderMock;
- upload_service_.sender_.reset(sender_);
- upload_service_.Init(base::TimeDelta::FromMinutes(30), kMetricsFilePath);
- }
-
virtual void SetUp() {
CHECK(dir_.CreateUniqueTempDir());
- upload_service_.GatherHistograms();
- upload_service_.Reset();
- sender_->Reset();
+ upload_service_.reset(new UploadService(new MockSystemProfileSetter(),
+ &metrics_lib_, "", true));
- chromeos_metrics::PersistentInteger::SetTestingMode(true);
- cache_.session_id_.reset(new chromeos_metrics::PersistentInteger(
- dir_.path().Append("session_id").value()));
+ upload_service_->sender_.reset(new SenderMock);
+ event_file_ = dir_.path().Append("event");
+ upload_service_->Init(base::TimeDelta::FromMinutes(30), event_file_.value());
+ upload_service_->GatherHistograms();
+ upload_service_->Reset();
+
+ chromeos_metrics::PersistentInteger::SetMetricsDirectory(
+ dir_.path().value());
}
scoped_ptr<metrics::MetricSample> Crash(const std::string& name) {
return metrics::MetricSample::CrashSample(name);
}
+ void SetTestingProperty(const std::string& name, const std::string& value) {
+ ASSERT_EQ(
+ value.size(),
+ base::WriteFile(dir_.path().Append(name), value.data(), value.size()));
+ }
+
+ base::FilePath event_file_;
+
base::ScopedTempDir dir_;
- SenderMock* sender_;
- SystemProfileCache cache_;
- UploadService upload_service_;
+ scoped_ptr<UploadService> upload_service_;
MetricsLibraryMock metrics_lib_;
scoped_ptr<base::AtExitManager> exit_manager_;
@@ -70,18 +72,18 @@
// Tests that the right crash increments a values.
TEST_F(UploadServiceTest, LogUserCrash) {
- upload_service_.AddSample(*Crash("user").get());
+ upload_service_->AddSample(*Crash("user").get());
- MetricsLog* log = upload_service_.current_log_.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"));
+ upload_service_->AddSample(*Crash("uncleanshutdown"));
- EXPECT_EQ(1, upload_service_.current_log_
+ EXPECT_EQ(1, upload_service_->current_log_
->uma_proto()
->system_profile()
.stability()
@@ -89,9 +91,9 @@
}
TEST_F(UploadServiceTest, LogKernelCrash) {
- upload_service_.AddSample(*Crash("kernel"));
+ upload_service_->AddSample(*Crash("kernel"));
- EXPECT_EQ(1, upload_service_.current_log_
+ EXPECT_EQ(1, upload_service_->current_log_
->uma_proto()
->system_profile()
.stability()
@@ -99,47 +101,56 @@
}
TEST_F(UploadServiceTest, UnknownCrashIgnored) {
- upload_service_.AddSample(*Crash("foo"));
+ upload_service_->AddSample(*Crash("foo"));
// The log should be empty.
- EXPECT_FALSE(upload_service_.current_log_);
+ EXPECT_FALSE(upload_service_->current_log_);
}
TEST_F(UploadServiceTest, FailedSendAreRetried) {
- sender_->set_should_succeed(false);
+ SenderMock* sender = new SenderMock();
+ upload_service_->sender_.reset(sender);
- upload_service_.AddSample(*Crash("user"));
- upload_service_.UploadEvent();
- EXPECT_EQ(1, sender_->send_call_count());
- std::string sent_string = sender_->last_message();
+ sender->set_should_succeed(false);
- upload_service_.UploadEvent();
- EXPECT_EQ(2, sender_->send_call_count());
- EXPECT_EQ(sent_string, sender_->last_message());
+ upload_service_->AddSample(*Crash("user"));
+ upload_service_->UploadEvent();
+ EXPECT_EQ(1, sender->send_call_count());
+ std::string sent_string = sender->last_message();
+
+ upload_service_->UploadEvent();
+ EXPECT_EQ(2, sender->send_call_count());
+ EXPECT_EQ(sent_string, sender->last_message());
}
TEST_F(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload) {
- sender_->set_should_succeed(false);
- upload_service_.AddSample(*Crash("user"));
+ SenderMock* sender = new SenderMock();
+ upload_service_->sender_.reset(sender);
+
+ sender->set_should_succeed(false);
+
+ upload_service_->AddSample(*Crash("user"));
for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
- upload_service_.UploadEvent();
+ upload_service_->UploadEvent();
}
- EXPECT_TRUE(upload_service_.staged_log_);
- upload_service_.UploadEvent();
- EXPECT_FALSE(upload_service_.staged_log_);
+ EXPECT_TRUE(upload_service_->staged_log_);
+ upload_service_->UploadEvent();
+ EXPECT_FALSE(upload_service_->staged_log_);
}
TEST_F(UploadServiceTest, EmptyLogsAreNotSent) {
- upload_service_.UploadEvent();
- EXPECT_FALSE(upload_service_.current_log_);
- EXPECT_EQ(0, sender_->send_call_count());
+ SenderMock* sender = new SenderMock();
+ upload_service_->sender_.reset(sender);
+ upload_service_->UploadEvent();
+ EXPECT_FALSE(upload_service_->current_log_);
+ EXPECT_EQ(0, sender->send_call_count());
}
TEST_F(UploadServiceTest, LogEmptyByDefault) {
UploadService upload_service(new MockSystemProfileSetter(), &metrics_lib_,
- kMetricsServer);
+ "");
// current_log_ should be initialized later as it needs AtExitManager to exit
// in order to gather system information from SysInfo.
@@ -147,39 +158,42 @@
}
TEST_F(UploadServiceTest, CanSendMultipleTimes) {
- upload_service_.AddSample(*Crash("user"));
- upload_service_.UploadEvent();
+ SenderMock* sender = new SenderMock();
+ upload_service_->sender_.reset(sender);
- std::string first_message = sender_->last_message();
+ upload_service_->AddSample(*Crash("user"));
+ upload_service_->UploadEvent();
- upload_service_.AddSample(*Crash("kernel"));
- upload_service_.UploadEvent();
+ std::string first_message = sender->last_message();
- EXPECT_NE(first_message, sender_->last_message());
+ upload_service_->AddSample(*Crash("kernel"));
+ upload_service_->UploadEvent();
+
+ EXPECT_NE(first_message, sender->last_message());
}
TEST_F(UploadServiceTest, LogEmptyAfterUpload) {
- upload_service_.AddSample(*Crash("user"));
+ upload_service_->AddSample(*Crash("user"));
- EXPECT_TRUE(upload_service_.current_log_);
+ EXPECT_TRUE(upload_service_->current_log_);
- upload_service_.UploadEvent();
- EXPECT_FALSE(upload_service_.current_log_);
+ 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());
+ upload_service_->AddSample(*histogram.get());
scoped_ptr<metrics::MetricSample> histogram2 =
metrics::MetricSample::HistogramSample("foo", 11, 0, 42, 10);
- upload_service_.AddSample(*histogram2.get());
+ upload_service_->AddSample(*histogram2.get());
- upload_service_.GatherHistograms();
+ upload_service_->GatherHistograms();
metrics::ChromeUserMetricsExtension* proto =
- upload_service_.current_log_->uma_proto();
+ upload_service_->current_log_->uma_proto();
EXPECT_EQ(1, proto->histogram_event().size());
}
@@ -190,46 +204,41 @@
metrics::SystemProfileProto::CHANNEL_UNKNOWN);
EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_DEV,
- SystemProfileCache::ProtoChannelFromString("dev-channel"));
+ SystemProfileCache::ProtoChannelFromString("dev"));
+
+ EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_STABLE,
+ SystemProfileCache::ProtoChannelFromString("stable"));
EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_UNKNOWN,
- SystemProfileCache::ProtoChannelFromString("dev-channel test"));
+ SystemProfileCache::ProtoChannelFromString("this is a test"));
}
TEST_F(UploadServiceTest, ValuesInConfigFileAreSent) {
- std::string name("os name");
- std::string content(
- "CHROMEOS_RELEASE_NAME=" + name +
- "\nCHROMEOS_RELEASE_VERSION=version\n"
- "CHROMEOS_RELEASE_DESCRIPTION=description beta-channel test\n"
- "CHROMEOS_RELEASE_TRACK=beta-channel\n"
- "CHROMEOS_RELEASE_BUILD_TYPE=developer build\n"
- "CHROMEOS_RELEASE_BOARD=myboard");
+ SenderMock* sender = new SenderMock();
+ upload_service_->sender_.reset(sender);
- base::SysInfo::SetChromeOSVersionInfoForTest(content, base::Time());
+ SetTestingProperty(metrics::kChannelProperty, "beta");
+ SetTestingProperty(metrics::kBuildTargetIdProperty, "hello");
+ SetTestingProperty(metrics::kProductVersionProperty, "1.2.3.4");
+
scoped_ptr<metrics::MetricSample> histogram =
metrics::MetricSample::SparseHistogramSample("myhistogram", 1);
- SystemProfileCache* local_cache_ = new SystemProfileCache(true, "/");
- local_cache_->session_id_.reset(new chromeos_metrics::PersistentInteger(
- dir_.path().Append("session_id").value()));
-
- upload_service_.system_profile_setter_.reset(local_cache_);
// Reset to create the new log with the profile setter.
- upload_service_.Reset();
- upload_service_.AddSample(*histogram.get());
- upload_service_.UploadEvent();
+ 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());
- EXPECT_TRUE(sender_->is_good_proto());
- EXPECT_EQ(1, sender_->last_message_proto().histogram_event().size());
+ EXPECT_EQ(1, sender->send_call_count());
+ EXPECT_TRUE(sender->is_good_proto());
+ EXPECT_EQ(1, sender->last_message_proto().histogram_event().size());
- EXPECT_EQ(name, sender_->last_message_proto().system_profile().os().name());
EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_BETA,
- sender_->last_message_proto().system_profile().channel());
- EXPECT_NE(0, sender_->last_message_proto().client_id());
- EXPECT_NE(0,
- sender_->last_message_proto().system_profile().build_timestamp());
- EXPECT_NE(0, sender_->last_message_proto().session_id());
+ sender->last_message_proto().system_profile().channel());
+ EXPECT_NE(0, sender->last_message_proto().client_id());
+ EXPECT_NE(0, sender->last_message_proto().system_profile().build_timestamp());
+ EXPECT_NE(0, sender->last_message_proto().session_id());
}
TEST_F(UploadServiceTest, PersistentGUID) {
@@ -252,15 +261,11 @@
}
TEST_F(UploadServiceTest, SessionIdIncrementedAtInitialization) {
- cache_.Initialize();
- int session_id = cache_.profile_.session_id;
- cache_.initialized_ = false;
- cache_.Initialize();
- EXPECT_EQ(cache_.profile_.session_id, session_id + 1);
-}
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
-
- return RUN_ALL_TESTS();
+ SetTestingProperty(metrics::kBuildTargetIdProperty, "hello");
+ SystemProfileCache cache(true, dir_.path());
+ cache.Initialize();
+ int session_id = cache.profile_.session_id;
+ cache.initialized_ = false;
+ cache.Initialize();
+ EXPECT_EQ(cache.profile_.session_id, session_id + 1);
}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index d2d13f6..1d3605e 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -52,7 +52,6 @@
start \
stop \
top \
- uptime \
ALL_TOOLS = $(BSD_TOOLS) $(OUR_TOOLS)
diff --git a/toolbox/uptime.c b/toolbox/uptime.c
deleted file mode 100644
index ebfb15e..0000000
--- a/toolbox/uptime.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2010, The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-static void format_time(int time, char* buffer) {
- int seconds = time % 60;
- time /= 60;
- int minutes = time % 60;
- time /= 60;
- int hours = time % 24;
- int days = time / 24;
-
- if (days > 0) {
- sprintf(buffer, "%d day%s, %02d:%02d:%02d", days, (days == 1) ? "" : "s", hours, minutes, seconds);
- } else {
- sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
- }
-}
-
-int uptime_main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) {
- FILE* file = fopen("/proc/uptime", "r");
- if (!file) {
- fprintf(stderr, "Could not open /proc/uptime\n");
- return -1;
- }
- float idle_time;
- if (fscanf(file, "%*f %f", &idle_time) != 1) {
- fprintf(stderr, "Could not parse /proc/uptime\n");
- fclose(file);
- return -1;
- }
- fclose(file);
-
- struct timespec up_timespec;
- if (clock_gettime(CLOCK_MONOTONIC, &up_timespec) == -1) {
- fprintf(stderr, "Could not get monotonic time: %s\n", strerror(errno));
- return -1;
- }
- float up_time = up_timespec.tv_sec + up_timespec.tv_nsec / 1e9;
-
- struct timespec elapsed_timespec;
- if (clock_gettime(CLOCK_BOOTTIME, &elapsed_timespec) == -1) {
- fprintf(stderr, "Could not get boot time: %s\n", strerror(errno));
- return -1;
- }
- int elapsed = elapsed_timespec.tv_sec;
-
- char up_string[100], idle_string[100], sleep_string[100];
- format_time(elapsed, up_string);
- format_time((int)idle_time, idle_string);
- format_time((int)(elapsed - up_time), sleep_string);
- printf("up time: %s, idle time: %s, sleep time: %s\n", up_string, idle_string, sleep_string);
-
- return 0;
-}