Merge "Invoke perfprofd daemon (only for userdebug/eng builds)."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index de82cd4..e526914 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -33,6 +33,7 @@
#include <string>
#include <base/stringprintf.h>
+#include <base/strings.h>
#include "adb_auth.h"
#include "adb_io.h"
@@ -381,87 +382,64 @@
}
#endif // ADB_HOST
-/* qual_overwrite is used to overwrite a qualifier string. dst is a
- * pointer to a char pointer. It is assumed that if *dst is non-NULL, it
- * was malloc'ed and needs to freed. *dst will be set to a dup of src.
- */
-static void qual_overwrite(char **dst, const char *src)
-{
- if (!dst)
- return;
-
+// qual_overwrite is used to overwrite a qualifier string. dst is a
+// pointer to a char pointer. It is assumed that if *dst is non-NULL, it
+// was malloc'ed and needs to freed. *dst will be set to a dup of src.
+// TODO: switch to std::string for these atransport fields instead.
+static void qual_overwrite(char** dst, const std::string& src) {
free(*dst);
- *dst = NULL;
-
- if (!src || !*src)
- return;
-
- *dst = strdup(src);
+ *dst = strdup(src.c_str());
}
-void parse_banner(char *banner, atransport *t)
-{
- static const char *prop_seps = ";";
- static const char key_val_sep = '=';
- char *cp;
- char *type;
-
+void parse_banner(const char* banner, atransport* t) {
D("parse_banner: %s\n", banner);
- type = banner;
- cp = strchr(type, ':');
- if (cp) {
- *cp++ = 0;
- /* Nothing is done with second field. */
- cp = strchr(cp, ':');
- if (cp) {
- char *save;
- char *key;
- key = adb_strtok_r(cp + 1, prop_seps, &save);
- while (key) {
- cp = strchr(key, key_val_sep);
- if (cp) {
- *cp++ = '\0';
- if (!strcmp(key, "ro.product.name"))
- qual_overwrite(&t->product, cp);
- else if (!strcmp(key, "ro.product.model"))
- qual_overwrite(&t->model, cp);
- else if (!strcmp(key, "ro.product.device"))
- qual_overwrite(&t->device, cp);
- }
- key = adb_strtok_r(NULL, prop_seps, &save);
+
+ // The format is something like:
+ // "device::ro.product.name=x;ro.product.model=y;ro.product.device=z;".
+ std::vector<std::string> pieces = android::base::Split(banner, ":");
+
+ if (pieces.size() > 2) {
+ const std::string& props = pieces[2];
+ for (auto& prop : android::base::Split(props, ";")) {
+ // The list of properties was traditionally ;-terminated rather than ;-separated.
+ if (prop.empty()) continue;
+
+ std::vector<std::string> key_value = android::base::Split(prop, "=");
+ if (key_value.size() != 2) continue;
+
+ const std::string& key = key_value[0];
+ const std::string& value = key_value[1];
+ if (key == "ro.product.name") {
+ qual_overwrite(&t->product, value);
+ } else if (key == "ro.product.model") {
+ qual_overwrite(&t->model, value);
+ } else if (key == "ro.product.device") {
+ qual_overwrite(&t->device, value);
}
}
}
- if(!strcmp(type, "bootloader")){
+ const std::string& type = pieces[0];
+ if (type == "bootloader") {
D("setting connection_state to CS_BOOTLOADER\n");
t->connection_state = CS_BOOTLOADER;
update_transports();
- return;
- }
-
- if(!strcmp(type, "device")) {
+ } else if (type == "device") {
D("setting connection_state to CS_DEVICE\n");
t->connection_state = CS_DEVICE;
update_transports();
- return;
- }
-
- if(!strcmp(type, "recovery")) {
+ } else if (type == "recovery") {
D("setting connection_state to CS_RECOVERY\n");
t->connection_state = CS_RECOVERY;
update_transports();
- return;
- }
-
- if(!strcmp(type, "sideload")) {
+ } else if (type == "sideload") {
D("setting connection_state to CS_SIDELOAD\n");
t->connection_state = CS_SIDELOAD;
update_transports();
- return;
+ } else {
+ D("setting connection_state to CS_HOST\n");
+ t->connection_state = CS_HOST;
}
-
- t->connection_state = CS_HOST;
}
void handle_packet(apacket *p, atransport *t)
@@ -493,7 +471,7 @@
handle_offline(t);
}
- parse_banner((char*) p->data, t);
+ parse_banner(reinterpret_cast<const char*>(p->data), t);
if (HOST || !auth_enabled) {
handle_online(t);
diff --git a/adb/adb.h b/adb/adb.h
index cb2cf60..b8c6156 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -243,8 +243,6 @@
void remove_socket(asocket *s);
void close_all_sockets(atransport *t);
-#define LOCAL_CLIENT_PREFIX "emulator-"
-
asocket *create_local_socket(int fd);
asocket *create_local_service_socket(const char *destination);
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 7c2bcfb..510dcc2 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -43,6 +43,7 @@
#include "mincrypt/rsa.h"
#undef RSA_verify
+#include <base/strings.h>
#include <cutils/list.h>
#include <openssl/evp.h>
@@ -172,7 +173,7 @@
return 0;
}
- outfile = fopen(path, "w");
+ outfile = fopen(path, "we");
if (!outfile) {
D("Failed to open '%s'\n", path);
return 0;
@@ -191,7 +192,7 @@
encoded_length = 1 + ((sizeof(pkey) + 2) / 3 * 4);
#endif
- encoded = reinterpret_cast<uint8_t*>(malloc(encoded_length));
+ encoded = new uint8_t[encoded_length];
if (encoded == nullptr) {
D("Allocation failure");
goto out;
@@ -212,9 +213,7 @@
if (outfile != NULL) {
fclose(outfile);
}
- if (encoded != NULL) {
- free(encoded);
- }
+ delete[] encoded;
return ret;
}
@@ -240,7 +239,7 @@
old_mask = umask(077);
- f = fopen(file, "w");
+ f = fopen(file, "we");
if (!f) {
D("Failed to open '%s'\n", file);
umask(old_mask);
@@ -274,30 +273,24 @@
{
D("read_key '%s'\n", file);
- FILE* f = fopen(file, "r");
- if (!f) {
- D("Failed to open '%s'\n", file);
+ FILE* fp = fopen(file, "re");
+ if (!fp) {
+ D("Failed to open '%s': %s\n", file, strerror(errno));
return 0;
}
- adb_private_key* key = reinterpret_cast<adb_private_key*>(
- malloc(sizeof(adb_private_key)));
- if (!key) {
- D("Failed to alloc key\n");
- fclose(f);
- return 0;
- }
+ adb_private_key* key = new adb_private_key;
key->rsa = RSA_new();
- if (!PEM_read_RSAPrivateKey(f, &key->rsa, NULL, NULL)) {
+ if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
D("Failed to read key\n");
- fclose(f);
+ fclose(fp);
RSA_free(key->rsa);
- free(key);
+ delete key;
return 0;
}
- fclose(f);
+ fclose(fp);
list_add_tail(list, &key->node);
return 1;
}
@@ -362,29 +355,16 @@
return read_key(path, list);
}
-static void get_vendor_keys(struct listnode *list)
-{
- const char *adb_keys_path;
- char keys_path[MAX_PAYLOAD];
- char *path;
- char *save;
- struct stat buf;
-
- adb_keys_path = getenv("ADB_VENDOR_KEYS");
- if (!adb_keys_path)
+static void get_vendor_keys(struct listnode* key_list) {
+ const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
+ if (adb_keys_path == nullptr) {
return;
- strncpy(keys_path, adb_keys_path, sizeof(keys_path));
+ }
- path = adb_strtok_r(keys_path, ENV_PATH_SEPARATOR_STR, &save);
- while (path) {
- D("Reading: '%s'\n", path);
-
- if (stat(path, &buf))
- D("Can't read '%s'\n", path);
- else if (!read_key(path, list))
- D("Failed to read '%s'\n", path);
-
- path = adb_strtok_r(NULL, ENV_PATH_SEPARATOR_STR, &save);
+ 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());
+ }
}
}
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 0f64998..62f79fa 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -29,6 +29,10 @@
#include <sys/types.h>
#include <string>
+#include <vector>
+
+#include <base/stringprintf.h>
+#include <base/strings.h>
#include "adb_io.h"
@@ -38,6 +42,29 @@
static int __adb_server_port = DEFAULT_ADB_PORT;
static const char* __adb_server_name = NULL;
+static std::string perror_str(const char* msg) {
+ return android::base::StringPrintf("%s: %s", msg, strerror(errno));
+}
+
+static bool ReadProtocolString(int fd, std::string* s, std::string* error) {
+ char buf[5];
+
+ if (!ReadFdExactly(fd, buf, 4)) {
+ *error = perror_str("protocol fault (couldn't read status length)");
+ return false;
+ }
+ buf[4] = 0;
+
+ unsigned long len = strtoul(buf, 0, 16);
+ s->resize(len + 1, '\0'); // Ensure NUL-termination.
+ if (!ReadFdExactly(fd, &(*s)[0], len)) {
+ *error = perror_str("protocol fault (couldn't read status message)");
+ return false;
+ }
+
+ return true;
+}
+
void adb_set_transport(transport_type type, const char* serial)
{
__adb_transport = type;
@@ -54,62 +81,37 @@
__adb_server_name = hostname;
}
-int adb_get_emulator_console_port(void)
-{
- const char* serial = __adb_serial;
- int port;
+int adb_get_emulator_console_port() {
+ if (__adb_serial) {
+ // The user specified a serial number; is it an emulator?
+ int port;
+ return (sscanf(__adb_serial, "emulator-%d", &port) == 1) ? port : -1;
+ }
- if (serial == NULL) {
- /* if no specific device was specified, we need to look at */
- /* the list of connected devices, and extract an emulator */
- /* name from it. two emulators is an error */
- char* tmp = adb_query("host:devices");
- char* p = tmp;
- if(!tmp) {
- printf("no emulator connected\n");
- return -1;
- }
- while (*p) {
- char* q = strchr(p, '\n');
- if (q != NULL)
- *q++ = 0;
- else
- q = p + strlen(p);
+ // No specific device was given, so get the list of connected
+ // devices and search for emulators. If there's one, we'll
+ // take it. If there are more than one, that's an error.
+ std::string devices;
+ std::string error;
+ if (!adb_query("host:devices", &devices, &error)) {
+ printf("no emulator connected: %s\n", error.c_str());
+ return -1;
+ }
- if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
- if (serial != NULL) { /* more than one emulator listed */
- free(tmp);
- return -2;
- }
- serial = p;
+ int port;
+ size_t emulator_count = 0;
+ for (auto& device : android::base::Split(devices, "\n")) {
+ if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
+ if (++emulator_count > 1) {
+ return -2;
}
-
- p = q;
}
- free(tmp);
-
- if (serial == NULL)
- return -1; /* no emulator found */
}
- else {
- if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
- return -1; /* not an emulator */
- }
-
- serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
- port = strtol(serial, NULL, 10);
+ if (emulator_count == 0) return -1;
return port;
}
-static char __adb_error[256] = { 0 };
-
-const char *adb_error(void)
-{
- return __adb_error;
-}
-
-static int switch_socket_transport(int fd)
-{
+static int switch_socket_transport(int fd, std::string* error) {
std::string service;
if (__adb_serial) {
service += "host:transport:";
@@ -137,92 +139,75 @@
char tmp[5];
snprintf(tmp, sizeof(tmp), "%04zx", service.size());
if (!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service.c_str(), service.size())) {
- strcpy(__adb_error, "write failure during connection");
+ *error = perror_str("write failure during connection");
adb_close(fd);
return -1;
}
D("Switch transport in progress\n");
- if (adb_status(fd)) {
+ if (!adb_status(fd, error)) {
adb_close(fd);
- D("Switch transport failed\n");
+ D("Switch transport failed: %s\n", error->c_str());
return -1;
}
D("Switch transport success\n");
return 0;
}
-int adb_status(int fd)
-{
- unsigned char buf[5];
- unsigned len;
+bool adb_status(int fd, std::string* error) {
+ char buf[5];
- if(!ReadFdExactly(fd, buf, 4)) {
- strcpy(__adb_error, "protocol fault (no status)");
- return -1;
+ if (!ReadFdExactly(fd, buf, 4)) {
+ *error = perror_str("protocol fault (couldn't read status)");
+ return false;
}
- if(!memcmp(buf, "OKAY", 4)) {
- return 0;
+ if (!memcmp(buf, "OKAY", 4)) {
+ return true;
}
- if(memcmp(buf, "FAIL", 4)) {
- sprintf(__adb_error,
- "protocol fault (status %02x %02x %02x %02x?!)",
- buf[0], buf[1], buf[2], buf[3]);
- return -1;
+ if (memcmp(buf, "FAIL", 4)) {
+ *error = android::base::StringPrintf("protocol fault (status %02x %02x %02x %02x?!)",
+ buf[0], buf[1], buf[2], buf[3]);
+ return false;
}
- if(!ReadFdExactly(fd, buf, 4)) {
- strcpy(__adb_error, "protocol fault (status len)");
- return -1;
- }
- buf[4] = 0;
- len = strtoul((char*)buf, 0, 16);
- if(len > 255) len = 255;
- if(!ReadFdExactly(fd, __adb_error, len)) {
- strcpy(__adb_error, "protocol fault (status read)");
- return -1;
- }
- __adb_error[len] = 0;
- return -1;
+ ReadProtocolString(fd, error, error);
+ return false;
}
-int _adb_connect(const char *service)
-{
- char tmp[5];
- int len;
- int fd;
-
- D("_adb_connect: %s\n", service);
- len = strlen(service);
- if((len < 1) || (len > 1024)) {
- strcpy(__adb_error, "service name too long");
+int _adb_connect(const std::string& service, std::string* error) {
+ D("_adb_connect: %s\n", service.c_str());
+ if (service.empty() || service.size() > 1024) {
+ *error = android::base::StringPrintf("bad service name length (%d)",
+ static_cast<int>(service.size()));
return -1;
}
- snprintf(tmp, sizeof tmp, "%04x", len);
- if (__adb_server_name)
+ int fd;
+ if (__adb_server_name) {
fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
- else
+ } else {
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
-
- if(fd < 0) {
- strcpy(__adb_error, "cannot connect to daemon");
+ }
+ if (fd < 0) {
+ *error = perror_str("cannot connect to daemon");
return -2;
}
- if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
+ if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
return -1;
}
- if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
- strcpy(__adb_error, "write failure during connection");
+ char tmp[5];
+ snprintf(tmp, sizeof(tmp), "%04zx", service.size());
+ if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, &service[0], service.size())) {
+ *error = perror_str("write failure during connection");
adb_close(fd);
return -1;
}
- if(adb_status(fd)) {
+ if (!adb_status(fd, error)) {
adb_close(fd);
return -1;
}
@@ -231,20 +216,19 @@
return fd;
}
-int adb_connect(const char *service)
-{
+int adb_connect(const std::string& service, std::string* error) {
// first query the adb server's version
- int fd = _adb_connect("host:version");
+ int fd = _adb_connect("host:version", error);
- D("adb_connect: service %s\n", service);
- if(fd == -2 && __adb_server_name) {
+ D("adb_connect: service %s\n", service.c_str());
+ if (fd == -2 && __adb_server_name) {
fprintf(stderr,"** Cannot start server on remote host\n");
return fd;
- } else if(fd == -2) {
+ } else if (fd == -2) {
fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
__adb_server_port);
start_server:
- if(launch_server(__adb_server_port)) {
+ if (launch_server(__adb_server_port)) {
fprintf(stderr,"* failed to start daemon *\n");
return -1;
} else {
@@ -255,31 +239,31 @@
// fall through to _adb_connect
} else {
// if server was running, check its version to make sure it is not out of date
- char buf[100];
- size_t n;
int version = ADB_SERVER_VERSION - 1;
// if we have a file descriptor, then parse version result
- if(fd >= 0) {
- if(!ReadFdExactly(fd, buf, 4)) goto error;
+ if (fd >= 0) {
+ std::string version_string;
+ if (!ReadProtocolString(fd, &version_string, error)) {
+ goto error;
+ }
- buf[4] = 0;
- n = strtoul(buf, 0, 16);
- if(n > sizeof(buf)) goto error;
- if(!ReadFdExactly(fd, buf, n)) goto error;
adb_close(fd);
- if (sscanf(buf, "%04x", &version) != 1) goto error;
+ if (sscanf(&version_string[0], "%04x", &version) != 1) {
+ goto error;
+ }
} else {
// if fd is -1, then check for "unknown host service",
// which would indicate a version of adb that does not support the version command
- if (strcmp(__adb_error, "unknown host service") != 0)
+ if (*error == "unknown host service") {
return fd;
+ }
}
- if(version != ADB_SERVER_VERSION) {
+ if (version != ADB_SERVER_VERSION) {
printf("adb server is out of date. killing...\n");
- fd = _adb_connect("host:kill");
+ fd = _adb_connect("host:kill", error);
adb_close(fd);
/* XXX can we better detect its death? */
@@ -289,12 +273,13 @@
}
// if the command is start-server, we are done.
- if (!strcmp(service, "host:start-server"))
+ if (service == "host:start-server") {
return 0;
+ }
- fd = _adb_connect(service);
- if(fd == -1) {
- D("_adb_connect error: %s", __adb_error);
+ fd = _adb_connect(service, error);
+ if (fd == -1) {
+ D("_adb_connect error: %s", error->c_str());
} else if(fd == -2) {
fprintf(stderr,"** daemon still not running\n");
}
@@ -307,15 +292,14 @@
}
-int adb_command(const char *service)
-{
- int fd = adb_connect(service);
- if(fd < 0) {
- fprintf(stderr, "error: %s\n", adb_error());
+int adb_command(const std::string& service, std::string* error) {
+ int fd = adb_connect(service, error);
+ if (fd < 0) {
+ fprintf(stderr, "error: %s\n", error->c_str());
return -1;
}
- if(adb_status(fd)) {
+ if (!adb_status(fd, error)) {
adb_close(fd);
return -1;
}
@@ -323,39 +307,18 @@
return 0;
}
-char *adb_query(const char *service)
-{
- char buf[5];
- unsigned long n;
- char* tmp;
-
- D("adb_query: %s\n", service);
- int fd = adb_connect(service);
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", __adb_error);
+bool adb_query(const std::string& service, std::string* result, std::string* error) {
+ D("adb_query: %s\n", service.c_str());
+ int fd = adb_connect(service, error);
+ if (fd < 0) {
+ fprintf(stderr,"error: %s\n", error->c_str());
return 0;
}
- if(!ReadFdExactly(fd, buf, 4)) goto oops;
-
- buf[4] = 0;
- n = strtoul(buf, 0, 16);
- if(n >= 0xffff) {
- strcpy(__adb_error, "reply is too long (>= 64kB)");
- goto oops;
- }
-
- tmp = reinterpret_cast<char*>(malloc(n + 1));
- if(tmp == 0) goto oops;
-
- if(!ReadFdExactly(fd, tmp, n) == 0) {
- tmp[n] = 0;
+ result->clear();
+ if (!ReadProtocolString(fd, result, error)) {
adb_close(fd);
- return tmp;
+ return false;
}
- free(tmp);
-
-oops:
- adb_close(fd);
- return 0;
+ return true;
}
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 934362a..96416f5 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -3,23 +3,23 @@
#include "adb.h"
+#include <string>
+
/* connect to adb, connect to the named service, and return
** a valid fd for interacting with that service upon success
** or a negative number on failure
*/
-int adb_connect(const char *service);
-int _adb_connect(const char *service);
+int adb_connect(const std::string& service, std::string* error);
+int _adb_connect(const std::string& service, std::string* error);
/* connect to adb, connect to the named service, return 0 if
** the connection succeeded AND the service returned OKAY
*/
-int adb_command(const char *service);
+int adb_command(const std::string& service, std::string* error);
-/* connect to adb, connect to the named service, return
-** a malloc'd string of its response upon success or NULL
-** on failure.
-*/
-char *adb_query(const char *service);
+// Connects to the named adb service and fills 'result' with the response.
+// Returns true on success; returns false and fills 'error' on failure.
+bool adb_query(const std::string& service, std::string* result, std::string* error);
/* Set the preferred transport to connect to.
*/
@@ -45,13 +45,9 @@
*/
int adb_send_emulator_command(int argc, const char** argv);
-/* return verbose error string from last operation */
-const char *adb_error(void);
-
-/* read a standard adb status response (OKAY|FAIL) and
-** return 0 in the event of OKAY, -1 in the event of FAIL
-** or protocol error
-*/
-int adb_status(int fd);
+// Reads a standard adb status response (OKAY|FAIL) and
+// returns true in the event of OKAY, false in the event of FAIL
+// or protocol error.
+bool adb_status(int fd, std::string* error);
#endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index e59a96a..4941689 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -201,7 +201,6 @@
" adb get-state - prints: offline | bootloader | device\n"
" adb get-serialno - prints: <serial-number>\n"
" adb get-devpath - prints: <device-path>\n"
- " adb status-window - continuously print device status for a specified device\n"
" adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
" adb reboot [bootloader|recovery]\n"
" - reboots the device, optionally into the bootloader or recovery program.\n"
@@ -410,11 +409,12 @@
static int interactive_shell() {
adb_thread_t thr;
- int fdi, fd;
+ int fdi;
- fd = adb_connect("shell:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", adb_error());
+ std::string error;
+ int fd = adb_connect("shell:", &error);
+ if (fd < 0) {
+ fprintf(stderr,"error: %s\n", error.c_str());
return 1;
}
fdi = 0; //dup(0);
@@ -436,64 +436,62 @@
}
-static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
-{
+static std::string format_host_command(const char* command, transport_type type, const char* serial) {
if (serial) {
- snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
- } else {
- const char* prefix = "host";
- if (ttype == kTransportUsb)
- prefix = "host-usb";
- else if (ttype == kTransportLocal)
- prefix = "host-local";
-
- snprintf(buffer, buflen, "%s:%s", prefix, command);
+ return android::base::StringPrintf("host-serial:%s:%s", serial, command);
}
+
+ const char* prefix = "host";
+ if (type == kTransportUsb) {
+ prefix = "host-usb";
+ } else if (type == kTransportLocal) {
+ prefix = "host-local";
+ }
+ return android::base::StringPrintf("%s:%s", prefix, command);
}
-static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
- unsigned progress)
+static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
+ bool show_progress)
{
- char buf[4096];
- unsigned total;
- int fd;
-
- sprintf(buf,"%s:%d", service, sz);
- fd = adb_connect(buf);
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", adb_error());
+ std::string error;
+ int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
+ if (fd < 0) {
+ fprintf(stderr,"error: %s\n", error.c_str());
return -1;
}
int opt = CHUNK_SIZE;
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
- total = sz;
+ unsigned total = sz;
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
- if(progress) {
+ if (show_progress) {
char *x = strrchr(service, ':');
if(x) service = x + 1;
}
- while(sz > 0) {
+ while (sz > 0) {
unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
- if(!WriteFdExactly(fd, ptr, xfer)) {
- adb_status(fd);
- fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+ if (!WriteFdExactly(fd, ptr, xfer)) {
+ std::string error;
+ adb_status(fd, &error);
+ fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
return -1;
}
sz -= xfer;
ptr += xfer;
- if(progress) {
+ if (show_progress) {
printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
fflush(stdout);
}
}
- if(progress) {
+ if (show_progress) {
printf("\n");
}
+ // TODO: should this be adb_status?
+ char buf[5];
if(!ReadFdExactly(fd, buf, 4)){
fprintf(stderr,"* error reading response *\n");
adb_close(fd);
@@ -547,37 +545,39 @@
return -1;
}
- char buf[100];
- sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
- int fd = adb_connect(buf);
+ std::string service =
+ android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
+ std::string error;
+ int fd = adb_connect(service, &error);
if (fd < 0) {
// Try falling back to the older sideload method. Maybe this
// is an older device that doesn't support sideload-host.
printf("\n");
- status = adb_download_buffer("sideload", fn, data, sz, 1);
+ status = adb_download_buffer("sideload", fn, data, sz, true);
goto done;
}
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
while (true) {
+ char buf[9];
if (!ReadFdExactly(fd, buf, 8)) {
- fprintf(stderr, "* failed to read command: %s\n", adb_error());
+ fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
status = -1;
goto done;
}
+ buf[8] = '\0';
- if (strncmp("DONEDONE", buf, 8) == 0) {
+ if (strcmp("DONEDONE", buf) == 0) {
status = 0;
break;
}
- buf[8] = '\0';
int block = strtol(buf, NULL, 10);
size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
if (offset >= sz) {
- fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
+ fprintf(stderr, "* attempt to read block %d past end\n", block);
status = -1;
goto done;
}
@@ -589,8 +589,8 @@
}
if(!WriteFdExactly(fd, start, to_write)) {
- adb_status(fd);
- fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+ adb_status(fd, &error);
+ fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
status = -1;
goto done;
}
@@ -618,50 +618,6 @@
return status;
}
-static void status_window(transport_type ttype, const char* serial)
-{
- char command[4096];
- char *state = 0;
- char *laststate = 0;
-
- /* silence stderr */
-#ifdef _WIN32
- /* XXX: TODO */
-#else
- int fd;
- fd = unix_open("/dev/null", O_WRONLY);
- dup2(fd, 2);
- adb_close(fd);
-#endif
-
- format_host_command(command, sizeof command, "get-state", ttype, serial);
-
- for(;;) {
- adb_sleep_ms(250);
-
- if(state) {
- free(state);
- state = 0;
- }
-
- state = adb_query(command);
-
- if(state) {
- if(laststate && !strcmp(state,laststate)){
- continue;
- } else {
- if(laststate) free(laststate);
- laststate = strdup(state);
- }
- }
-
- printf("%c[2J%c[2H", 27, 27);
- printf("Android Debug Bridge\n");
- printf("State: %s\n", state ? state : "offline");
- fflush(stdout);
- }
-}
-
/**
* Run ppp in "notty" mode against a resource listed as the first parameter
* eg:
@@ -674,9 +630,6 @@
fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
return -1;
#else
- pid_t pid;
- int fd;
-
if (argc < 2) {
fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
argv[0]);
@@ -685,15 +638,15 @@
}
const char* adb_service_name = argv[1];
- fd = adb_connect(adb_service_name);
-
- if(fd < 0) {
+ std::string error;
+ int fd = adb_connect(adb_service_name, &error);
+ if (fd < 0) {
fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
- adb_service_name, adb_error());
+ adb_service_name, error.c_str());
return 1;
}
- pid = fork();
+ pid_t pid = fork();
if (pid < 0) {
perror("from fork()");
@@ -738,9 +691,11 @@
const std::string& command) {
int fd;
while (true) {
- fd = adb_connect(command.c_str());
- if (fd >= 0)
+ std::string error;
+ fd = adb_connect(command, &error);
+ if (fd >= 0) {
break;
+ }
fprintf(stderr,"- waiting for device -\n");
adb_sleep_ms(1000);
do_cmd(transport, serial, "wait-for-device", 0);
@@ -830,9 +785,10 @@
}
D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
- int fd = adb_connect(cmd.c_str());
+ std::string error;
+ int fd = adb_connect(cmd, &error);
if (fd < 0) {
- fprintf(stderr, "adb: unable to connect for backup\n");
+ fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
adb_close(outFd);
return -1;
}
@@ -846,21 +802,19 @@
}
static int restore(int argc, const char** argv) {
- const char* filename;
- int fd, tarFd;
-
if (argc != 2) return usage();
- filename = argv[1];
- tarFd = adb_open(filename, O_RDONLY);
+ const char* filename = argv[1];
+ int tarFd = adb_open(filename, O_RDONLY);
if (tarFd < 0) {
- fprintf(stderr, "adb: unable to open file %s\n", filename);
+ fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
return -1;
}
- fd = adb_connect("restore:");
+ std::string error;
+ int fd = adb_connect("restore:", &error);
if (fd < 0) {
- fprintf(stderr, "adb: unable to connect for restore\n");
+ fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
adb_close(tarFd);
return -1;
}
@@ -961,17 +915,29 @@
}
}
-static int adb_connect_command(const char* command) {
- int fd = adb_connect(command);
+static int adb_connect_command(const std::string& command) {
+ std::string error;
+ int fd = adb_connect(command, &error);
if (fd != -1) {
read_and_dump(fd);
adb_close(fd);
return 0;
}
- fprintf(stderr, "Error: %s\n", adb_error());
+ fprintf(stderr, "Error: %s\n", error.c_str());
return 1;
}
+static int adb_query_command(const std::string& command) {
+ std::string result;
+ std::string error;
+ if (!adb_query(command, &result, &error)) {
+ fprintf(stderr, "error: %s\n", error.c_str());
+ return 1;
+ }
+ printf("%s\n", result.c_str());
+ return 0;
+}
+
int adb_commandline(int argc, const char **argv)
{
char buf[4096];
@@ -1125,11 +1091,11 @@
}
}
- format_host_command(buf, sizeof buf, service, ttype, serial);
-
- if (adb_command(buf)) {
- D("failure: %s *\n",adb_error());
- fprintf(stderr,"error: %s\n", adb_error());
+ std::string cmd = format_host_command(service, ttype, serial);
+ std::string error;
+ if (adb_command(cmd, &error)) {
+ D("failure: %s *\n", error.c_str());
+ fprintf(stderr,"error: %s\n", error.c_str());
return 1;
}
@@ -1147,59 +1113,38 @@
/* adb_connect() commands */
if (!strcmp(argv[0], "devices")) {
- char *tmp;
const char *listopt;
- if (argc < 2)
+ if (argc < 2) {
listopt = "";
- else if (argc == 2 && !strcmp(argv[1], "-l"))
+ } else if (argc == 2 && !strcmp(argv[1], "-l")) {
listopt = argv[1];
- else {
+ } else {
fprintf(stderr, "Usage: adb devices [-l]\n");
return 1;
}
- snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
- tmp = adb_query(buf);
- if (tmp) {
- printf("List of devices attached \n");
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+
+ std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
+ printf("List of devices attached\n");
+ return adb_query_command(query);
}
else if (!strcmp(argv[0], "connect")) {
- char *tmp;
if (argc != 2) {
fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
return 1;
}
- snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
- tmp = adb_query(buf);
- if (tmp) {
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+
+ std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
+ return adb_query_command(query);
}
else if (!strcmp(argv[0], "disconnect")) {
- char *tmp;
if (argc > 2) {
fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
return 1;
}
- if (argc == 2) {
- snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
- } else {
- snprintf(buf, sizeof buf, "host:disconnect:");
- }
- tmp = adb_query(buf);
- if (tmp) {
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+
+ std::string query = android::base::StringPrintf("host:disconnect:%s",
+ (argc == 2) ? argv[1] : "");
+ return adb_query_command(query);
}
else if (!strcmp(argv[0], "emu")) {
return adb_send_emulator_command(argc, argv);
@@ -1232,7 +1177,8 @@
while (true) {
D("interactive shell loop. cmd=%s\n", cmd.c_str());
- int fd = adb_connect(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);
@@ -1241,7 +1187,7 @@
adb_close(fd);
r = 0;
} else {
- fprintf(stderr,"error: %s\n", adb_error());
+ fprintf(stderr,"error: %s\n", error.c_str());
r = -1;
}
@@ -1270,9 +1216,10 @@
cmd += " " + escape_arg(*argv++);
}
- int fd = adb_connect(cmd.c_str());
+ std::string error;
+ int fd = adb_connect(cmd, &error);
if (fd < 0) {
- fprintf(stderr, "error: %s\n", adb_error());
+ fprintf(stderr, "error: %s\n", error.c_str());
return -1;
}
@@ -1286,8 +1233,8 @@
return 0;
}
else if (!strcmp(argv[0], "kill-server")) {
- int fd;
- fd = _adb_connect("host:kill");
+ std::string error;
+ int fd = _adb_connect("host:kill", &error);
if (fd == -1) {
fprintf(stderr,"* server not running *\n");
return 1;
@@ -1375,17 +1322,12 @@
// Implement forward --list
if (list) {
- if (argc != 1)
+ if (argc != 1) {
return usage();
- snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
- char* forwards = adb_query(buf);
- if (forwards == NULL) {
- fprintf(stderr, "error: %s\n", adb_error());
- return 1;
}
- printf("%s", forwards);
- free(forwards);
- return 0;
+
+ std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
+ return adb_query_command(query);
}
// Implement forward --remove-all
@@ -1412,8 +1354,9 @@
snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
}
- if (adb_command(buf)) {
- fprintf(stderr,"error: %s\n", adb_error());
+ std::string error;
+ if (adb_command(buf, &error)) {
+ fprintf(stderr,"error: %s\n", error.c_str());
return 1;
}
return 0;
@@ -1511,22 +1454,9 @@
!strcmp(argv[0],"get-serialno") ||
!strcmp(argv[0],"get-devpath"))
{
- char *tmp;
-
- format_host_command(buf, sizeof buf, argv[0], ttype, serial);
- tmp = adb_query(buf);
- if (tmp) {
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+ return adb_query_command(format_host_command(argv[0], ttype, serial));
}
/* other commands */
- else if (!strcmp(argv[0],"status-window")) {
- status_window(ttype, serial);
- return 0;
- }
else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
return logcat(ttype, serial, argc, argv);
}
@@ -1534,7 +1464,8 @@
return ppp(argc, argv);
}
else if (!strcmp(argv[0], "start-server")) {
- return adb_connect("host:start-server");
+ std::string error;
+ return adb_connect("host:start-server", &error);
}
else if (!strcmp(argv[0], "backup")) {
return backup(argc, argv);
@@ -1742,9 +1673,10 @@
}
// Create install session
- int fd = adb_connect(cmd.c_str());
+ std::string error;
+ int fd = adb_connect(cmd, &error);
if (fd < 0) {
- fprintf(stderr, "Connect error for create: %s\n", adb_error());
+ fprintf(stderr, "Connect error for create: %s\n", error.c_str());
return -1;
}
char buf[BUFSIZ];
@@ -1788,14 +1720,15 @@
int localFd = adb_open(file, O_RDONLY);
if (localFd < 0) {
- fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
+ fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
success = 0;
goto finalize_session;
}
- int remoteFd = adb_connect(cmd.c_str());
+ std::string error;
+ int remoteFd = adb_connect(cmd, &error);
if (remoteFd < 0) {
- fprintf(stderr, "Connect error for write: %s\n", adb_error());
+ fprintf(stderr, "Connect error for write: %s\n", error.c_str());
adb_close(localFd);
success = 0;
goto finalize_session;
@@ -1817,15 +1750,12 @@
finalize_session:
// Commit session if we streamed everything okay; otherwise abandon
- if (success) {
- snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
- } else {
- snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
- }
-
- fd = adb_connect(buf);
+ std::string service =
+ android::base::StringPrintf("exec:pm install-%s %d",
+ success ? "commit" : "abandon", session_id);
+ fd = adb_connect(service, &error);
if (fd < 0) {
- fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
+ fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
return -1;
}
read_status_line(fd, buf, sizeof(buf));
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 49d8783..aded301 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -539,11 +539,11 @@
printf("%08x %08x %08x %s\n", mode, size, time, name);
}
-int do_sync_ls(const char *path)
-{
- int fd = adb_connect("sync:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", adb_error());
+int do_sync_ls(const char* path) {
+ std::string error;
+ int fd = adb_connect("sync:", &error);
+ if (fd < 0) {
+ fprintf(stderr,"error: %s\n", error.c_str());
return 1;
}
@@ -743,11 +743,11 @@
{
struct stat st;
unsigned mode;
- int fd;
- fd = adb_connect("sync:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", adb_error());
+ std::string error;
+ int fd = adb_connect("sync:", &error);
+ if (fd < 0) {
+ fprintf(stderr,"error: %s\n", error.c_str());
return 1;
}
@@ -967,11 +967,10 @@
unsigned mode, time;
struct stat st;
- int fd;
-
- fd = adb_connect("sync:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", adb_error());
+ std::string error;
+ int fd = adb_connect("sync:", &error);
+ if (fd < 0) {
+ fprintf(stderr,"error: %s\n", error.c_str());
return 1;
}
@@ -1031,9 +1030,10 @@
{
fprintf(stderr, "syncing %s...\n", rpath.c_str());
- int fd = adb_connect("sync:");
+ std::string error;
+ int fd = adb_connect("sync:", &error);
if (fd < 0) {
- fprintf(stderr, "error: %s\n", adb_error());
+ fprintf(stderr, "error: %s\n", error.c_str());
return 1;
}
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index d9a1518..59e5b0b 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -271,8 +271,6 @@
return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
}
-extern char* adb_strtok_r(char *str, const char *delim, char **saveptr);
-
#else /* !_WIN32 a.k.a. Unix */
#include "fdevent.h"
@@ -517,19 +515,11 @@
return path[0] == '/';
}
-static __inline__ char* adb_strtok_r(char *str, const char *delim, char **saveptr)
-{
- return strtok_r(str, delim, saveptr);
-}
-
static __inline__ unsigned long adb_thread_id()
{
return (unsigned long)pthread_self();
}
-#undef strtok_r
-#define strtok_r ___xxx_strtok_r
-
#endif /* !_WIN32 */
#endif /* _ADB_SYSDEPS_H */
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index de47638..633f6f5 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -2151,85 +2151,6 @@
InitializeCriticalSection( &_win32_lock );
}
-/* Windows doesn't have strtok_r. Use the one from bionic. */
-
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
- */
-
-char *
-adb_strtok_r(char *s, const char *delim, char **last)
-{
- char *spanp;
- int c, sc;
- char *tok;
-
-
- if (s == NULL && (s = *last) == NULL)
- return (NULL);
-
- /*
- * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
- */
-cont:
- c = *s++;
- for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
- if (c == sc)
- goto cont;
- }
-
- if (c == 0) { /* no non-delimiter characters */
- *last = NULL;
- return (NULL);
- }
- tok = s - 1;
-
- /*
- * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
- * Note that delim must have one NUL; we stop if we see that, too.
- */
- for (;;) {
- c = *s++;
- spanp = (char *)delim;
- do {
- if ((sc = *spanp++) == c) {
- if (c == 0)
- s = NULL;
- else
- s[-1] = 0;
- *last = s;
- return (tok);
- }
- } while (sc != 0);
- }
- /* NOTREACHED */
-}
-
/**************************************************************************/
/**************************************************************************/
/***** *****/
diff --git a/adb/transport.cpp b/adb/transport.cpp
index d395a80..45740a8 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -847,7 +847,7 @@
result = t;
} else if (ttype == kTransportAny) {
if (result) {
- if (error_out) *error_out = "more than one device and emulator";
+ if (error_out) *error_out = "more than one device/emulator";
ambiguous = 1;
result = NULL;
break;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 30e6bf5..4d93bb5 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -105,7 +105,7 @@
D("client: connected on remote on fd %d\n", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
- snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
+ snprintf(buf, sizeof buf, "emulator-%d", console_port);
register_socket_transport(fd, buf, adb_port, 1);
return 0;
}
diff --git a/base/Android.mk b/base/Android.mk
index ad85c6b..7bd317b 100644
--- a/base/Android.mk
+++ b/base/Android.mk
@@ -18,11 +18,13 @@
libbase_src_files := \
file.cpp \
+ logging.cpp \
stringprintf.cpp \
strings.cpp \
libbase_test_src_files := \
file_test.cpp \
+ logging_test.cpp \
stringprintf_test.cpp \
strings_test.cpp \
test_main.cpp \
@@ -38,7 +40,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase
LOCAL_CLANG := true
-LOCAL_SRC_FILES := $(libbase_src_files) logging.cpp
+LOCAL_SRC_FILES := $(libbase_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@@ -61,9 +63,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase
LOCAL_SRC_FILES := $(libbase_src_files)
-ifneq ($(HOST_OS),windows)
- LOCAL_SRC_FILES += logging.cpp
-endif
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@@ -85,7 +84,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase_test
LOCAL_CLANG := true
-LOCAL_SRC_FILES := $(libbase_test_src_files) logging_test.cpp
+LOCAL_SRC_FILES := $(libbase_test_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_SHARED_LIBRARIES := libbase
@@ -97,9 +96,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbase_test
LOCAL_SRC_FILES := $(libbase_test_src_files)
-ifneq ($(HOST_OS),windows)
- LOCAL_SRC_FILES += logging_test.cpp
-endif
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CPPFLAGS := $(libbase_cppflags)
LOCAL_SHARED_LIBRARIES := libbase
diff --git a/base/file_test.cpp b/base/file_test.cpp
index e5cf696..b138094 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -36,7 +36,8 @@
TEST(file, ReadFileToString_success) {
std::string s("hello");
- ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s))
+ << strerror(errno);
EXPECT_GT(s.length(), 6U);
EXPECT_EQ('\n', s[s.length() - 1]);
s[5] = 0;
@@ -46,37 +47,44 @@
TEST(file, WriteStringToFile) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename)) << errno;
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename))
+ << strerror(errno);
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ << strerror(errno);
EXPECT_EQ("abc", s);
}
+// WriteStringToFile2 is explicitly for setting Unix permissions, which make no
+// sense on Windows.
+#if !defined(_WIN32)
TEST(file, WriteStringToFile2) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename, 0660,
getuid(), getgid()))
- << errno;
+ << strerror(errno);
struct stat sb;
ASSERT_EQ(0, stat(tf.filename, &sb));
- ASSERT_EQ(0660U, (sb.st_mode & ~S_IFMT));
+ ASSERT_EQ(0660U, static_cast<unsigned int>(sb.st_mode & ~S_IFMT));
ASSERT_EQ(getuid(), sb.st_uid);
ASSERT_EQ(getgid(), sb.st_gid);
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ << strerror(errno);
EXPECT_EQ("abc", s);
}
+#endif
TEST(file, WriteStringToFd) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
- ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << errno;
+ ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
std::string s;
- ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << strerror(errno);
EXPECT_EQ("abc", s);
}
@@ -101,6 +109,7 @@
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3));
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+ ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ << strerror(errno);
EXPECT_EQ("abc", s);
}
diff --git a/base/include/base/strings.h b/base/include/base/strings.h
index 3559342..5dbc5fb 100644
--- a/base/include/base/strings.h
+++ b/base/include/base/strings.h
@@ -27,8 +27,6 @@
//
// The string is split at each occurrence of a character in delimiters.
//
-// Empty splits will be omitted. I.e. Split("a,,b", ",") -> {"a", "b"}
-//
// The empty string is not a valid delimiter list.
std::vector<std::string> Split(const std::string& s,
const std::string& delimiters);
diff --git a/base/logging.cpp b/base/logging.cpp
index 0142b70..83957b3 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -27,12 +27,19 @@
#include <iostream>
#include <limits>
-#include <mutex>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
+#ifndef _WIN32
+#include <mutex>
+#else
+#define NOGDI // Suppress the evil ERROR macro.
+#include <windows.h>
+#endif
+
+#include "base/macros.h"
#include "base/strings.h"
#include "cutils/threads.h"
@@ -45,10 +52,79 @@
#include <unistd.h>
#endif
+namespace {
+#ifndef _WIN32
+using std::mutex;
+using std::lock_guard;
+
+#if defined(__GLIBC__)
+const char* getprogname() {
+ return program_invocation_short_name;
+}
+#endif
+
+#else
+const char* getprogname() {
+ static bool first = true;
+ static char progname[MAX_PATH] = {};
+
+ if (first) {
+ // TODO(danalbert): This is a full path on Windows. Just get the basename.
+ DWORD nchars = GetModuleFileName(nullptr, progname, sizeof(progname));
+ DCHECK_GT(nchars, 0U);
+ first = false;
+ }
+
+ return progname;
+}
+
+class mutex {
+ public:
+ mutex() {
+ semaphore_ = CreateSemaphore(nullptr, 1, 1, nullptr);
+ CHECK(semaphore_ != nullptr) << "Failed to create Mutex";
+ }
+ ~mutex() {
+ CloseHandle(semaphore_);
+ }
+
+ void lock() {
+ DWORD result = WaitForSingleObject(semaphore_, INFINITE);
+ CHECK_EQ(result, WAIT_OBJECT_0) << GetLastError();
+ }
+
+ void unlock() {
+ bool result = ReleaseSemaphore(semaphore_, 1, nullptr);
+ CHECK(result);
+ }
+
+ private:
+ HANDLE semaphore_;
+};
+
+template <typename LockT>
+class lock_guard {
+ public:
+ explicit lock_guard(LockT& lock) : lock_(lock) {
+ lock_.lock();
+ }
+
+ ~lock_guard() {
+ lock_.unlock();
+ }
+
+ private:
+ LockT& lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(lock_guard);
+};
+#endif
+} // namespace
+
namespace android {
namespace base {
-static std::mutex logging_lock;
+static mutex logging_lock;
#ifdef __ANDROID__
static LogFunction gLogger = LogdLogger();
@@ -60,12 +136,6 @@
static LogSeverity gMinimumLogSeverity = INFO;
static std::unique_ptr<std::string> gProgramInvocationName;
-#if defined(__GLIBC__)
-static const char* getprogname() {
- return program_invocation_short_name;
-}
-#endif
-
static const char* ProgramInvocationName() {
if (gProgramInvocationName == nullptr) {
gProgramInvocationName.reset(new std::string(getprogname()));
@@ -182,7 +252,7 @@
}
void SetLogger(LogFunction&& logger) {
- std::lock_guard<std::mutex> lock(logging_lock);
+ lock_guard<mutex> lock(logging_lock);
gLogger = std::move(logger);
}
@@ -287,7 +357,7 @@
void LogMessage::LogLine(const char* file, unsigned int line, LogId id,
LogSeverity severity, const char* message) {
const char* tag = ProgramInvocationName();
- std::lock_guard<std::mutex> lock(logging_lock);
+ lock_guard<mutex> lock(logging_lock);
gLogger(id, severity, tag, file, line, message);
}
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index d947c1d..c91857a 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -85,6 +85,9 @@
TEST(logging, LOG) {
ASSERT_DEATH(LOG(FATAL) << "foobar", "foobar");
+ // We can't usefully check the output of any of these on Windows because we
+ // don't have std::regex, but we can at least make sure we printed at least as
+ // many characters are in the log message.
{
CapturedStderr cap;
LOG(WARNING) << "foobar";
@@ -92,10 +95,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::WARNING, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
{
@@ -105,10 +111,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::INFO, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
{
@@ -129,10 +138,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::DEBUG, "foobar"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
}
@@ -145,10 +157,13 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("foobar"));
+#if !defined(_WIN32)
std::regex message_regex(make_log_pattern(
android::base::INFO, "foobar: No such file or directory"));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
}
@@ -161,11 +176,14 @@
std::string output;
android::base::ReadFdToString(cap.fd(), &output);
+ ASSERT_GT(output.length(), strlen("unimplemented"));
+#if !defined(_WIN32)
std::string expected_message =
android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
std::regex message_regex(
make_log_pattern(android::base::ERROR, expected_message.c_str()));
ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
}
}
diff --git a/base/stringprintf_test.cpp b/base/stringprintf_test.cpp
index 5cc2086..54b2b6c 100644
--- a/base/stringprintf_test.cpp
+++ b/base/stringprintf_test.cpp
@@ -20,11 +20,14 @@
#include <string>
+// The z size sepcifier isn't supported on Windows, so this test isn't useful.
+#if !defined(_WIN32)
TEST(StringPrintfTest, HexSizeT) {
size_t size = 0x00107e59;
EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size));
EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size));
}
+#endif
TEST(StringPrintfTest, StringAppendF) {
std::string s("a");
diff --git a/base/strings.cpp b/base/strings.cpp
index 6f698d9..d3375d9 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -32,24 +32,17 @@
const std::string& delimiters) {
CHECK_NE(delimiters.size(), 0U);
- std::vector<std::string> split;
- if (s.size() == 0) {
- // Split("", d) returns {} rather than {""}.
- return split;
- }
+ std::vector<std::string> result;
size_t base = 0;
size_t found;
do {
found = s.find_first_of(delimiters, base);
- if (found != base) {
- split.push_back(s.substr(base, found - base));
- }
-
+ result.push_back(s.substr(base, found - base));
base = found + 1;
} while (found != s.npos);
- return split;
+ return result;
}
std::string Trim(const std::string& s) {
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index 1bf07a1..46a1ab5 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -23,7 +23,8 @@
TEST(strings, split_empty) {
std::vector<std::string> parts = android::base::Split("", ",");
- ASSERT_EQ(0U, parts.size());
+ ASSERT_EQ(1U, parts.size());
+ ASSERT_EQ("", parts[0]);
}
TEST(strings, split_single) {
@@ -42,9 +43,10 @@
TEST(strings, split_with_empty_part) {
std::vector<std::string> parts = android::base::Split("foo,,bar", ",");
- ASSERT_EQ(2U, parts.size());
+ ASSERT_EQ(3U, parts.size());
ASSERT_EQ("foo", parts[0]);
- ASSERT_EQ("bar", parts[1]);
+ ASSERT_EQ("", parts[1]);
+ ASSERT_EQ("bar", parts[2]);
}
TEST(strings, split_null_char) {
@@ -65,9 +67,10 @@
TEST(strings, split_any_with_empty_part) {
std::vector<std::string> parts = android::base::Split("foo:,bar", ",:");
- ASSERT_EQ(2U, parts.size());
+ ASSERT_EQ(3U, parts.size());
ASSERT_EQ("foo", parts[0]);
- ASSERT_EQ("bar", parts[1]);
+ ASSERT_EQ("", parts[1]);
+ ASSERT_EQ("bar", parts[2]);
}
TEST(strings, trim_empty) {
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 1f6d3cf..0517bc7 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -16,15 +16,26 @@
#include "test_utils.h"
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/stat.h>
#include <unistd.h>
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
TemporaryFile::TemporaryFile() {
+#if defined(__ANDROID__)
init("/data/local/tmp");
- if (fd == -1) {
- init("/tmp");
- }
+#elif defined(_WIN32)
+ char wd[MAX_PATH] = {};
+ _getcwd(wd, sizeof(wd));
+ init(wd);
+#else
+ init("/tmp");
+#endif
}
TemporaryFile::~TemporaryFile() {
@@ -34,5 +45,15 @@
void TemporaryFile::init(const char* tmp_dir) {
snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
+#if !defined(_WIN32)
fd = mkstemp(filename);
+#else
+ // Windows doesn't have mkstemp, and tmpfile creates the file in the root
+ // directory, requiring root (?!) permissions. We have to settle for mktemp.
+ if (mktemp(filename) == nullptr) {
+ abort();
+ }
+
+ fd = open(filename, O_RDWR | O_NOINHERIT | O_CREAT, _S_IREAD | _S_IWRITE);
+#endif
}
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 7b2975b..dee471a 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -58,7 +58,8 @@
libsparse_host \
libutils \
liblog \
- libz
+ libz \
+ libbase
ifneq ($(HOST_OS),windows)
LOCAL_STATIC_LIBRARIES += libselinux
diff --git a/include/cutils/threads.h b/include/cutils/threads.h
index 3133cdb..5727494 100644
--- a/include/cutils/threads.h
+++ b/include/cutils/threads.h
@@ -17,6 +17,14 @@
#ifndef _LIBS_CUTILS_THREADS_H
#define _LIBS_CUTILS_THREADS_H
+#include <sys/types.h>
+
+#if !defined(_WIN32)
+#include <pthread.h>
+#else
+#include <windows.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -29,10 +37,9 @@
/***********************************************************************/
/***********************************************************************/
-#if !defined(_WIN32)
+extern pid_t gettid();
-#include <pthread.h>
-#include <sys/types.h>
+#if !defined(_WIN32)
typedef struct {
pthread_mutex_t lock;
@@ -40,14 +47,10 @@
pthread_key_t tls;
} thread_store_t;
-extern pid_t gettid();
-
#define THREAD_STORE_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0 }
#else // !defined(_WIN32)
-#include <windows.h>
-
typedef struct {
int lock_init;
int has_tls;
diff --git a/include/log/log.h b/include/log/log.h
index ce253e2..f9299b0 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -492,6 +492,7 @@
EVENT_TYPE_LONG = 1,
EVENT_TYPE_STRING = 2,
EVENT_TYPE_LIST = 3,
+ EVENT_TYPE_FLOAT = 4,
} AndroidEventLogType;
#define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType)
#define typeof_AndroidEventLogType unsigned char
@@ -510,6 +511,13 @@
sizeof(longBuf)); \
}
#endif
+#ifndef LOG_EVENT_FLOAT
+#define LOG_EVENT_FLOAT(_tag, _value) { \
+ float floatBuf = _value; \
+ (void) android_btWriteLog(_tag, EVENT_TYPE_FLOAT, &floatBuf, \
+ sizeof(floatBuf)); \
+ }
+#endif
#ifndef LOG_EVENT_STRING
#define LOG_EVENT_STRING(_tag, _value) \
(void) __android_log_bswrite(_tag, _value);
diff --git a/include/system/window.h b/include/system/window.h
index a875427..508ce00 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -267,7 +267,16 @@
* The default data space for the buffers as set by the consumer.
* The values are defined in graphics.h.
*/
- NATIVE_WINDOW_DEFAULT_DATASPACE = 12
+ NATIVE_WINDOW_DEFAULT_DATASPACE = 12,
+
+ /*
+ * Returns the age of the contents of the most recently dequeued buffer as
+ * the number of frames that have elapsed since it was last queued. For
+ * example, if the window is double-buffered, the age of any given buffer in
+ * steady state will be 2. If the dequeued buffer has never been queued, its
+ * age will be 0.
+ */
+ NATIVE_WINDOW_BUFFER_AGE = 13,
};
/* Valid operations for the (*perform)() hook.
diff --git a/init/Android.mk b/init/Android.mk
index 4bd4f3d..0dc257d 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -5,9 +5,9 @@
# --
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_DISABLE_SELINUX=1
+init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_PERMISSIVE_SELINUX=1
else
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_DISABLE_SELINUX=0
+init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_PERMISSIVE_SELINUX=0
endif
init_options += -DLOG_UEVENTS=0
diff --git a/init/init.cpp b/init/init.cpp
index dd74538..68c8b7f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -860,7 +860,7 @@
sehandle_prop = selinux_android_prop_context_handle();
}
-enum selinux_enforcing_status { SELINUX_DISABLED, SELINUX_PERMISSIVE, SELINUX_ENFORCING };
+enum selinux_enforcing_status { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
static selinux_enforcing_status selinux_status_from_cmdline() {
selinux_enforcing_status status = SELINUX_ENFORCING;
@@ -870,9 +870,7 @@
if (value == nullptr) { return; }
*value++ = '\0';
if (strcmp(name, "androidboot.selinux") == 0) {
- if (strcmp(value, "disabled") == 0) {
- status = SELINUX_DISABLED;
- } else if (strcmp(value, "permissive") == 0) {
+ if (strcmp(value, "permissive") == 0) {
status = SELINUX_PERMISSIVE;
}
}
@@ -882,24 +880,9 @@
return status;
}
-
-static bool selinux_is_disabled(void)
-{
- if (ALLOW_DISABLE_SELINUX) {
- if (access("/sys/fs/selinux", F_OK) != 0) {
- // SELinux is not compiled into the kernel, or has been disabled
- // via the kernel command line "selinux=0".
- return true;
- }
- return selinux_status_from_cmdline() == SELINUX_DISABLED;
- }
-
- return false;
-}
-
static bool selinux_is_enforcing(void)
{
- if (ALLOW_DISABLE_SELINUX) {
+ if (ALLOW_PERMISSIVE_SELINUX) {
return selinux_status_from_cmdline() == SELINUX_ENFORCING;
}
return true;
@@ -907,10 +890,6 @@
int selinux_reload_policy(void)
{
- if (selinux_is_disabled()) {
- return -1;
- }
-
INFO("SELinux: Attempting to reload policy files\n");
if (selinux_android_reload_policy() == -1) {
@@ -947,10 +926,6 @@
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
- if (selinux_is_disabled()) {
- return;
- }
-
if (in_kernel_domain) {
INFO("Loading SELinux policy...\n");
if (selinux_android_load_policy() < 0) {
@@ -958,8 +933,15 @@
security_failure();
}
+ bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = selinux_is_enforcing();
- security_setenforce(is_enforcing);
+ if (kernel_enforcing != is_enforcing) {
+ if (security_setenforce(is_enforcing)) {
+ ERROR("security_setenforce(%s) failed: %s\n",
+ is_enforcing ? "true" : "false", strerror(errno));
+ security_failure();
+ }
+ }
if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) {
security_failure();
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 54cace9..a2b4cfe 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -51,18 +51,10 @@
UnwindMap.cpp \
UnwindPtrace.cpp \
-libbacktrace_shared_libraries_target := \
- libcutils \
-
libbacktrace_shared_libraries := \
libbase \
- libunwind \
-
-libbacktrace_shared_libraries_host := \
liblog \
-
-libbacktrace_static_libraries_host := \
- libcutils \
+ libunwind \
libbacktrace_ldlibs_host := \
-lpthread \
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 91ca8b7..b2d8297 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -27,6 +27,8 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
+#include <cutils/threads.h>
+
#include "BacktraceLog.h"
#include "thread_utils.h"
#include "UnwindCurrent.h"
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index fd1f4da..14f04de 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -29,6 +29,8 @@
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
+#include <cutils/threads.h>
+
#include "BacktraceCurrent.h"
#include "BacktraceLog.h"
#include "ThreadEntry.h"
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index b0ada46..ca47f67 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -135,7 +135,7 @@
#if defined(__APPLE__)
// Corkscrew and libunwind don't compile on the mac, so create a generic
// map object.
-BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) {
+BacktraceMap* BacktraceMap::Create(pid_t pid, bool /*uncached*/) {
BacktraceMap* map = new BacktraceMap(pid);
if (!map->Build()) {
delete map;
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 4af6592..36c73c5 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -30,20 +30,21 @@
#include <time.h>
#include <unistd.h>
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-// For the THREAD_SIGNAL definition.
-#include "BacktraceCurrent.h"
-
-#include <cutils/atomic.h>
-#include <gtest/gtest.h>
-
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
+#include <cutils/atomic.h>
+#include <cutils/threads.h>
+
+#include <gtest/gtest.h>
+
+// For the THREAD_SIGNAL definition.
+#include "BacktraceCurrent.h"
#include "thread_utils.h"
// Number of microseconds per milliseconds.
diff --git a/libbacktrace/thread_utils.c b/libbacktrace/thread_utils.c
index 6f4cd3c..e75f56e 100644
--- a/libbacktrace/thread_utils.c
+++ b/libbacktrace/thread_utils.c
@@ -16,25 +16,12 @@
#include "thread_utils.h"
-#if defined(__APPLE__)
+#if !defined(__BIONIC__)
-#include <sys/syscall.h>
-
-// Mac OS >= 10.6 has a system call equivalent to Linux's gettid().
-pid_t gettid() {
- return syscall(SYS_thread_selfid);
-}
-
-#elif !defined(__BIONIC__)
-
-// glibc doesn't implement or export either gettid or tgkill.
+// glibc doesn't implement or export tgkill.
#include <unistd.h>
#include <sys/syscall.h>
-pid_t gettid() {
- return syscall(__NR_gettid);
-}
-
int tgkill(int tgid, int tid, int sig) {
return syscall(__NR_tgkill, tgid, tid, sig);
}
diff --git a/libbacktrace/thread_utils.h b/libbacktrace/thread_utils.h
index ae4c929..df83581 100644
--- a/libbacktrace/thread_utils.h
+++ b/libbacktrace/thread_utils.h
@@ -23,8 +23,6 @@
int tgkill(int tgid, int tid, int sig);
-pid_t gettid();
-
__END_DECLS
#endif /* _LIBBACKTRACE_THREAD_UTILS_H */
diff --git a/libcutils/threads.c b/libcutils/threads.c
index 5f5577b..036f8c5 100644
--- a/libcutils/threads.c
+++ b/libcutils/threads.c
@@ -16,8 +16,6 @@
#include "cutils/threads.h"
-#if !defined(_WIN32)
-
// For gettid.
#if defined(__APPLE__)
#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
@@ -30,9 +28,24 @@
#include <syscall.h>
#include <unistd.h>
#elif defined(_WIN32)
-#include <Windows.h>
+#include <windows.h>
#endif
+// No definition needed for Android because we'll just pick up bionic's copy.
+#ifndef __ANDROID__
+pid_t gettid() {
+#if defined(__APPLE__)
+ return syscall(SYS_thread_selfid);
+#elif defined(__linux__)
+ return syscall(__NR_gettid);
+#elif defined(_WIN32)
+ return GetCurrentThreadId();
+#endif
+}
+#endif // __ANDROID__
+
+#if !defined(_WIN32)
+
void* thread_store_get( thread_store_t* store )
{
if (!store->has_tls)
@@ -58,24 +71,6 @@
pthread_setspecific( store->tls, value );
}
-// No definition needed for Android because we'll just pick up bionic's copy.
-#ifndef __ANDROID__
-pid_t gettid() {
-#if defined(__APPLE__)
- uint64_t owner;
- int rc = pthread_threadid_np(NULL, &owner);
- if (rc != 0) {
- abort();
- }
- return owner;
-#elif defined(__linux__)
- return syscall(__NR_gettid);
-#elif defined(_WIN32)
- return (pid_t)GetCurrentThreadId();
-#endif
-}
-#endif // __ANDROID__
-
#else /* !defined(_WIN32) */
void* thread_store_get( thread_store_t* store )
{
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 7ba4c8e..0f01542 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <inttypes.h>
#include <sys/param.h>
#include <log/logd.h>
@@ -432,7 +433,7 @@
low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
- return ((long long) high << 32) | (long long) low;
+ return ((uint64_t) high << 32) | (uint64_t) low;
}
@@ -490,7 +491,7 @@
case EVENT_TYPE_LONG:
/* 64-bit signed long */
{
- long long lval;
+ uint64_t lval;
if (eventDataLen < 8)
return -1;
@@ -498,7 +499,30 @@
eventData += 8;
eventDataLen -= 8;
- outCount = snprintf(outBuf, outBufLen, "%lld", lval);
+ outCount = snprintf(outBuf, outBufLen, "%" PRId64, lval);
+ if (outCount < outBufLen) {
+ outBuf += outCount;
+ outBufLen -= outCount;
+ } else {
+ /* halt output */
+ goto no_room;
+ }
+ }
+ break;
+ case EVENT_TYPE_FLOAT:
+ /* float */
+ {
+ uint32_t ival;
+ float fval;
+
+ if (eventDataLen < 4)
+ return -1;
+ ival = get4LE(eventData);
+ fval = *(float*)&ival;
+ eventData += 4;
+ eventDataLen -= 4;
+
+ outCount = snprintf(outBuf, outBufLen, "%f", fval);
if (outCount < outBufLen) {
outBuf += outCount;
outBufLen -= outCount;
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index 6ece31d..c70d45f 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -135,7 +135,7 @@
break;
else:
crc_bin = FH.read(4)
- crc = struct.unpack("<I", crc)
+ crc = struct.unpack("<I", crc_bin)
print("Unverified CRC32 0x%08X" % (crc))
else:
print("Unknown chunk type 0x%04X" % (chunk_type), end="")
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 34131f1..79c4c53 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -30,6 +30,7 @@
#include <memory>
#include <vector>
+#include "base/file.h"
#include "base/macros.h" // TEMP_FAILURE_RETRY may or may not be in unistd
#include "base/memory.h"
#include "log/log.h"
@@ -1033,24 +1034,14 @@
return false;
}
- // Keep track of the start position so we can calculate the
- // total number of bytes written.
- const uint8_t* const start = buf;
- while (buf_size > 0) {
- ssize_t bytes_written = TEMP_FAILURE_RETRY(write(fd_, buf, buf_size));
- if (bytes_written == -1) {
- ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
- return false;
- }
-
- buf_size -= bytes_written;
- buf += bytes_written;
+ const bool result = android::base::WriteFully(fd_, buf, buf_size);
+ if (result) {
+ total_bytes_written_ += buf_size;
+ } else {
+ ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
}
- total_bytes_written_ += static_cast<size_t>(
- reinterpret_cast<uintptr_t>(buf) - reinterpret_cast<uintptr_t>(start));
-
- return true;
+ return result;
}
private:
FileWriter(const int fd, const size_t declared_length) :
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 1b5c6f4..909f8e2 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -21,6 +21,7 @@
# 2: long
# 3: string
# 4: list
+# 5: float
#
# The data unit is a number taken from the following list:
# 1: Number of objects
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 1dced11..b6b6124 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -295,7 +295,8 @@
uint64_t current = e->getRealTime().nsec() - NS_PER_SEC;
ssize_t index = -1;
while((index = next(index)) >= 0) {
- if (current > editEntryAt(index).getLast()->getRealTime().nsec()) {
+ LogBufferElement *l = editEntryAt(index).getLast();
+ if ((l->getDropped() >= 4) && (current > l->getRealTime().nsec())) {
removeAt(index);
index = -1;
}
@@ -630,7 +631,7 @@
pthread_mutex_unlock(&mLogElementsLock);
// range locking in LastLogTimes looks after us
- max = element->flushTo(reader);
+ max = element->flushTo(reader, this);
if (max == element->FLUSH_ERROR) {
return max;
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 9ee243d..00b19b6 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -74,6 +74,7 @@
// helper
char *pidToName(pid_t pid) { return stats.pidToName(pid); }
uid_t pidToUid(pid_t pid) { return stats.pidToUid(pid); }
+ char *uidToName(uid_t uid) { return stats.uidToName(uid); }
private:
void maybePrune(log_id_t id);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index a173e63..6a05700 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+#include <ctype.h>
#include <endian.h>
+#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
@@ -48,19 +50,89 @@
delete [] mMsg;
}
-// assumption: mMsg == NULL
-size_t LogBufferElement::populateDroppedMessage(char *&buffer, bool privileged) {
- static const char format_uid[] = "uid=%u dropped=%u";
- static const size_t unprivileged_offset = 7;
- static const char tag[] = "logd";
-
- size_t len;
- if (privileged) {
- len = snprintf(NULL, 0, format_uid, mUid, mDropped);
- } else {
- len = snprintf(NULL, 0, format_uid + unprivileged_offset, mDropped);
+// caller must own and free character string
+static char *tidToName(pid_t tid) {
+ char *retval = NULL;
+ char buffer[256];
+ snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid);
+ int fd = open(buffer, O_RDONLY);
+ if (fd >= 0) {
+ ssize_t ret = read(fd, buffer, sizeof(buffer));
+ if (ret >= (ssize_t)sizeof(buffer)) {
+ ret = sizeof(buffer) - 1;
+ }
+ while ((ret > 0) && isspace(buffer[ret - 1])) {
+ --ret;
+ }
+ if (ret > 0) {
+ buffer[ret] = '\0';
+ retval = strdup(buffer);
+ }
+ close(fd);
}
+ // if nothing for comm, check out cmdline
+ char *name = android::pidToName(tid);
+ if (!retval) {
+ retval = name;
+ name = NULL;
+ }
+
+ // check if comm is truncated, see if cmdline has full representation
+ if (name) {
+ // impossible for retval to be NULL if name not NULL
+ size_t retval_len = strlen(retval);
+ size_t name_len = strlen(name);
+ // KISS: ToDo: Only checks prefix truncated, not suffix, or both
+ if ((retval_len < name_len) && !strcmp(retval, name + name_len - retval_len)) {
+ free(retval);
+ retval = name;
+ } else {
+ free(name);
+ }
+ }
+ return retval;
+}
+
+// assumption: mMsg == NULL
+size_t LogBufferElement::populateDroppedMessage(char *&buffer,
+ LogBuffer *parent) {
+ static const char tag[] = "logd";
+ static const char format_uid[] = "uid=%u%s too chatty%s, expire %u line%s";
+
+ char *name = parent->uidToName(mUid);
+ char *commName = tidToName(mTid);
+ if (!commName && (mTid != mPid)) {
+ commName = tidToName(mPid);
+ }
+ if (!commName) {
+ commName = parent->pidToName(mPid);
+ }
+ if (name && commName && !strcmp(name, commName)) {
+ free(commName);
+ commName = NULL;
+ }
+ if (name) {
+ char *p = NULL;
+ asprintf(&p, "(%s)", name);
+ if (p) {
+ free(name);
+ name = p;
+ }
+ }
+ if (commName) {
+ char *p = NULL;
+ asprintf(&p, " comm=%s", commName);
+ if (p) {
+ free(commName);
+ commName = p;
+ }
+ }
+ // identical to below to calculate the buffer size required
+ size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "",
+ commName ? commName : "",
+ mDropped, (mDropped > 1) ? "s" : "");
+
size_t hdrLen;
if (mLogId == LOG_ID_EVENTS) {
hdrLen = sizeof(android_log_event_string_t);
@@ -70,6 +142,8 @@
buffer = static_cast<char *>(calloc(1, hdrLen + len + 1));
if (!buffer) {
+ free(name);
+ free(commName);
return 0;
}
@@ -86,16 +160,16 @@
strcpy(buffer + 1, tag);
}
- if (privileged) {
- snprintf(buffer + hdrLen, len + 1, format_uid, mUid, mDropped);
- } else {
- snprintf(buffer + hdrLen, len + 1, format_uid + unprivileged_offset, mDropped);
- }
+ snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
+ commName ? commName : "",
+ mDropped, (mDropped > 1) ? "s" : "");
+ free(name);
+ free(commName);
return retval;
}
-uint64_t LogBufferElement::flushTo(SocketClient *reader) {
+uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent) {
struct logger_entry_v3 entry;
memset(&entry, 0, sizeof(struct logger_entry_v3));
@@ -114,7 +188,7 @@
char *buffer = NULL;
if (!mMsg) {
- entry.len = populateDroppedMessage(buffer, clientHasLogCredentials(reader));
+ entry.len = populateDroppedMessage(buffer, parent);
if (!entry.len) {
return mSequence;
}
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 7b6456d..059c031 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -28,15 +28,19 @@
namespace android {
// Furnished in main.cpp. Caller must own and free returned value
-// This function is designed for a single caller and is NOT thread-safe
char *uidToName(uid_t uid);
+// Furnished in LogStatistics.cpp. Caller must own and free returned value
+char *pidToName(pid_t pid);
+
}
static inline bool worstUidEnabledForLogid(log_id_t id) {
return (id != LOG_ID_CRASH) && (id != LOG_ID_EVENTS);
}
+class LogBuffer;
+
class LogBufferElement {
const log_id_t mLogId;
const uid_t mUid;
@@ -52,7 +56,8 @@
static atomic_int_fast64_t sequence;
// assumption: mMsg == NULL
- size_t populateDroppedMessage(char *&buffer, bool privileged);
+ size_t populateDroppedMessage(char *&buffer,
+ LogBuffer *parent);
public:
LogBufferElement(log_id_t log_id, log_time realtime,
@@ -78,7 +83,7 @@
log_time getRealTime(void) const { return mRealTime; }
static const uint64_t FLUSH_ERROR;
- uint64_t flushTo(SocketClient *writer);
+ uint64_t flushTo(SocketClient *writer, LogBuffer *parent);
};
#endif
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index eadc4dd..b063630 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -39,7 +39,7 @@
namespace android {
// caller must own and free character string
-static char *pidToName(pid_t pid) {
+char *pidToName(pid_t pid) {
char *retval = NULL;
if (pid == 0) { // special case from auditd for kernel
retval = strdup("logd.auditd");
diff --git a/logd/main.cpp b/logd/main.cpp
index eb29596..237c7c1 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -210,18 +210,26 @@
return NULL;
}
+static sem_t sem_name;
+
char *android::uidToName(uid_t u) {
if (!u || !reinit_running) {
return NULL;
}
- // Not multi-thread safe, we know there is only one caller
+ sem_wait(&sem_name);
+
+ // Not multi-thread safe, we use sem_name to protect
uid = u;
name = NULL;
sem_post(&reinit);
sem_wait(&uidName);
- return name;
+ char *ret = name;
+
+ sem_post(&sem_name);
+
+ return ret;
}
// Serves as a global method to trigger reinitialization
@@ -277,6 +285,7 @@
// Reinit Thread
sem_init(&reinit, 0, 0);
sem_init(&uidName, 0, 0);
+ sem_init(&sem_name, 0, 1);
pthread_attr_t attr;
if (!pthread_attr_init(&attr)) {
struct sched_param param;