am ccb0806b: (-s ours) am 92b100b3: am 3670eab0: Merge "metricsd: Add Android.mk."
* commit 'ccb0806b6f458068b49bc5c2b51d1ae8d9e9513d':
diff --git a/.gitignore b/.gitignore
index b25c15b..2f836aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*~
+*.pyc
diff --git a/adb/Android.mk b/adb/Android.mk
index e2d0bb1..df0c7a1 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -118,6 +118,8 @@
ifeq ($(HOST_OS),windows)
LOCAL_C_INCLUDES += development/host/windows/usb/api/
+else
+ LOCAL_MULTILIB := 64
endif
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -277,6 +279,8 @@
LOCAL_MODULE := adbd
+LOCAL_INIT_RC := adbd.rc
+
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
index 63000f2..30c21f7 100644
--- a/adb/SERVICES.TXT
+++ b/adb/SERVICES.TXT
@@ -237,7 +237,7 @@
Note that there is no single-shot service to retrieve the list only once.
sync:
- This starts the file synchronisation service, used to implement "adb push"
+ This starts the file synchronization service, used to implement "adb push"
and "adb pull". Since this service is pretty complex, it will be detailed
in a companion document named SYNC.TXT
diff --git a/adb/SYNC.TXT b/adb/SYNC.TXT
index e74d217..06d7804 100644
--- a/adb/SYNC.TXT
+++ b/adb/SYNC.TXT
@@ -25,12 +25,9 @@
The following sync requests are accepted:
LIST - List the files in a folder
+RECV - Retrieve a file from device
SEND - Send a file to device
-RECV - Retreive a file from device
-
-Not yet documented:
STAT - Stat a file
-ULNK - Unlink (remove) a file. (Not currently supported)
For all of the sync request above the must be followed by length number of
bytes containing an utf-8 string with a remote filename.
@@ -40,7 +37,7 @@
respond with zero or more directory entries or "dents".
The directory entries will be returned in the following form
-1. A four-byte sync response id beeing "DENT"
+1. A four-byte sync response id "DENT"
2. A four-byte integer representing file mode.
3. A four-byte integer representing file size.
4. A four-byte integer representing last modified time.
@@ -60,13 +57,13 @@
adb push disk_image /some_block_device
to work.
-After this the actual file is sent in chunks. Each chucks has the following
+After this the actual file is sent in chunks. Each chunk has the following
format.
A sync request with id "DATA" and length equal to the chunk size. After
follows chunk size number of bytes. This is repeated until the file is
-transfered. Each chunk must not be larger than 64k.
+transferred. Each chunk must not be larger than 64k.
-When the file is tranfered a sync request "DONE" is sent, where length is set
+When the file is transferred a sync request "DONE" is sent, where length is set
to the last modified time for the file. The server responds to this last
request (but not to chuck requests) with an "OKAY" sync response (length can
be ignored).
@@ -77,8 +74,8 @@
the file that will be returned. Just as for the SEND sync request the file
received is split up into chunks. The sync response id is "DATA" and length is
the chuck size. After follows chunk size number of bytes. This is repeated
-until the file is transfered. Each chuck will not be larger than 64k.
+until the file is transferred. Each chuck will not be larger than 64k.
-When the file is transfered a sync resopnse "DONE" is retrieved where the
+When the file is transferred a sync response "DONE" is retrieved where the
length can be ignored.
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 821b785..a0501a6 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -55,11 +55,11 @@
ADB_MUTEX_DEFINE(D_lock);
-int HOST = 0;
-
#if !ADB_HOST
const char* adb_device_banner = "device";
static android::base::LogdLogger gLogdLogger;
+#else
+const char* adb_device_banner = "host";
#endif
void AdbLogger(android::base::LogId id, android::base::LogSeverity severity,
@@ -71,6 +71,14 @@
#endif
}
+std::string adb_version() {
+ // Don't change the format of this --- it's parsed by ddmlib.
+ return android::base::StringPrintf("Android Debug Bridge version %d.%d.%d\n"
+ "Revision %s\n",
+ ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
+ ADB_REVISION);
+}
+
void fatal(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
@@ -192,21 +200,20 @@
}
void adb_trace_init(char** argv) {
+#if !ADB_HOST
// Don't open log file if no tracing, since this will block
// the crypto unmount of /data
- const std::string trace_setting = get_trace_setting();
- if (trace_setting.empty()) {
- return;
- }
-
-#if !ADB_HOST
- if (isatty(STDOUT_FILENO) == 0) {
- start_device_log();
+ if (!get_trace_setting().empty()) {
+ if (isatty(STDOUT_FILENO) == 0) {
+ start_device_log();
+ }
}
#endif
setup_trace_mask();
android::base::InitLogging(argv, AdbLogger);
+
+ D("%s", adb_version().c_str());
}
apacket* get_apacket(void)
@@ -236,6 +243,11 @@
D("adb: offline\n");
//Close the associated usb
t->online = 0;
+
+ // This is necessary to avoid a race condition that occured when a transport closes
+ // while a client socket is still active.
+ close_all_sockets(t);
+
run_transport_disconnects(t);
}
@@ -300,45 +312,50 @@
send_packet(p, t);
}
-static size_t fill_connect_data(char *buf, size_t bufsize)
-{
-#if ADB_HOST
- return snprintf(buf, bufsize, "host::") + 1;
-#else
- static const char *cnxn_props[] = {
+std::string get_connection_string() {
+ std::vector<std::string> connection_properties;
+
+#if !ADB_HOST
+ static const char* cnxn_props[] = {
"ro.product.name",
"ro.product.model",
"ro.product.device",
};
- static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
- int i;
- size_t remaining = bufsize;
- size_t len;
- len = snprintf(buf, remaining, "%s::", adb_device_banner);
- remaining -= len;
- buf += len;
- for (i = 0; i < num_cnxn_props; i++) {
+ for (const auto& prop_name : cnxn_props) {
char value[PROPERTY_VALUE_MAX];
- property_get(cnxn_props[i], value, "");
- len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
- remaining -= len;
- buf += len;
+ property_get(prop_name, value, "");
+ connection_properties.push_back(
+ android::base::StringPrintf("%s=%s", prop_name, value));
}
-
- return bufsize - remaining + 1;
#endif
+
+ connection_properties.push_back(android::base::StringPrintf(
+ "features=%s", android::base::Join(supported_features(), ',').c_str()));
+
+ return android::base::StringPrintf(
+ "%s::%s", adb_device_banner,
+ android::base::Join(connection_properties, ';').c_str());
}
-void send_connect(atransport *t)
-{
+void send_connect(atransport* t) {
D("Calling send_connect \n");
- apacket *cp = get_apacket();
+ apacket* cp = get_apacket();
cp->msg.command = A_CNXN;
cp->msg.arg0 = t->get_protocol_version();
cp->msg.arg1 = t->get_max_payload();
- cp->msg.data_length = fill_connect_data((char *)cp->data,
- MAX_PAYLOAD_V1);
+
+ std::string connection_str = get_connection_string();
+ // Connect and auth packets are limited to MAX_PAYLOAD_V1 because we don't
+ // yet know how much data the other size is willing to accept.
+ if (connection_str.length() > MAX_PAYLOAD_V1) {
+ LOG(FATAL) << "Connection banner is too long (length = "
+ << connection_str.length() << ")";
+ }
+
+ memcpy(cp->data, connection_str.c_str(), connection_str.length());
+ cp->msg.data_length = connection_str.length();
+
send_packet(cp, t);
}
@@ -351,8 +368,8 @@
*dst = strdup(src.c_str());
}
-void parse_banner(const char* banner, atransport* t) {
- D("parse_banner: %s\n", banner);
+void parse_banner(const std::string& banner, atransport* t) {
+ D("parse_banner: %s\n", banner.c_str());
// The format is something like:
// "device::ro.product.name=x;ro.product.model=y;ro.product.device=z;".
@@ -375,6 +392,10 @@
qual_overwrite(&t->model, value);
} else if (key == "ro.product.device") {
qual_overwrite(&t->device, value);
+ } else if (key == "features") {
+ for (const auto& feature : android::base::Split(value, ",")) {
+ t->add_feature(feature);
+ }
}
}
}
@@ -402,6 +423,29 @@
}
}
+static void handle_new_connection(atransport* t, apacket* p) {
+ if (t->connection_state != kCsOffline) {
+ t->connection_state = kCsOffline;
+ handle_offline(t);
+ }
+
+ t->update_version(p->msg.arg0, p->msg.arg1);
+ std::string banner(reinterpret_cast<const char*>(p->data),
+ p->msg.data_length);
+ parse_banner(banner, t);
+
+#if ADB_HOST
+ handle_online(t);
+#else
+ if (!auth_required) {
+ handle_online(t);
+ send_connect(t);
+ } else {
+ send_auth_request(t);
+ }
+#endif
+}
+
void handle_packet(apacket *p, atransport *t)
{
asocket *s;
@@ -416,7 +460,9 @@
case A_SYNC:
if(p->msg.arg0){
send_packet(p, t);
- if(HOST) send_connect(t);
+#if ADB_HOST
+ send_connect(t);
+#endif
} else {
t->connection_state = kCsOffline;
handle_offline(t);
@@ -424,21 +470,8 @@
}
return;
- case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
- if(t->connection_state != kCsOffline) {
- t->connection_state = kCsOffline;
- handle_offline(t);
- }
-
- t->update_version(p->msg.arg0, p->msg.arg1);
- parse_banner(reinterpret_cast<const char*>(p->data), t);
-
- if (HOST || !auth_required) {
- handle_online(t);
- if (!HOST) send_connect(t);
- } else {
- send_auth_request(t);
- }
+ case A_CNXN: // CONNECT(version, maxdata, "system-id-string")
+ handle_new_connection(t, p);
break;
case A_AUTH:
@@ -847,7 +880,7 @@
case INSTALL_STATUS_OK: message = "success (!)"; break;
case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
case INSTALL_STATUS_CANNOT_BIND:
- message = android::base::StringPrintf("cannot bind to socket: %s",
+ message = android::base::StringPrintf("cannot bind listener: %s",
error.c_str());
break;
case INSTALL_STATUS_CANNOT_REBIND:
@@ -877,6 +910,12 @@
fprintf(stderr, "adb server killed by remote request\n");
fflush(stdout);
SendOkay(reply_fd);
+
+ // At least on Windows, if we exit() without shutdown(SD_SEND) or
+ // closesocket(), the client's next recv() will error-out with
+ // WSAECONNRESET and they'll never read the OKAY.
+ adb_shutdown(reply_fd);
+
exit(0);
}
@@ -922,6 +961,13 @@
return 1;
}
+ if (!strcmp(service, "features")) {
+ SendOkay(reply_fd);
+ SendProtocolString(
+ reply_fd, android::base::Join(supported_features(), '\n'));
+ return 0;
+ }
+
// remove TCP transport
if (!strncmp(service, "disconnect:", 11)) {
const std::string address(service + 11);
diff --git a/adb/adb.h b/adb/adb.h
index b0e53f0..6855f3b 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -20,10 +20,10 @@
#include <limits.h>
#include <sys/types.h>
-#include <base/macros.h>
-
#include <string>
+#include <base/macros.h>
+
#include "adb_trace.h"
#include "fdevent.h"
@@ -46,6 +46,8 @@
#define ADB_VERSION_MAJOR 1
#define ADB_VERSION_MINOR 0
+std::string adb_version();
+
// Increment this when we want to force users to start a new adb server.
#define ADB_SERVER_VERSION 32
@@ -189,71 +191,6 @@
kCsUnauthorized,
};
-class atransport {
-public:
- // TODO(danalbert): We expose waaaaaaay too much stuff because this was
- // historically just a struct, but making the whole thing a more idiomatic
- // class in one go is a very large change. Given how bad our testing is,
- // it's better to do this piece by piece.
-
- atransport() {
- auth_fde = {};
- transport_fde = {};
- protocol_version = A_VERSION;
- max_payload = MAX_PAYLOAD;
- }
-
- virtual ~atransport() {}
-
- int (*read_from_remote)(apacket* p, atransport* t) = nullptr;
- int (*write_to_remote)(apacket* p, atransport* t) = nullptr;
- void (*close)(atransport* t) = nullptr;
- void (*kick)(atransport* t) = nullptr;
-
- int fd = -1;
- int transport_socket = -1;
- fdevent transport_fde;
- int ref_count = 0;
- uint32_t sync_token = 0;
- ConnectionState connection_state = kCsOffline;
- bool online = false;
- TransportType type = kTransportAny;
-
- // USB handle or socket fd as needed.
- usb_handle* usb = nullptr;
- int sfd = -1;
-
- // Used to identify transports for clients.
- char* serial = nullptr;
- char* product = nullptr;
- char* model = nullptr;
- char* device = nullptr;
- char* devpath = nullptr;
- int adb_port = -1; // Use for emulators (local transport)
- bool kicked = false;
-
- // A list of adisconnect callbacks called when the transport is kicked.
- adisconnect disconnects = {};
-
- void* key = nullptr;
- unsigned char token[TOKEN_SIZE] = {};
- fdevent auth_fde;
- size_t failed_auth_attempts = 0;
-
- const char* connection_state_name() const;
-
- void update_version(int version, size_t payload);
- int get_protocol_version() const;
- size_t get_max_payload() const;
-
-private:
- int protocol_version;
- size_t max_payload;
-
- DISALLOW_COPY_AND_ASSIGN(atransport);
-};
-
-
/* A listener is an entity which binds to a local port
** and, upon receiving a connection on that port, creates
** an asocket to connect the new local connection to a
@@ -378,8 +315,8 @@
ConnectionState connection_state(atransport *t);
-extern const char *adb_device_banner;
-extern int HOST;
+extern const char* adb_device_banner;
+
#if !ADB_HOST
extern int SHELL_EXIT_NOTIFY_FD;
#endif // !ADB_HOST
@@ -404,4 +341,6 @@
void send_connect(atransport *t);
+void parse_banner(const std::string&, atransport* t);
+
#endif
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index afff2ef..a1bbb78 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -44,28 +44,6 @@
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, '\0');
- if (!ReadFdExactly(fd, &(*s)[0], len)) {
- *error = perror_str("protocol fault (couldn't read status message)");
- return false;
- }
-
- return true;
-}
-
void adb_set_transport(TransportType type, const char* serial)
{
__adb_transport = type;
@@ -175,7 +153,7 @@
return -1;
}
- if(!SendProtocolString(fd, service)) {
+ if (!SendProtocolString(fd, service)) {
*error = perror_str("write failure during connection");
adb_close(fd);
return -1;
@@ -197,6 +175,7 @@
D("adb_connect: service %s\n", 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
return fd;
} else if (fd == -2) {
fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
@@ -204,6 +183,10 @@
start_server:
if (launch_server(__adb_server_port)) {
fprintf(stderr,"* failed to start daemon *\n");
+ // launch_server() has already printed detailed error info, so just
+ // return a generic error string about the overall adb_connect()
+ // that the caller requested.
+ *error = "cannot connect to daemon";
return -1;
} else {
fprintf(stdout,"* daemon started successfully *\n");
@@ -225,7 +208,10 @@
adb_close(fd);
if (sscanf(&version_string[0], "%04x", &version) != 1) {
- goto error;
+ *error = android::base::StringPrintf(
+ "cannot parse version string: %s",
+ version_string.c_str());
+ return -1;
}
} else {
// if fd is -1, then check for "unknown host service",
@@ -239,7 +225,13 @@
if (version != ADB_SERVER_VERSION) {
printf("adb server is out of date. killing...\n");
fd = _adb_connect("host:kill", error);
- adb_close(fd);
+ if (fd >= 0) {
+ adb_close(fd);
+ } else {
+ // If we couldn't connect to the server or had some other error,
+ // report it, but still try to start the server.
+ fprintf(stderr, "error: %s\n", error->c_str());
+ }
/* XXX can we better detect its death? */
adb_sleep_ms(2000);
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index 5ae6ec3..7092609 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -32,7 +32,27 @@
length = 0xffff;
}
- return WriteFdFmt(fd, "%04x", length) && WriteFdExactly(fd, s);
+ // The cost of sending two strings outweighs the cost of formatting.
+ // "adb sync" performance is affected by this.
+ return WriteFdFmt(fd, "%04x%.*s", length, length, s.c_str());
+}
+
+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, '\0');
+ if (!ReadFdExactly(fd, &(*s)[0], len)) {
+ *error = perror_str("protocol fault (couldn't read status message)");
+ return false;
+ }
+
+ return true;
}
bool SendOkay(int fd) {
diff --git a/adb/adb_io.h b/adb/adb_io.h
index 8d50a6d..9c3b2a5 100644
--- a/adb/adb_io.h
+++ b/adb/adb_io.h
@@ -30,23 +30,22 @@
// Writes a protocol-format string; a four hex digit length followed by the string data.
bool SendProtocolString(int fd, const std::string& s);
-/*
- * Reads exactly len bytes from fd into buf.
- *
- * Returns false if there is an error or if EOF was reached before len bytes
- * were read. If EOF was found, errno will be set to 0.
- *
- * If this function fails, the contents of buf are undefined.
- */
-bool ReadFdExactly(int fd, void *buf, size_t len);
+// Reads a protocol-format string; a four hex digit length followed by the string data.
+bool ReadProtocolString(int fd, std::string* s, std::string* error);
-/*
- * Writes exactly len bytes from buf to fd.
- *
- * Returns false if there is an error or if the fd was closed before the write
- * completed. If the other end of the fd (such as in a socket, pipe, or fifo),
- * is closed, errno will be set to 0.
- */
+// Reads exactly len bytes from fd into buf.
+//
+// Returns false if there is an error or if EOF was reached before len bytes
+// were read. If EOF was found, errno will be set to 0.
+//
+// If this function fails, the contents of buf are undefined.
+bool ReadFdExactly(int fd, void* buf, size_t len);
+
+// Writes exactly len bytes from buf to fd.
+//
+// Returns false if there is an error or if the fd was closed before the write
+// completed. If the other end of the fd (such as in a socket, pipe, or fifo),
+// is closed, errno will be set to 0.
bool WriteFdExactly(int fd, const void* buf, size_t len);
// Same as above, but for strings.
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 1e7ce5d..8fb2d19 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -190,16 +190,19 @@
/* can't repurpose a smartsocket */
if(l->connect_to[0] == '*') {
+ *error = "cannot repurpose smartsocket";
return INSTALL_STATUS_INTERNAL_ERROR;
}
/* can't repurpose a listener if 'no_rebind' is true */
if (no_rebind) {
+ *error = "cannot rebind";
return INSTALL_STATUS_CANNOT_REBIND;
}
cto = strdup(connect_to);
if(cto == 0) {
+ *error = "cannot duplicate string";
return INSTALL_STATUS_INTERNAL_ERROR;
}
@@ -232,7 +235,6 @@
listener->fd = local_name_to_fd(listener->local_name, error);
if (listener->fd < 0) {
- printf("cannot bind '%s': %s\n", listener->local_name, error->c_str());
free(listener->local_name);
free(listener->connect_to);
free(listener);
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index ca843bd..e5dc692 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -225,3 +225,7 @@
<< " (" << *canonical_address << ")";
return true;
}
+
+std::string perror_str(const char* msg) {
+ return android::base::StringPrintf("%s: %s", msg, strerror(errno));
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 739efcc..b38ec59 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -44,4 +44,6 @@
std::string* host, int* port,
std::string* error);
+std::string perror_str(const char* msg);
+
#endif
diff --git a/adb/adbd.rc b/adb/adbd.rc
new file mode 100644
index 0000000..b91d8b5
--- /dev/null
+++ b/adb/adbd.rc
@@ -0,0 +1,14 @@
+on post-fs-data
+ mkdir /data/misc/adb 02750 system shell
+ mkdir /data/adb 0700 root root
+
+# adbd is controlled via property triggers in init.<platform>.usb.rc
+service adbd /sbin/adbd --root_seclabel=u:r:su:s0
+ class core
+ socket adbd stream 660 system system
+ disabled
+ seclabel u:r:adbd:s0
+
+# adbd on at boot in emulator
+on property:ro.kernel.qemu=1
+ start adbd
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 73acbb0..39bb02b 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -88,13 +88,8 @@
DWORD nchars = GetTempPathW(arraysize(temp_path), temp_path);
if ((nchars >= arraysize(temp_path)) || (nchars == 0)) {
// If string truncation or some other error.
- // TODO(danalbert): Log the error message from
- // FormatMessage(GetLastError()). Pure Windows APIs only touch
- // GetLastError(), C Runtime APIs touch errno, so maybe there should be
- // WPLOG or PLOGW (which would read GetLastError() instead of errno),
- // in addition to PLOG, or maybe better to just ignore it and add a
- // simplified version of FormatMessage() for use in log messages.
- LOG(ERROR) << "Error creating log file";
+ fatal("cannot retrieve temporary file path: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
}
return narrow(temp_path) + log_name;
@@ -109,19 +104,28 @@
static void close_stdin() {
int fd = unix_open(kNullFileName, O_RDONLY);
- CHECK_NE(fd, -1);
- dup2(fd, STDIN_FILENO);
+ if (fd == -1) {
+ fatal("cannot open '%s': %s", kNullFileName, strerror(errno));
+ }
+ if (dup2(fd, STDIN_FILENO) == -1) {
+ fatal("cannot redirect stdin: %s", strerror(errno));
+ }
unix_close(fd);
}
static void setup_daemon_logging(void) {
- int fd = unix_open(GetLogFilePath().c_str(), O_WRONLY | O_CREAT | O_APPEND,
+ const std::string log_file_path(GetLogFilePath());
+ int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND,
0640);
if (fd == -1) {
- fd = unix_open(kNullFileName, O_WRONLY);
+ fatal("cannot open '%s': %s", log_file_path.c_str(), strerror(errno));
}
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
+ if (dup2(fd, STDOUT_FILENO) == -1) {
+ fatal("cannot redirect stdout: %s", strerror(errno));
+ }
+ if (dup2(fd, STDERR_FILENO) == -1) {
+ fatal("cannot redirect stderr: %s", strerror(errno));
+ }
unix_close(fd);
#ifdef _WIN32
@@ -130,11 +134,10 @@
setvbuf(stderr, NULL, _IONBF, 0);
#endif
fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
+ LOG(INFO) << adb_version();
}
int adb_main(int is_daemon, int server_port, int ack_reply_fd) {
- HOST = 1;
-
#if defined(_WIN32)
SetConsoleCtrlHandler(ctrlc_handler, TRUE);
#else
@@ -154,7 +157,7 @@
std::string error;
std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
if (install_listener(local_name, "*smartsocket*", nullptr, 0, &error)) {
- LOG(FATAL) << "Could not install *smartsocket* listener: " << error;
+ fatal("could not install *smartsocket* listener: %s", error.c_str());
}
// Inform our parent that we are up and running.
@@ -176,7 +179,9 @@
#else
// TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
// "OKAY".
- android::base::WriteStringToFd("OK\n", ack_reply_fd);
+ if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) {
+ fatal_errno("error writing ACK to fd %d", ack_reply_fd);
+ }
unix_close(ack_reply_fd);
#endif
close_stdin();
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 87be7cb..ed25f3b 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -65,16 +65,9 @@
gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
}
-static void version(FILE* out) {
- fprintf(out, "Android Debug Bridge version %d.%d.%d\nRevision %s\n",
- ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_REVISION);
-}
-
static void help() {
- version(stderr);
-
+ fprintf(stderr, "%s\n", adb_version().c_str());
fprintf(stderr,
- "\n"
" -a - directs adb to listen on all interfaces for a connection\n"
" -d - directs command to the only connected USB device\n"
" returns an error if more than one USB device is present.\n"
@@ -291,10 +284,7 @@
count--;
while (count > 0) {
int len = adb_read(fd, buf, count);
- if (len == 0) {
- break;
- } else if (len < 0) {
- if (errno == EINTR) continue;
+ if (len <= 0) {
break;
}
@@ -347,11 +337,7 @@
break;
}
if (len < 0) {
- if (errno == EINTR) {
- D("copy_to_file() : EINTR, retrying\n");
- continue;
- }
- D("copy_to_file() : error %d\n", errno);
+ D("copy_to_file(): read failed: %s\n", strerror(errno));
break;
}
if (outFd == STDOUT_FILENO) {
@@ -396,17 +382,13 @@
fdi = fds[1];
free(fds);
- for(;;) {
+ 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);
r = unix_read(fdi, buf, 1024);
D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
- if(r == 0) break;
- if(r < 0) {
- if(errno == EINTR) continue;
- break;
- }
- for(n = 0; n < r; n++){
+ if (r <= 0) break;
+ for (n = 0; n < r; n++){
switch(buf[n]) {
case '\n':
state = 1;
@@ -904,14 +886,14 @@
}
static void parse_push_pull_args(const char **arg, int narg, char const **path1,
- char const **path2, int *show_progress,
+ char const **path2, bool* show_progress,
int *copy_attrs) {
- *show_progress = 0;
+ *show_progress = false;
*copy_attrs = 0;
while (narg > 0) {
if (!strcmp(*arg, "-p")) {
- *show_progress = 1;
+ *show_progress = true;
} else if (!strcmp(*arg, "-a")) {
*copy_attrs = 1;
} else {
@@ -983,7 +965,7 @@
server_port = strtol(server_port_str, nullptr, 0);
if (server_port <= 0 || server_port > 65535) {
fprintf(stderr,
- "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
+ "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65536. Got \"%s\"\n",
server_port_str);
return usage();
}
@@ -1248,11 +1230,22 @@
else if (!strcmp(argv[0], "kill-server")) {
std::string error;
int fd = _adb_connect("host:kill", &error);
- if (fd == -1) {
+ if (fd == -2) {
+ // Failed to make network connection to server. Don't output the
+ // network error since that is expected.
fprintf(stderr,"* server not running *\n");
+ // Successful exit code because the server is already "killed".
+ return 0;
+ } else if (fd == -1) {
+ // Some other error.
+ fprintf(stderr, "error: %s\n", error.c_str());
return 1;
+ } else {
+ // Successfully connected, kill command sent, okay status came back.
+ // Server should exit() in a moment, if not already.
+ adb_close(fd);
+ return 0;
}
- return 0;
}
else if (!strcmp(argv[0], "sideload")) {
if (argc != 2) return usage();
@@ -1335,33 +1328,25 @@
/* do_sync_*() commands */
else if (!strcmp(argv[0], "ls")) {
if (argc != 2) return usage();
- return do_sync_ls(argv[1]);
+ return do_sync_ls(argv[1]) ? 0 : 1;
}
else if (!strcmp(argv[0], "push")) {
- int show_progress = 0;
- int copy_attrs = 0; // unused
+ bool show_progress = false;
+ int copy_attrs = 0;
const char* lpath = NULL, *rpath = NULL;
parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, ©_attrs);
-
- if ((lpath != NULL) && (rpath != NULL)) {
- return do_sync_push(lpath, rpath, show_progress);
- }
-
- return usage();
+ if (!lpath || !rpath || copy_attrs != 0) return usage();
+ return do_sync_push(lpath, rpath, show_progress) ? 0 : 1;
}
else if (!strcmp(argv[0], "pull")) {
- int show_progress = 0;
+ bool show_progress = false;
int copy_attrs = 0;
const char* rpath = NULL, *lpath = ".";
parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, ©_attrs);
-
- if (rpath != NULL) {
- return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
- }
-
- return usage();
+ if (!rpath) return usage();
+ return do_sync_pull(rpath, lpath, show_progress, copy_attrs) ? 0 : 1;
}
else if (!strcmp(argv[0], "install")) {
if (argc < 2) return usage();
@@ -1405,20 +1390,20 @@
std::string vendor_src_path = product_file("vendor");
std::string oem_src_path = product_file("oem");
- int rc = 0;
- if (rc == 0 && (src.empty() || src == "system")) {
- rc = do_sync_sync(system_src_path, "/system", list_only);
+ bool okay = true;
+ if (okay && (src.empty() || src == "system")) {
+ okay = do_sync_sync(system_src_path, "/system", list_only);
}
- if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
- rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
+ if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
+ okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
}
- if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
- rc = do_sync_sync(oem_src_path, "/oem", list_only);
+ if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
+ okay = do_sync_sync(oem_src_path, "/oem", list_only);
}
- if (rc == 0 && (src.empty() || src == "data")) {
- rc = do_sync_sync(data_src_path, "/data", list_only);
+ if (okay && (src.empty() || src == "data")) {
+ okay = do_sync_sync(data_src_path, "/data", list_only);
}
- return rc;
+ return okay ? 0 : 1;
}
/* passthrough commands */
else if (!strcmp(argv[0],"get-state") ||
@@ -1436,7 +1421,11 @@
}
else if (!strcmp(argv[0], "start-server")) {
std::string error;
- return adb_connect("host:start-server", &error);
+ const int result = adb_connect("host:start-server", &error);
+ if (result < 0) {
+ fprintf(stderr, "error: %s\n", error.c_str());
+ }
+ return result;
}
else if (!strcmp(argv[0], "backup")) {
return backup(argc, argv);
@@ -1457,9 +1446,12 @@
return 0;
}
else if (!strcmp(argv[0], "version")) {
- version(stdout);
+ fprintf(stdout, "%s", adb_version().c_str());
return 0;
}
+ else if (!strcmp(argv[0], "features")) {
+ return adb_query_command("host:features");
+ }
usage();
return 1;
@@ -1532,20 +1524,16 @@
return -1;
}
+ int result = -1;
const char* apk_file = argv[last_apk];
std::string apk_dest = android::base::StringPrintf(where, adb_basename(apk_file).c_str());
- int err = do_sync_push(apk_file, apk_dest.c_str(), 0 /* no show progress */);
- if (err) {
- goto cleanup_apk;
- } else {
- argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
- }
-
- err = pm_command(transport, serial, argc, argv);
+ if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
+ argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
+ result = pm_command(transport, serial, argc, argv);
cleanup_apk:
delete_file(transport, serial, apk_dest);
- return err;
+ return result;
}
static int install_multiple_app(TransportType transport, const char* serial, int argc,
diff --git a/adb/device.py b/adb/device.py
index a15675b..5b33ff2 100644
--- a/adb/device.py
+++ b/adb/device.py
@@ -101,6 +101,20 @@
class AndroidDevice(object):
+ # Delimiter string to indicate the start of the exit code.
+ _RETURN_CODE_DELIMITER = 'x'
+
+ # Follow any shell command with this string to get the exit
+ # status of a program since this isn't propagated by adb.
+ #
+ # The delimiter is needed because `printf 1; echo $?` would print
+ # "10", and we wouldn't be able to distinguish the exit code.
+ _RETURN_CODE_PROBE_STRING = 'echo "{0}$?"'.format(_RETURN_CODE_DELIMITER)
+
+ # Maximum search distance from the output end to find the delimiter.
+ # adb on Windows returns \r\n even if adbd returns \n.
+ _RETURN_CODE_SEARCH_LENGTH = len('{0}255\r\n'.format(_RETURN_CODE_DELIMITER))
+
def __init__(self, serial, product=None):
self.serial = serial
self.product = product
@@ -110,40 +124,44 @@
if self.product is not None:
self.adb_cmd.extend(['-p', product])
self._linesep = None
- self._shell_result_pattern = None
@property
def linesep(self):
if self._linesep is None:
- self._linesep = subprocess.check_output(['adb', 'shell', 'echo'])
+ self._linesep = subprocess.check_output(self.adb_cmd +
+ ['shell', 'echo'])
return self._linesep
def _make_shell_cmd(self, user_cmd):
- # Follow any shell command with `; echo; echo $?` to get the exit
- # status of a program since this isn't propagated by adb.
- #
- # The leading newline is needed because `printf 1; echo $?` would print
- # "10", and we wouldn't be able to distinguish the exit code.
- rc_probe = '; echo "\n$?"'
- return self.adb_cmd + ['shell'] + user_cmd + [rc_probe]
+ return (self.adb_cmd + ['shell'] + user_cmd +
+ ['; ' + self._RETURN_CODE_PROBE_STRING])
- def _parse_shell_output(self, out): # pylint: disable=no-self-use
+ def _parse_shell_output(self, out):
+ """Finds the exit code string from shell output.
+
+ Args:
+ out: Shell output string.
+
+ Returns:
+ An (exit_code, output_string) tuple. The output string is
+ cleaned of any additional stuff we appended to find the
+ exit code.
+
+ Raises:
+ RuntimeError: Could not find the exit code in |out|.
+ """
search_text = out
- max_result_len = len('{0}255{0}'.format(self.linesep))
- if len(search_text) > max_result_len:
- # We don't want to regex match over massive amounts of data when we
- # know the part we want is right at the end.
- search_text = search_text[-max_result_len:]
- if self._shell_result_pattern is None:
- self._shell_result_pattern = re.compile(
- r'({0}\d+{0})$'.format(self.linesep), re.MULTILINE)
- m = self._shell_result_pattern.search(search_text)
- if m is None:
+ if len(search_text) > self._RETURN_CODE_SEARCH_LENGTH:
+ # We don't want to search over massive amounts of data when we know
+ # the part we want is right at the end.
+ search_text = search_text[-self._RETURN_CODE_SEARCH_LENGTH:]
+ partition = search_text.rpartition(self._RETURN_CODE_DELIMITER)
+ if partition[1] == '':
raise RuntimeError('Could not find exit status in shell output.')
-
- result_text = m.group(1)
- result = int(result_text.strip())
- out = out[:-len(result_text)] # Trim the result text from the output.
+ result = int(partition[2])
+ # partition[0] won't contain the full text if search_text was truncated,
+ # pull from the original string instead.
+ out = out[:-len(partition[1]) - len(partition[2])]
return result, out
def _simple_call(self, cmd):
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index a8abade..d25bbfb 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -2,16 +2,16 @@
**
** Copyright 2006, Brian Swetland <swetland@frotz.net>
**
-** 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
+** 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
+** 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
+** 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.
*/
@@ -205,8 +205,8 @@
n = epoll_wait(epoll_fd, events, 256, -1);
- if(n < 0) {
- if(errno == EINTR) return;
+ if (n < 0) {
+ if (errno == EINTR) return;
perror("epoll_wait");
exit(1);
}
@@ -688,7 +688,7 @@
fdevent_subproc_setup();
#endif // !ADB_HOST
- for(;;) {
+ while (true) {
D("--- ---- waiting for events\n");
fdevent_process();
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index da80013..e70d550 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -27,6 +27,8 @@
#include <time.h>
#include <utime.h>
+#include <memory>
+
#include "sysdeps.h"
#include "adb.h"
@@ -35,36 +37,21 @@
#include "adb_utils.h"
#include "file_sync_service.h"
+#include <base/strings.h>
#include <base/stringprintf.h>
-static unsigned long long total_bytes;
-static long long start_time;
+struct syncsendbuf {
+ unsigned id;
+ unsigned size;
+ char data[SYNC_DATA_MAX];
+};
-static long long NOW()
-{
+static syncsendbuf send_buffer;
+
+static long long NOW() {
struct timeval tv;
gettimeofday(&tv, 0);
- return ((long long) tv.tv_usec) +
- 1000000LL * ((long long) tv.tv_sec);
-}
-
-static void BEGIN()
-{
- total_bytes = 0;
- start_time = NOW();
-}
-
-static void END()
-{
- long long t = NOW() - start_time;
- if(total_bytes == 0) return;
-
- if (t == 0) /* prevent division by 0 :-) */
- t = 1000000;
-
- fprintf(stderr,"%lld KB/s (%lld bytes in %lld.%03llds)\n",
- ((total_bytes * 1000000LL) / t) / 1024LL,
- total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
+ return ((long long) tv.tv_usec) + 1000000LL * ((long long) tv.tv_sec);
}
static void print_transfer_progress(uint64_t bytes_current,
@@ -82,148 +69,123 @@
fflush(stderr);
}
-static void sync_quit(int fd) {
- syncmsg msg;
-
- msg.req.id = ID_QUIT;
- msg.req.namelen = 0;
-
- WriteFdExactly(fd, &msg.req, sizeof(msg.req));
-}
-
-typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);
-
-static int sync_ls(int fd, const char* path, sync_ls_cb func, void* cookie) {
- int len = strlen(path);
- if (len > 1024) goto fail;
-
- syncmsg msg;
- msg.req.id = ID_LIST;
- msg.req.namelen = htoll(len);
-
- if (!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || !WriteFdExactly(fd, path, len)) {
- goto fail;
+static bool SendRequest(int fd, int id, const char* path) {
+ size_t path_length = strlen(path);
+ if (path_length > 1024) {
+ fprintf(stderr, "SendRequest failed: path too long: %zu", path_length);
+ return false;
}
- for (;;) {
- if (!ReadFdExactly(fd, &msg.dent, sizeof(msg.dent))) break;
- if (msg.dent.id == ID_DONE) return 0;
- if (msg.dent.id != ID_DENT) break;
+ // Sending header and payload in a single write makes a noticeable
+ // difference to "adb sync" performance.
+ char buf[sizeof(SyncRequest) + path_length] __attribute__((aligned(8)));
+ SyncRequest* req = reinterpret_cast<SyncRequest*>(buf);
+ req->id = id;
+ req->path_length = path_length;
+ char* data = reinterpret_cast<char*>(req + 1);
+ memcpy(data, path, path_length);
- len = ltohl(msg.dent.namelen);
- if (len > 256) break;
-
- char buf[257];
- if (!ReadFdExactly(fd, buf, len)) break;
- buf[len] = 0;
-
- func(ltohl(msg.dent.mode), ltohl(msg.dent.size), ltohl(msg.dent.time), buf, cookie);
- }
-
-fail:
- adb_close(fd);
- return -1;
+ return WriteFdExactly(fd, buf, sizeof(buf));
}
-struct syncsendbuf {
- unsigned id;
- unsigned size;
- char data[SYNC_DATA_MAX];
+class SyncConnection {
+ public:
+ SyncConnection() : total_bytes(0), start_time_(NOW()) {
+ max = SYNC_DATA_MAX; // TODO: decide at runtime.
+
+ std::string error;
+ fd = adb_connect("sync:", &error);
+ if (fd < 0) {
+ fprintf(stderr, "error: %s\n", error.c_str());
+ }
+ }
+
+ ~SyncConnection() {
+ if (!IsValid()) return;
+
+ SendQuit();
+ ShowTransferRate();
+ adb_close(fd);
+ }
+
+ bool IsValid() { return fd >= 0; }
+
+ uint64_t total_bytes;
+
+ // TODO: add a char[max] buffer here, to replace syncsendbuf...
+ int fd;
+ size_t max;
+
+ private:
+ uint64_t start_time_;
+
+ void SendQuit() {
+ SendRequest(fd, ID_QUIT, ""); // TODO: add a SendResponse?
+ }
+
+ void ShowTransferRate() {
+ uint64_t t = NOW() - start_time_;
+ if (total_bytes == 0 || t == 0) return;
+
+ fprintf(stderr, "%lld KB/s (%" PRId64 " bytes in %lld.%03llds)\n",
+ ((total_bytes * 1000000LL) / t) / 1024LL,
+ total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
+ }
};
-static syncsendbuf send_buffer;
+typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name, void* cookie);
-static int sync_readtime(int fd, const char* path, unsigned int* timestamp, unsigned int* mode) {
- syncmsg msg;
- int len = strlen(path);
+static bool sync_ls(int fd, const char* path, sync_ls_cb func, void* cookie) {
+ if (!SendRequest(fd, ID_LIST, path)) return false;
- msg.req.id = ID_STAT;
- msg.req.namelen = htoll(len);
+ while (true) {
+ syncmsg msg;
+ if (!ReadFdExactly(fd, &msg.dent, sizeof(msg.dent))) return false;
- if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
- !WriteFdExactly(fd, path, len)) {
- return -1;
+ if (msg.dent.id == ID_DONE) return true;
+ if (msg.dent.id != ID_DENT) return false;
+
+ size_t len = msg.dent.namelen;
+ if (len > 256) return false; // TODO: resize buffer? continue?
+
+ char buf[257];
+ if (!ReadFdExactly(fd, buf, len)) return false;
+ buf[len] = 0;
+
+ func(msg.dent.mode, msg.dent.size, msg.dent.time, buf, cookie);
}
-
- if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) {
- return -1;
- }
-
- if(msg.stat.id != ID_STAT) {
- return -1;
- }
-
- *timestamp = ltohl(msg.stat.time);
- *mode = ltohl(msg.stat.mode);
- return 0;
}
-static int sync_start_readtime(int fd, const char *path)
-{
- syncmsg msg;
- int len = strlen(path);
-
- msg.req.id = ID_STAT;
- msg.req.namelen = htoll(len);
-
- if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
- !WriteFdExactly(fd, path, len)) {
- return -1;
- }
-
- return 0;
+static bool sync_start_stat(SyncConnection& sc, const char* path) {
+ return SendRequest(sc.fd, ID_STAT, path);
}
-static int sync_finish_readtime(int fd, unsigned int *timestamp,
- unsigned int *mode, unsigned int *size)
-{
+static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp,
+ unsigned int* mode, unsigned int* size) {
syncmsg msg;
+ if (!ReadFdExactly(sc.fd, &msg.stat, sizeof(msg.stat)) || msg.stat.id != ID_STAT) {
+ return false;
+ }
- if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat)))
- return -1;
+ if (timestamp) *timestamp = msg.stat.time;
+ if (mode) *mode = msg.stat.mode;
+ if (size) *size = msg.stat.size;
- if(msg.stat.id != ID_STAT)
- return -1;
-
- *timestamp = ltohl(msg.stat.time);
- *mode = ltohl(msg.stat.mode);
- *size = ltohl(msg.stat.size);
-
- return 0;
+ return true;
}
-static int sync_readmode(int fd, const char* path, unsigned* mode) {
- syncmsg msg;
- int len = strlen(path);
-
- msg.req.id = ID_STAT;
- msg.req.namelen = htoll(len);
-
- if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
- !WriteFdExactly(fd, path, len)) {
- return -1;
- }
-
- if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) {
- return -1;
- }
-
- if(msg.stat.id != ID_STAT) {
- return -1;
- }
-
- *mode = ltohl(msg.stat.mode);
- return 0;
+static bool sync_stat(SyncConnection& sc, const char* path,
+ unsigned int* timestamp, unsigned int* mode, unsigned int* size) {
+ return sync_start_stat(sc, path) && sync_finish_stat(sc, timestamp, mode, size);
}
-static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, bool show_progress)
-{
- int lfd, err = 0;
+static int write_data_file(SyncConnection& sc, const char* path, syncsendbuf* sbuf, bool show_progress) {
+ int err = 0;
unsigned long long size = 0;
- lfd = adb_open(path, O_RDONLY);
- if(lfd < 0) {
- fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno));
+ int lfd = adb_open(path, O_RDONLY);
+ if (lfd < 0) {
+ fprintf(stderr, "cannot open '%s': %s\n", path, strerror(errno));
return -1;
}
@@ -231,7 +193,7 @@
// Determine local file size.
struct stat st;
if (stat(path, &st)) {
- fprintf(stderr,"cannot stat '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "cannot stat '%s': %s\n", path, strerror(errno));
return -1;
}
@@ -239,29 +201,22 @@
}
sbuf->id = ID_DATA;
- for(;;) {
- int ret;
-
- ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX);
- if(!ret)
- break;
-
- if(ret < 0) {
- if(errno == EINTR)
- continue;
- fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));
+ while (true) {
+ int ret = adb_read(lfd, sbuf->data, sc.max);
+ if (ret <= 0) {
+ if (ret < 0) fprintf(stderr, "cannot read '%s': %s\n", path, strerror(errno));
break;
}
- sbuf->size = htoll(ret);
- if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + ret)){
+ sbuf->size = ret;
+ if (!WriteFdExactly(sc.fd, sbuf, sizeof(unsigned) * 2 + ret)) {
err = -1;
break;
}
- total_bytes += ret;
+ sc.total_bytes += ret;
if (show_progress) {
- print_transfer_progress(total_bytes, size);
+ print_transfer_progress(sc.total_bytes, size);
}
}
@@ -269,176 +224,98 @@
return err;
}
-static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf,
- bool show_progress)
-{
- int err = 0;
- int total = 0;
-
- sbuf->id = ID_DATA;
- while (total < size) {
- int count = size - total;
- if (count > SYNC_DATA_MAX) {
- count = SYNC_DATA_MAX;
- }
-
- memcpy(sbuf->data, &file_buffer[total], count);
- sbuf->size = htoll(count);
- if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + count)){
- err = -1;
- break;
- }
- total += count;
- total_bytes += count;
-
- if (show_progress) {
- print_transfer_progress(total, size);
- }
- }
-
- return err;
-}
-
#if defined(_WIN32)
-extern int write_data_link(int fd, const char *path, syncsendbuf *sbuf) __attribute__((error("no symlinks on Windows")));
+extern int write_data_link(SyncConnection& sc, const char* path, syncsendbuf* sbuf) __attribute__((error("no symlinks on Windows")));
#else
-static int write_data_link(int fd, const char *path, syncsendbuf *sbuf)
-{
- int len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);
+static int write_data_link(SyncConnection& sc, const char* path, syncsendbuf* sbuf) {
+ ssize_t len = readlink(path, sbuf->data, sc.max - 1);
if (len < 0) {
fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));
return -1;
}
sbuf->data[len] = '\0';
- sbuf->size = htoll(len + 1);
+ sbuf->size = len + 1;
sbuf->id = ID_DATA;
- if (!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + len + 1)) {
+ if (!WriteFdExactly(sc.fd, sbuf, sizeof(unsigned) * 2 + len + 1)) {
return -1;
}
- total_bytes += len + 1;
+ sc.total_bytes += len + 1;
return 0;
}
#endif
-static int sync_send(int fd, const char *lpath, const char *rpath,
- unsigned mtime, mode_t mode, bool show_progress)
+static bool sync_send(SyncConnection& sc, const char *lpath, const char *rpath,
+ unsigned mtime, mode_t mode, bool show_progress)
{
+ syncsendbuf* sbuf = &send_buffer;
+
+ std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
+ if (!SendRequest(sc.fd, ID_SEND, path_and_mode.c_str())) goto fail;
+
+ if (S_ISREG(mode)) {
+ write_data_file(sc, lpath, sbuf, show_progress);
+ } else if (S_ISLNK(mode)) {
+ write_data_link(sc, lpath, sbuf);
+ } else {
+ goto fail;
+ }
+
syncmsg msg;
- int len, r;
- syncsendbuf *sbuf = &send_buffer;
- char* file_buffer = NULL;
- int size = 0;
- char tmp[64];
-
- len = strlen(rpath);
- if(len > 1024) goto fail;
-
- snprintf(tmp, sizeof(tmp), ",%d", mode);
- r = strlen(tmp);
-
- msg.req.id = ID_SEND;
- msg.req.namelen = htoll(len + r);
-
- if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
- !WriteFdExactly(fd, rpath, len) || !WriteFdExactly(fd, tmp, r)) {
- free(file_buffer);
- goto fail;
- }
-
- if (file_buffer) {
- write_data_buffer(fd, file_buffer, size, sbuf, show_progress);
- free(file_buffer);
- } else if (S_ISREG(mode))
- write_data_file(fd, lpath, sbuf, show_progress);
- else if (S_ISLNK(mode))
- write_data_link(fd, lpath, sbuf);
- else
- goto fail;
-
msg.data.id = ID_DONE;
- msg.data.size = htoll(mtime);
- if(!WriteFdExactly(fd, &msg.data, sizeof(msg.data)))
- goto fail;
+ msg.data.size = mtime;
+ if (!WriteFdExactly(sc.fd, &msg.data, sizeof(msg.data))) goto fail;
- if(!ReadFdExactly(fd, &msg.status, sizeof(msg.status)))
- return -1;
+ if (!ReadFdExactly(sc.fd, &msg.status, sizeof(msg.status))) goto fail;
- if(msg.status.id != ID_OKAY) {
- if(msg.status.id == ID_FAIL) {
- len = ltohl(msg.status.msglen);
- if(len > 256) len = 256;
- if(!ReadFdExactly(fd, sbuf->data, len)) {
- return -1;
- }
+ if (msg.status.id != ID_OKAY) {
+ if (msg.status.id == ID_FAIL) {
+ size_t len = msg.status.msglen;
+ if (len > 256) len = 256;
+ if (!ReadFdExactly(sc.fd, sbuf->data, len)) goto fail;
sbuf->data[len] = 0;
- } else
+ } else {
strcpy(sbuf->data, "unknown reason");
-
- fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data);
- return -1;
+ }
+ fprintf(stderr, "failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data);
+ return false;
}
- return 0;
+ return true;
fail:
- fprintf(stderr,"protocol failure\n");
- adb_close(fd);
- return -1;
+ fprintf(stderr, "protocol failure\n");
+ return false;
}
-static int sync_recv(int fd, const char* rpath, const char* lpath, bool show_progress) {
+static int sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
syncmsg msg;
- int len;
int lfd = -1;
char *buffer = send_buffer.data;
unsigned id;
- unsigned long long size = 0;
- len = strlen(rpath);
- if(len > 1024) return -1;
+ size_t len = strlen(rpath);
+ if (len > 1024) return -1;
+ unsigned size = 0;
if (show_progress) {
- // Determine remote file size.
- syncmsg stat_msg;
- stat_msg.req.id = ID_STAT;
- stat_msg.req.namelen = htoll(len);
-
- if (!WriteFdExactly(fd, &stat_msg.req, sizeof(stat_msg.req)) ||
- !WriteFdExactly(fd, rpath, len)) {
- return -1;
- }
-
- if (!ReadFdExactly(fd, &stat_msg.stat, sizeof(stat_msg.stat))) {
- return -1;
- }
-
- if (stat_msg.stat.id != ID_STAT) return -1;
-
- size = ltohl(stat_msg.stat.size);
+ if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return -1;
}
- msg.req.id = ID_RECV;
- msg.req.namelen = htoll(len);
- if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
- !WriteFdExactly(fd, rpath, len)) {
- return -1;
- }
+ if (!SendRequest(sc.fd, ID_RECV, rpath)) return -1;
+ if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) return -1;
- if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) {
- return -1;
- }
id = msg.data.id;
- if((id == ID_DATA) || (id == ID_DONE)) {
+ if (id == ID_DATA || id == ID_DONE) {
adb_unlink(lpath);
mkdirs(lpath);
lfd = adb_creat(lpath, 0644);
if(lfd < 0) {
- fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno));
+ fprintf(stderr, "cannot create '%s': %s\n", lpath, strerror(errno));
return -1;
}
goto handle_data;
@@ -446,37 +323,37 @@
goto remote_error;
}
- for(;;) {
- if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) {
+ while (true) {
+ if(!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
return -1;
}
id = msg.data.id;
handle_data:
- len = ltohl(msg.data.size);
- if(id == ID_DONE) break;
- if(id != ID_DATA) goto remote_error;
- if(len > SYNC_DATA_MAX) {
- fprintf(stderr,"data overrun\n");
+ len = msg.data.size;
+ if (id == ID_DONE) break;
+ if (id != ID_DATA) goto remote_error;
+ if (len > sc.max) {
+ fprintf(stderr, "msg.data.size too large: %zu (max %zu)\n", len, sc.max);
adb_close(lfd);
return -1;
}
- if(!ReadFdExactly(fd, buffer, len)) {
+ if(!ReadFdExactly(sc.fd, buffer, len)) {
adb_close(lfd);
return -1;
}
if(!WriteFdExactly(lfd, buffer, len)) {
- fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno));
+ fprintf(stderr, "cannot write '%s': %s\n", rpath, strerror(errno));
adb_close(lfd);
return -1;
}
- total_bytes += len;
+ sc.total_bytes += len;
if (show_progress) {
- print_transfer_progress(total_bytes, size);
+ print_transfer_progress(sc.total_bytes, size);
}
}
@@ -488,9 +365,9 @@
adb_unlink(lpath);
if(id == ID_FAIL) {
- len = ltohl(msg.data.size);
+ len = msg.data.size;
if(len > 256) len = 256;
- if(!ReadFdExactly(fd, buffer, len)) {
+ if(!ReadFdExactly(sc.fd, buffer, len)) {
return -1;
}
buffer[len] = 0;
@@ -498,31 +375,20 @@
memcpy(buffer, &id, 4);
buffer[4] = 0;
}
- fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer);
+ fprintf(stderr, "failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer);
return 0;
}
-/* --- */
static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
- const char *name, void *cookie)
-{
+ const char* name, void* /*cookie*/) {
printf("%08x %08x %08x %s\n", mode, size, time, name);
}
-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;
- }
+bool do_sync_ls(const char* path) {
+ SyncConnection sc;
+ if (!sc.IsValid()) return false;
- if (sync_ls(fd, path, do_sync_ls_cb, 0)) {
- return 1;
- }
-
- sync_quit(fd);
- return 0;
+ return sync_ls(sc.fd, path, do_sync_ls_cb, 0);
}
struct copyinfo
@@ -545,7 +411,7 @@
copyinfo *ci = reinterpret_cast<copyinfo*>(malloc(sizeof(copyinfo) + ssize + dsize));
if(ci == 0) {
- fprintf(stderr,"out of memory\n");
+ fprintf(stderr, "out of memory\n");
abort();
}
@@ -562,54 +428,41 @@
return ci;
}
+static bool IsDotOrDotDot(const char* name) {
+ return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
+}
-static int local_build_list(copyinfo **filelist,
- const char *lpath, const char *rpath)
-{
- DIR *d;
- struct dirent *de;
- struct stat st;
+static int local_build_list(copyinfo** filelist, const char* lpath, const char* rpath) {
copyinfo *dirlist = 0;
copyinfo *ci, *next;
- d = opendir(lpath);
- if(d == 0) {
- fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));
+ std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(lpath), closedir);
+ if (!dir) {
+ fprintf(stderr, "cannot open '%s': %s\n", lpath, strerror(errno));
return -1;
}
- while((de = readdir(d))) {
+ dirent *de;
+ while ((de = readdir(dir.get()))) {
+ if (IsDotOrDotDot(de->d_name)) continue;
+
char stat_path[PATH_MAX];
- char *name = de->d_name;
-
- if(name[0] == '.') {
- if(name[1] == 0) continue;
- if((name[1] == '.') && (name[2] == 0)) continue;
- }
-
- /*
- * We could use d_type if HAVE_DIRENT_D_TYPE is defined, but reiserfs
- * always returns DT_UNKNOWN, so we just use stat() for all cases.
- */
- if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path))
+ if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) {
+ fprintf(stderr, "skipping long path '%s%s'\n", lpath, de->d_name);
continue;
+ }
strcpy(stat_path, lpath);
strcat(stat_path, de->d_name);
- if(!lstat(stat_path, &st)) {
+ struct stat st;
+ if (!lstat(stat_path, &st)) {
if (S_ISDIR(st.st_mode)) {
- ci = mkcopyinfo(lpath, rpath, name, 1);
+ ci = mkcopyinfo(lpath, rpath, de->d_name, 1);
ci->next = dirlist;
dirlist = ci;
} else {
- ci = mkcopyinfo(lpath, rpath, name, 0);
- if(lstat(ci->src, &st)) {
- fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno));
- free(ci);
- closedir(d);
- return -1;
- }
- if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
+ ci = mkcopyinfo(lpath, rpath, de->d_name, 0);
+ if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
fprintf(stderr, "skipping special file '%s'\n", ci->src);
free(ci);
} else {
@@ -625,9 +478,9 @@
}
}
- closedir(d);
-
- for(ci = dirlist; ci != 0; ci = next) {
+ // Close this directory and recurse.
+ dir.reset();
+ for (ci = dirlist; ci != 0; ci = next) {
next = ci->next;
local_build_list(filelist, ci->src, ci->dst);
free(ci);
@@ -636,60 +489,55 @@
return 0;
}
-
-static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, int checktimestamps, int listonly)
-{
+static bool copy_local_dir_remote(SyncConnection& sc, const char* lpath, const char* rpath,
+ bool check_timestamps, bool list_only) {
copyinfo *filelist = 0;
copyinfo *ci, *next;
int pushed = 0;
int skipped = 0;
- if((lpath[0] == 0) || (rpath[0] == 0)) return -1;
- if(lpath[strlen(lpath) - 1] != '/') {
+ if ((lpath[0] == 0) || (rpath[0] == 0)) return false;
+ if (lpath[strlen(lpath) - 1] != '/') {
int tmplen = strlen(lpath)+2;
char *tmp = reinterpret_cast<char*>(malloc(tmplen));
- if(tmp == 0) return -1;
+ if(tmp == 0) return false;
snprintf(tmp, tmplen, "%s/",lpath);
lpath = tmp;
}
- if(rpath[strlen(rpath) - 1] != '/') {
+ if (rpath[strlen(rpath) - 1] != '/') {
int tmplen = strlen(rpath)+2;
char *tmp = reinterpret_cast<char*>(malloc(tmplen));
- if(tmp == 0) return -1;
+ if(tmp == 0) return false;
snprintf(tmp, tmplen, "%s/",rpath);
rpath = tmp;
}
- if(local_build_list(&filelist, lpath, rpath)) {
- return -1;
+ if (local_build_list(&filelist, lpath, rpath)) {
+ return false;
}
- if(checktimestamps){
- for(ci = filelist; ci != 0; ci = ci->next) {
- if(sync_start_readtime(fd, ci->dst)) {
- return 1;
- }
+ if (check_timestamps) {
+ for (ci = filelist; ci != 0; ci = ci->next) {
+ if (!sync_start_stat(sc, ci->dst)) return false;
}
for(ci = filelist; ci != 0; ci = ci->next) {
unsigned int timestamp, mode, size;
- if(sync_finish_readtime(fd, ×tamp, &mode, &size))
- return 1;
- if(size == ci->size) {
+ if (!sync_finish_stat(sc, ×tamp, &mode, &size)) return false;
+ if (size == ci->size) {
/* for links, we cannot update the atime/mtime */
- if((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
- (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
+ if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
+ (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) {
ci->flag = 1;
+ }
}
}
}
- for(ci = filelist; ci != 0; ci = next) {
+ for (ci = filelist; ci != 0; ci = next) {
next = ci->next;
- if(ci->flag == 0) {
- fprintf(stderr,"%spush: %s -> %s\n", listonly ? "would " : "", ci->src, ci->dst);
- if(!listonly &&
- sync_send(fd, ci->src, ci->dst, ci->time, ci->mode,
- 0 /* no show progress */)) {
- return 1;
+ if (ci->flag == 0) {
+ fprintf(stderr, "%spush: %s -> %s\n", list_only ? "would " : "", ci->src, ci->dst);
+ if (!list_only && !sync_send(sc, ci->src, ci->dst, ci->time, ci->mode, false)) {
+ return false;
}
pushed++;
} else {
@@ -698,55 +546,37 @@
free(ci);
}
- fprintf(stderr,"%d file%s pushed. %d file%s skipped.\n",
+ fprintf(stderr, "%d file%s pushed. %d file%s skipped.\n",
pushed, (pushed == 1) ? "" : "s",
skipped, (skipped == 1) ? "" : "s");
- return 0;
+ return true;
}
-
-int do_sync_push(const char* lpath, const char* rpath, bool show_progress) {
- std::string error;
- int fd = adb_connect("sync:", &error);
- if (fd < 0) {
- fprintf(stderr,"error: %s\n", error.c_str());
- return 1;
- }
+bool do_sync_push(const char* lpath, const char* rpath, bool show_progress) {
+ SyncConnection sc;
+ if (!sc.IsValid()) return false;
struct stat st;
if (stat(lpath, &st)) {
- fprintf(stderr,"cannot stat '%s': %s\n", lpath, strerror(errno));
- sync_quit(fd);
- return 1;
+ fprintf(stderr, "cannot stat '%s': %s\n", lpath, strerror(errno));
+ return false;
}
if (S_ISDIR(st.st_mode)) {
- BEGIN();
- if (copy_local_dir_remote(fd, lpath, rpath, 0, 0)) {
- return 1;
- }
- } else {
- unsigned mode;
- if (sync_readmode(fd, rpath, &mode)) {
- return 1;
- }
- std::string path_holder;
- if ((mode != 0) && S_ISDIR(mode)) {
- // If we're copying a local file to a remote directory,
- // we really want to copy to remote_dir + "/" + local_filename.
- path_holder = android::base::StringPrintf("%s/%s", rpath, adb_basename(lpath).c_str());
- rpath = path_holder.c_str();
- }
- BEGIN();
- if (sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, show_progress)) {
- return 1;
- }
+ return copy_local_dir_remote(sc, lpath, rpath, false, false);
}
- END();
- sync_quit(fd);
- return 0;
+ unsigned mode;
+ if (!sync_stat(sc, rpath, nullptr, &mode, nullptr)) return false;
+ std::string path_holder;
+ if (mode != 0 && S_ISDIR(mode)) {
+ // If we're copying a local file to a remote directory,
+ // we really want to copy to remote_dir + "/" + local_filename.
+ path_holder = android::base::StringPrintf("%s/%s", rpath, adb_basename(lpath).c_str());
+ rpath = path_holder.c_str();
+ }
+ return sync_send(sc, lpath, rpath, st.st_mtime, st.st_mode, show_progress);
}
@@ -766,11 +596,8 @@
if (S_ISDIR(mode)) {
copyinfo **dirlist = args->dirlist;
- /* Don't try recursing down "." or ".." */
- if (name[0] == '.') {
- if (name[1] == '\0') return;
- if ((name[1] == '.') && (name[2] == '\0')) return;
- }
+ // Don't try recursing down "." or "..".
+ if (IsDotOrDotDot(name)) return;
ci = mkcopyinfo(args->rpath, args->lpath, name, 1);
ci->next = *dirlist;
@@ -789,9 +616,8 @@
}
}
-static int remote_build_list(int syncfd, copyinfo **filelist,
- const char *rpath, const char *lpath)
-{
+static bool remote_build_list(int syncfd, copyinfo **filelist,
+ const char *rpath, const char *lpath) {
copyinfo *dirlist = NULL;
sync_ls_build_list_cb_args args;
@@ -800,22 +626,22 @@
args.rpath = rpath;
args.lpath = lpath;
- /* Put the files/dirs in rpath on the lists. */
- if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) {
- return 1;
+ // Put the files/dirs in rpath on the lists.
+ if (!sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) {
+ return false;
}
- /* Recurse into each directory we found. */
+ // Recurse into each directory we found.
while (dirlist != NULL) {
copyinfo *next = dirlist->next;
- if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) {
- return 1;
+ if (!remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) {
+ return false;
}
free(dirlist);
dirlist = next;
}
- return 0;
+ return true;
}
static int set_time_and_mode(const char *lpath, time_t time, unsigned int mode)
@@ -831,101 +657,57 @@
return r1 ? : r2;
}
-/* Return a copy of the path string with / appended if needed */
-static char *add_slash_to_path(const char *path)
-{
- if (path[strlen(path) - 1] != '/') {
- size_t len = strlen(path) + 2;
- char *path_with_slash = reinterpret_cast<char*>(malloc(len));
- if (path_with_slash == NULL)
- return NULL;
- snprintf(path_with_slash, len, "%s/", path);
- return path_with_slash;
- } else {
- return strdup(path);
- }
-}
+static bool copy_remote_dir_local(SyncConnection& sc, const char* rpath, const char* lpath,
+ int copy_attrs) {
+ // Make sure that both directory paths end in a slash.
+ std::string rpath_clean(rpath);
+ std::string lpath_clean(lpath);
+ if (rpath_clean.empty() || lpath_clean.empty()) return false;
+ if (rpath_clean.back() != '/') rpath_clean.push_back('/');
+ if (lpath_clean.back() != '/') lpath_clean.push_back('/');
-static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
- int copy_attrs)
-{
- copyinfo *filelist = 0;
- copyinfo *ci, *next;
+ // Recursively build the list of files to copy.
+ fprintf(stderr, "pull: building file list...\n");
+ copyinfo* filelist = nullptr;
+ if (!remote_build_list(sc.fd, &filelist, rpath_clean.c_str(), lpath_clean.c_str())) return false;
+
int pulled = 0;
int skipped = 0;
- char *rpath_clean = NULL;
- char *lpath_clean = NULL;
- int ret = 0;
-
- if (rpath[0] == '\0' || lpath[0] == '\0') {
- ret = -1;
- goto finish;
- }
-
- /* Make sure that both directory paths end in a slash. */
- rpath_clean = add_slash_to_path(rpath);
- if (!rpath_clean) {
- ret = -1;
- goto finish;
- }
- lpath_clean = add_slash_to_path(lpath);
- if (!lpath_clean) {
- ret = -1;
- goto finish;
- }
-
- /* Recursively build the list of files to copy. */
- fprintf(stderr, "pull: building file list...\n");
- if (remote_build_list(fd, &filelist, rpath_clean, lpath_clean)) {
- ret = -1;
- goto finish;
- }
-
- for (ci = filelist; ci != 0; ci = next) {
- next = ci->next;
+ copyinfo* ci = filelist;
+ while (ci) {
+ copyinfo* next = ci->next;
if (ci->flag == 0) {
fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
- if (sync_recv(fd, ci->src, ci->dst, 0 /* no show progress */)) {
- ret = -1;
- goto finish;
+ if (sync_recv(sc, ci->src, ci->dst, false)) {
+ return false;
}
if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) {
- ret = -1;
- goto finish;
+ return false;
}
pulled++;
} else {
skipped++;
}
free(ci);
+ ci = next;
}
fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
pulled, (pulled == 1) ? "" : "s",
skipped, (skipped == 1) ? "" : "s");
-
-finish:
- free(lpath_clean);
- free(rpath_clean);
- return ret;
+ return true;
}
-int do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs) {
- std::string error;
- int fd = adb_connect("sync:", &error);
- if (fd < 0) {
- fprintf(stderr,"error: %s\n", error.c_str());
- return 1;
- }
+bool do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs) {
+ SyncConnection sc;
+ if (!sc.IsValid()) return false;
unsigned mode, time;
- if (sync_readtime(fd, rpath, &time, &mode)) {
- return 1;
- }
+ if (!sync_stat(sc, rpath, &time, &mode, nullptr)) return false;
if (mode == 0) {
- fprintf(stderr,"remote object '%s' does not exist\n", rpath);
- return 1;
+ fprintf(stderr, "remote object '%s' does not exist\n", rpath);
+ return false;
}
if (S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
@@ -939,44 +721,27 @@
lpath = path_holder.c_str();
}
}
- BEGIN();
- if (sync_recv(fd, rpath, lpath, show_progress)) {
- return 1;
+ if (sync_recv(sc, rpath, lpath, show_progress)) {
+ return false;
} else {
if (copy_attrs && set_time_and_mode(lpath, time, mode)) {
- return 1;
+ return false;
}
}
- } else if(S_ISDIR(mode)) {
- BEGIN();
- if (copy_remote_dir_local(fd, rpath, lpath, copy_attrs)) {
- return 1;
- }
- } else {
- fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
- return 1;
+ return true;
+ } else if (S_ISDIR(mode)) {
+ return copy_remote_dir_local(sc, rpath, lpath, copy_attrs);
}
- END();
- sync_quit(fd);
- return 0;
+
+ fprintf(stderr, "remote object '%s' not a file or directory\n", rpath);
+ return false;
}
-int do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only)
-{
+bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) {
fprintf(stderr, "syncing %s...\n", rpath.c_str());
- std::string error;
- int fd = adb_connect("sync:", &error);
- if (fd < 0) {
- fprintf(stderr, "error: %s\n", error.c_str());
- return 1;
- }
+ SyncConnection sc;
+ if (!sc.IsValid()) return false;
- BEGIN();
- if (copy_local_dir_remote(fd, lpath.c_str(), rpath.c_str(), 1, list_only)) {
- return 1;
- }
- END();
- sync_quit(fd);
- return 0;
+ return copy_local_dir_remote(sc, lpath.c_str(), rpath.c_str(), true, list_only);
}
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index a503327..536dbbc 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -34,6 +34,7 @@
#include "adb_io.h"
#include "private/android_filesystem_config.h"
+#include <base/stringprintf.h>
#include <base/strings.h>
static bool should_use_fs_config(const std::string& path) {
@@ -70,44 +71,30 @@
if (chown(partial_path.c_str(), uid, gid) == -1) {
return false;
}
+ // Not all filesystems support setting SELinux labels. http://b/23530370.
selinux_android_restorecon(partial_path.c_str(), 0);
}
}
return true;
}
-static int do_stat(int s, const char *path)
-{
+static bool do_stat(int s, const char* path) {
syncmsg msg;
- struct stat st;
-
msg.stat.id = ID_STAT;
- if(lstat(path, &st)) {
- msg.stat.mode = 0;
- msg.stat.size = 0;
- msg.stat.time = 0;
- } else {
- msg.stat.mode = htoll(st.st_mode);
- msg.stat.size = htoll(st.st_size);
- msg.stat.time = htoll(st.st_mtime);
- }
+ struct stat st;
+ memset(&st, 0, sizeof(st));
+ // TODO: add a way to report that the stat failed!
+ lstat(path, &st);
+ msg.stat.mode = st.st_mode;
+ msg.stat.size = st.st_size;
+ msg.stat.time = st.st_mtime;
- return WriteFdExactly(s, &msg.stat, sizeof(msg.stat)) ? 0 : -1;
+ return WriteFdExactly(s, &msg.stat, sizeof(msg.stat));
}
-static int do_list(int s, const char *path)
-{
- struct dirent *de;
- struct stat st;
-
- char tmp[1024 + 256 + 1];
- char *fname;
-
- size_t len = strlen(path);
- memcpy(tmp, path, len);
- tmp[len] = '/';
- fname = tmp + len + 1;
+static bool do_list(int s, const char* path) {
+ dirent* de;
syncmsg msg;
msg.dent.id = ID_DENT;
@@ -116,22 +103,19 @@
if (!d) goto done;
while ((de = readdir(d.get()))) {
- int len = strlen(de->d_name);
+ std::string filename(android::base::StringPrintf("%s/%s", path, de->d_name));
- /* not supposed to be possible, but
- if it does happen, let's not buffer overrun */
- if(len > 256) continue;
+ struct stat st;
+ if (lstat(filename.c_str(), &st) == 0) {
+ size_t d_name_length = strlen(de->d_name);
+ msg.dent.mode = st.st_mode;
+ msg.dent.size = st.st_size;
+ msg.dent.time = st.st_mtime;
+ msg.dent.namelen = d_name_length;
- strcpy(fname, de->d_name);
- if(lstat(tmp, &st) == 0) {
- msg.dent.mode = htoll(st.st_mode);
- msg.dent.size = htoll(st.st_size);
- msg.dent.time = htoll(st.st_mtime);
- msg.dent.namelen = htoll(len);
-
- if(!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
- !WriteFdExactly(s, de->d_name, len)) {
- return -1;
+ if (!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
+ !WriteFdExactly(s, de->d_name, d_name_length)) {
+ return false;
}
}
}
@@ -142,255 +126,215 @@
msg.dent.size = 0;
msg.dent.time = 0;
msg.dent.namelen = 0;
- return WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1;
+ return WriteFdExactly(s, &msg.dent, sizeof(msg.dent));
}
-static int fail_message(int s, const char *reason)
-{
+static bool SendSyncFail(int fd, const std::string& reason) {
+ D("sync: failure: %s\n", reason.c_str());
+
syncmsg msg;
- int len = strlen(reason);
-
- D("sync: failure: %s\n", reason);
-
msg.data.id = ID_FAIL;
- msg.data.size = htoll(len);
- if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) ||
- !WriteFdExactly(s, reason, len)) {
- return -1;
- } else {
- return 0;
- }
+ msg.data.size = reason.size();
+ return WriteFdExactly(fd, &msg.data, sizeof(msg.data)) && WriteFdExactly(fd, reason);
}
-static int fail_errno(int s)
-{
- return fail_message(s, strerror(errno));
+static bool SendSyncFailErrno(int fd, const std::string& reason) {
+ return SendSyncFail(fd, android::base::StringPrintf("%s: %s", reason.c_str(), strerror(errno)));
}
-static int handle_send_file(int s, char *path, uid_t uid,
- gid_t gid, mode_t mode, char *buffer, bool do_unlink)
-{
+static bool handle_send_file(int s, const char* path, uid_t uid,
+ gid_t gid, mode_t mode, std::vector<char>& buffer, bool do_unlink) {
syncmsg msg;
unsigned int timestamp = 0;
- int fd;
- fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
- if(fd < 0 && errno == ENOENT) {
+ int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
+ if (fd < 0 && errno == ENOENT) {
if (!secure_mkdirs(path)) {
- if(fail_errno(s))
- return -1;
- fd = -1;
- } else {
- fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
+ SendSyncFailErrno(s, "secure_mkdirs failed");
+ goto fail;
}
+ fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
}
- if(fd < 0 && errno == EEXIST) {
+ if (fd < 0 && errno == EEXIST) {
fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
}
- if(fd < 0) {
- if(fail_errno(s))
- return -1;
- fd = -1;
+ if (fd < 0) {
+ SendSyncFailErrno(s, "couldn't create file");
+ goto fail;
} else {
- if(fchown(fd, uid, gid) != 0) {
- fail_errno(s);
- errno = 0;
+ if (fchown(fd, uid, gid) == -1) {
+ SendSyncFailErrno(s, "fchown failed");
+ goto fail;
}
- /*
- * fchown clears the setuid bit - restore it if present.
- * Ignore the result of calling fchmod. It's not supported
- * by all filesystems. b/12441485
- */
+ // Not all filesystems support setting SELinux labels. http://b/23530370.
+ selinux_android_restorecon(path, 0);
+
+ // fchown clears the setuid bit - restore it if present.
+ // Ignore the result of calling fchmod. It's not supported
+ // by all filesystems. b/12441485
fchmod(fd, mode);
}
- for(;;) {
+ while (true) {
unsigned int len;
- if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
- goto fail;
+ if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;
- if(msg.data.id != ID_DATA) {
- if(msg.data.id == ID_DONE) {
- timestamp = ltohl(msg.data.size);
+ if (msg.data.id != ID_DATA) {
+ if (msg.data.id == ID_DONE) {
+ timestamp = msg.data.size;
break;
}
- fail_message(s, "invalid data message");
+ SendSyncFail(s, "invalid data message");
goto fail;
}
- len = ltohl(msg.data.size);
- if(len > SYNC_DATA_MAX) {
- fail_message(s, "oversize data message");
+ len = msg.data.size;
+ if (len > buffer.size()) { // TODO: resize buffer?
+ SendSyncFail(s, "oversize data message");
goto fail;
}
- if(!ReadFdExactly(s, buffer, len))
- goto fail;
- if(fd < 0)
- continue;
- if(!WriteFdExactly(fd, buffer, len)) {
- int saved_errno = errno;
- adb_close(fd);
- if (do_unlink) adb_unlink(path);
- fd = -1;
- errno = saved_errno;
- if(fail_errno(s)) return -1;
+ if (!ReadFdExactly(s, &buffer[0], len)) goto fail;
+
+ if (!WriteFdExactly(fd, &buffer[0], len)) {
+ SendSyncFailErrno(s, "write failed");
+ goto fail;
}
}
- if(fd >= 0) {
- struct utimbuf u;
- adb_close(fd);
- selinux_android_restorecon(path, 0);
- u.actime = timestamp;
- u.modtime = timestamp;
- utime(path, &u);
+ adb_close(fd);
- msg.status.id = ID_OKAY;
- msg.status.msglen = 0;
- if(!WriteFdExactly(s, &msg.status, sizeof(msg.status)))
- return -1;
- }
- return 0;
+ utimbuf u;
+ u.actime = timestamp;
+ u.modtime = timestamp;
+ utime(path, &u);
+
+ msg.status.id = ID_OKAY;
+ msg.status.msglen = 0;
+ return WriteFdExactly(s, &msg.status, sizeof(msg.status));
fail:
- if(fd >= 0)
- adb_close(fd);
+ if (fd >= 0) adb_close(fd);
if (do_unlink) adb_unlink(path);
- return -1;
+ return false;
}
#if defined(_WIN32)
-extern int handle_send_link(int s, char *path, char *buffer) __attribute__((error("no symlinks on Windows")));
+extern bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) __attribute__((error("no symlinks on Windows")));
#else
-static int handle_send_link(int s, char *path, char *buffer)
-{
+static bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) {
syncmsg msg;
unsigned int len;
int ret;
- if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
- return -1;
+ if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
- if(msg.data.id != ID_DATA) {
- fail_message(s, "invalid data message: expected ID_DATA");
- return -1;
+ if (msg.data.id != ID_DATA) {
+ SendSyncFail(s, "invalid data message: expected ID_DATA");
+ return false;
}
- len = ltohl(msg.data.size);
- if(len > SYNC_DATA_MAX) {
- fail_message(s, "oversize data message");
- return -1;
+ len = msg.data.size;
+ if (len > buffer.size()) { // TODO: resize buffer?
+ SendSyncFail(s, "oversize data message");
+ return false;
}
- if(!ReadFdExactly(s, buffer, len))
- return -1;
+ if (!ReadFdExactly(s, &buffer[0], len)) return false;
- ret = symlink(buffer, path);
- if(ret && errno == ENOENT) {
+ ret = symlink(&buffer[0], path.c_str());
+ if (ret && errno == ENOENT) {
if (!secure_mkdirs(path)) {
- fail_errno(s);
- return -1;
+ SendSyncFailErrno(s, "secure_mkdirs failed");
+ return false;
}
- ret = symlink(buffer, path);
+ ret = symlink(&buffer[0], path.c_str());
}
- if(ret) {
- fail_errno(s);
- return -1;
+ if (ret) {
+ SendSyncFailErrno(s, "symlink failed");
+ return false;
}
- if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
- return -1;
+ if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
- if(msg.data.id == ID_DONE) {
+ if (msg.data.id == ID_DONE) {
msg.status.id = ID_OKAY;
msg.status.msglen = 0;
- if(!WriteFdExactly(s, &msg.status, sizeof(msg.status)))
- return -1;
+ if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
} else {
- fail_message(s, "invalid data message: expected ID_DONE");
- return -1;
+ SendFail(s, "invalid data message: expected ID_DONE");
+ return false;
}
- return 0;
+ return true;
}
#endif
-static int do_send(int s, char *path, char *buffer)
-{
- unsigned int mode;
- bool is_link = false;
- bool do_unlink;
-
- char* tmp = strrchr(path,',');
- if(tmp) {
- *tmp = 0;
- errno = 0;
- mode = strtoul(tmp + 1, NULL, 0);
- is_link = S_ISLNK((mode_t) mode);
- mode &= 0777;
- }
- if(!tmp || errno) {
- mode = 0644;
- is_link = 0;
- do_unlink = true;
- } else {
- struct stat st;
- /* Don't delete files before copying if they are not "regular" */
- do_unlink = lstat(path, &st) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
- if (do_unlink) {
- adb_unlink(path);
- }
+static bool do_send(int s, const std::string& spec, std::vector<char>& buffer) {
+ // 'spec' is of the form "/some/path,0755". Break it up.
+ size_t comma = spec.find_last_of(',');
+ if (comma == std::string::npos) {
+ SendFail(s, "missing , in ID_SEND");
+ return false;
}
- if (is_link) {
- return handle_send_link(s, path, buffer);
+ std::string path = spec.substr(0, comma);
+
+ errno = 0;
+ mode_t mode = strtoul(spec.substr(comma + 1).c_str(), nullptr, 0);
+ if (errno != 0) {
+ SendFail(s, "bad mode");
+ return false;
}
+ // Don't delete files before copying if they are not "regular" or symlinks.
+ struct stat st;
+ bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
+ if (do_unlink) {
+ adb_unlink(path.c_str());
+ }
+
+ if (S_ISLNK(mode)) {
+ return handle_send_link(s, path.c_str(), buffer);
+ }
+
+ // Copy user permission bits to "group" and "other" permissions.
+ mode &= 0777;
+ mode |= ((mode >> 3) & 0070);
+ mode |= ((mode >> 3) & 0007);
+
uid_t uid = -1;
gid_t gid = -1;
uint64_t cap = 0;
-
- /* copy user permission bits to "group" and "other" permissions */
- mode |= ((mode >> 3) & 0070);
- mode |= ((mode >> 3) & 0007);
-
- tmp = path;
- if(*tmp == '/') {
- tmp++;
- }
if (should_use_fs_config(path)) {
- fs_config(tmp, 0, NULL, &uid, &gid, &mode, &cap);
+ unsigned int broken_api_hack = mode;
+ fs_config(path.c_str(), 0, nullptr, &uid, &gid, &broken_api_hack, &cap);
+ mode = broken_api_hack;
}
- return handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
+ return handle_send_file(s, path.c_str(), uid, gid, mode, buffer, do_unlink);
}
-static int do_recv(int s, const char *path, char *buffer)
-{
- syncmsg msg;
- int fd, r;
-
- fd = adb_open(path, O_RDONLY | O_CLOEXEC);
- if(fd < 0) {
- if(fail_errno(s)) return -1;
- return 0;
+static bool do_recv(int s, const char* path, std::vector<char>& buffer) {
+ int fd = adb_open(path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0) {
+ SendSyncFailErrno(s, "open failed");
+ return false;
}
+ syncmsg msg;
msg.data.id = ID_DATA;
- for(;;) {
- r = adb_read(fd, buffer, SYNC_DATA_MAX);
- if(r <= 0) {
- if(r == 0) break;
- if(errno == EINTR) continue;
- r = fail_errno(s);
+ while (true) {
+ int r = adb_read(fd, &buffer[0], buffer.size());
+ if (r <= 0) {
+ if (r == 0) break;
+ SendSyncFailErrno(s, "read failed");
adb_close(fd);
- return r;
+ return false;
}
- msg.data.size = htoll(r);
- if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) ||
- !WriteFdExactly(s, buffer, r)) {
+ msg.data.size = r;
+ if (!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || !WriteFdExactly(s, &buffer[0], r)) {
adb_close(fd);
- return -1;
+ return false;
}
}
@@ -398,66 +342,62 @@
msg.data.id = ID_DONE;
msg.data.size = 0;
- if(!WriteFdExactly(s, &msg.data, sizeof(msg.data))) {
- return -1;
- }
-
- return 0;
+ return WriteFdExactly(s, &msg.data, sizeof(msg.data));
}
-void file_sync_service(int fd, void *cookie)
-{
- syncmsg msg;
+static bool handle_sync_command(int fd, std::vector<char>& buffer) {
+ D("sync: waiting for request\n");
+
+ SyncRequest request;
+ if (!ReadFdExactly(fd, &request, sizeof(request))) {
+ SendSyncFail(fd, "command read failure");
+ return false;
+ }
+ size_t path_length = request.path_length;
+ if (path_length > 1024) {
+ SendSyncFail(fd, "path too long");
+ return false;
+ }
char name[1025];
- unsigned namelen;
+ if (!ReadFdExactly(fd, name, path_length)) {
+ SendSyncFail(fd, "filename read failure");
+ return false;
+ }
+ name[path_length] = 0;
- char *buffer = reinterpret_cast<char*>(malloc(SYNC_DATA_MAX));
- if(buffer == 0) goto fail;
+ const char* id = reinterpret_cast<const char*>(&request.id);
+ D("sync: '%.4s' '%s'\n", id, name);
- for(;;) {
- D("sync: waiting for command\n");
-
- if(!ReadFdExactly(fd, &msg.req, sizeof(msg.req))) {
- fail_message(fd, "command read failure");
- break;
- }
- namelen = ltohl(msg.req.namelen);
- if(namelen > 1024) {
- fail_message(fd, "invalid namelen");
- break;
- }
- if(!ReadFdExactly(fd, name, namelen)) {
- fail_message(fd, "filename read failure");
- break;
- }
- name[namelen] = 0;
-
- msg.req.namelen = 0;
- D("sync: '%s' '%s'\n", (char*) &msg.req, name);
-
- switch(msg.req.id) {
- case ID_STAT:
- if(do_stat(fd, name)) goto fail;
- break;
- case ID_LIST:
- if(do_list(fd, name)) goto fail;
- break;
- case ID_SEND:
- if(do_send(fd, name, buffer)) goto fail;
- break;
- case ID_RECV:
- if(do_recv(fd, name, buffer)) goto fail;
- break;
- case ID_QUIT:
- goto fail;
- default:
- fail_message(fd, "unknown command");
- goto fail;
- }
+ switch (request.id) {
+ case ID_STAT:
+ if (!do_stat(fd, name)) return false;
+ break;
+ case ID_LIST:
+ if (!do_list(fd, name)) return false;
+ break;
+ case ID_SEND:
+ if (!do_send(fd, name, buffer)) return false;
+ break;
+ case ID_RECV:
+ if (!do_recv(fd, name, buffer)) return false;
+ break;
+ case ID_QUIT:
+ return false;
+ default:
+ SendSyncFail(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
+ id, request.id));
+ return false;
}
-fail:
- if(buffer != 0) free(buffer);
+ return true;
+}
+
+void file_sync_service(int fd, void* cookie) {
+ std::vector<char> buffer(SYNC_DATA_MAX);
+
+ while (handle_sync_command(fd, buffer)) {
+ }
+
D("sync: done\n");
adb_close(fd);
}
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 1d3e3bd..67ed3fc 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -19,14 +19,10 @@
#include <string>
-#define htoll(x) (x)
-#define ltohl(x) (x)
-
#define MKID(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
#define ID_STAT MKID('S','T','A','T')
#define ID_LIST MKID('L','I','S','T')
-#define ID_ULNK MKID('U','L','N','K')
#define ID_SEND MKID('S','E','N','D')
#define ID_RECV MKID('R','E','C','V')
#define ID_DENT MKID('D','E','N','T')
@@ -36,41 +32,41 @@
#define ID_FAIL MKID('F','A','I','L')
#define ID_QUIT MKID('Q','U','I','T')
+struct SyncRequest {
+ uint32_t id; // ID_STAT, et cetera.
+ uint32_t path_length; // <= 1024
+ // Followed by 'path_length' bytes of path (not NUL-terminated).
+} __attribute__((packed)) ;
+
union syncmsg {
- unsigned id;
- struct {
- unsigned id;
- unsigned namelen;
- } req;
- struct {
+ struct __attribute__((packed)) {
unsigned id;
unsigned mode;
unsigned size;
unsigned time;
} stat;
- struct {
+ struct __attribute__((packed)) {
unsigned id;
unsigned mode;
unsigned size;
unsigned time;
unsigned namelen;
} dent;
- struct {
+ struct __attribute__((packed)) {
unsigned id;
unsigned size;
} data;
- struct {
+ struct __attribute__((packed)) {
unsigned id;
unsigned msglen;
} status;
-} ;
+};
-
-void file_sync_service(int fd, void *cookie);
-int do_sync_ls(const char *path);
-int do_sync_push(const char *lpath, const char *rpath, bool show_progress);
-int do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
-int do_sync_pull(const char *rpath, const char *lpath, bool show_progress, int pullTime);
+void file_sync_service(int fd, void* cookie);
+bool do_sync_ls(const char* path);
+bool do_sync_push(const char* lpath, const char* rpath, bool show_progress);
+bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
+bool do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs);
#define SYNC_DATA_MAX (64*1024)
diff --git a/adb/services.cpp b/adb/services.cpp
index 63a0a76..c8c2d54 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -59,6 +59,10 @@
void *cookie;
};
+enum class SubprocessType {
+ kPty,
+ kRaw,
+};
void *service_bootstrap_func(void *x)
{
@@ -389,17 +393,27 @@
}
}
-static int create_subproc_thread(const char *name, bool pty = false) {
+// Starts a subprocess and spawns a thread to wait for the subprocess to finish
+// and trigger the necessary cleanup.
+//
+// |name| is the command to execute in the subprocess; empty string will start
+// an interactive session.
+// |type| selects between a PTY or raw subprocess.
+//
+// Returns an open file descriptor tied to the subprocess stdin/stdout/stderr.
+static int create_subproc_thread(const char *name, SubprocessType type) {
const char *arg0, *arg1;
- if (name == 0 || *name == 0) {
- arg0 = "-"; arg1 = 0;
+ if (*name == '\0') {
+ arg0 = "-";
+ arg1 = nullptr;
} else {
- arg0 = "-c"; arg1 = name;
+ arg0 = "-c";
+ arg1 = name;
}
pid_t pid = -1;
int ret_fd;
- if (pty) {
+ if (type == SubprocessType::kPty) {
ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);
} else {
ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
@@ -424,8 +438,7 @@
}
#endif
-int service_to_fd(const char *name)
-{
+int service_to_fd(const char* name) {
int ret = -1;
if(!strncmp(name, "tcp:", 4)) {
@@ -465,10 +478,17 @@
ret = create_service_thread(framebuffer_service, 0);
} else if (!strncmp(name, "jdwp:", 5)) {
ret = create_jdwp_connection_fd(atoi(name+5));
- } else if(!HOST && !strncmp(name, "shell:", 6)) {
- ret = create_subproc_thread(name + 6, true);
- } else if(!HOST && !strncmp(name, "exec:", 5)) {
- ret = create_subproc_thread(name + 5);
+ } else if(!strncmp(name, "shell:", 6)) {
+ const char* args = name + 6;
+ if (*args) {
+ // Non-interactive session uses a raw subprocess.
+ ret = create_subproc_thread(args, SubprocessType::kRaw);
+ } else {
+ // Interactive session uses a PTY subprocess.
+ ret = create_subproc_thread(args, SubprocessType::kPty);
+ }
+ } else if(!strncmp(name, "exec:", 5)) {
+ ret = create_subproc_thread(name + 5, SubprocessType::kRaw);
} else if(!strncmp(name, "sync:", 5)) {
ret = create_service_thread(file_sync_service, NULL);
} else if(!strncmp(name, "remount:", 8)) {
@@ -483,9 +503,10 @@
ret = create_service_thread(restart_unroot_service, NULL);
} else if(!strncmp(name, "backup:", 7)) {
ret = create_subproc_thread(android::base::StringPrintf("/system/bin/bu backup %s",
- (name + 7)).c_str());
+ (name + 7)).c_str(),
+ SubprocessType::kRaw);
} else if(!strncmp(name, "restore:", 8)) {
- ret = create_subproc_thread("/system/bin/bu restore");
+ ret = create_subproc_thread("/system/bin/bu restore", SubprocessType::kRaw);
} else if(!strncmp(name, "tcpip:", 6)) {
int port;
if (sscanf(name + 6, "%d", &port) != 1) {
@@ -643,8 +664,7 @@
#endif
#if ADB_HOST
-asocket* host_service_to_socket(const char* name, const char *serial)
-{
+asocket* host_service_to_socket(const char* name, const char* serial) {
if (!strcmp(name,"track-devices")) {
return create_device_tracker();
} else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index db552a2..f534d61 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -554,6 +554,9 @@
// POSIX and socket error codes, so this can only meaningfully map so much.
switch ( err ) {
case 0: errno = 0; break;
+ // Mapping WSAEWOULDBLOCK to EAGAIN is absolutely critical because
+ // non-blocking sockets can cause an error code of WSAEWOULDBLOCK and
+ // callers check specifically for EAGAIN.
case WSAEWOULDBLOCK: errno = EAGAIN; break;
case WSAEINTR: errno = EINTR; break;
case WSAEFAULT: errno = EFAULT; break;
@@ -619,8 +622,12 @@
int result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
if (result == SOCKET_ERROR) {
const DWORD err = WSAGetLastError();
- D("recv fd %d failed: %s\n", _fh_to_int(f),
- SystemErrorCodeToString(err).c_str());
+ // 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),
+ SystemErrorCodeToString(err).c_str());
+ }
_socket_set_errno(err);
result = -1;
}
@@ -652,20 +659,10 @@
static int _winsock_init;
static void
-_cleanup_winsock( void )
-{
- // TODO: WSAStartup() might be called multiple times and this won't properly
- // cleanup the right number of times. Plus, WSACleanup() probably doesn't
- // make sense since it might interrupt other threads using Winsock (since
- // our various threads are not explicitly cleanly shutdown at process exit).
- WSACleanup();
-}
-
-static void
_init_winsock( void )
{
// TODO: Multiple threads calling this may potentially cause multiple calls
- // to WSAStartup() and multiple atexit() calls.
+ // to WSAStartup() which offers no real benefit.
if (!_winsock_init) {
WSADATA wsaData;
int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
@@ -673,8 +670,21 @@
fatal( "adb: could not initialize Winsock: %s",
SystemErrorCodeToString( rc ).c_str());
}
- atexit( _cleanup_winsock );
_winsock_init = 1;
+
+ // Note that we do not call atexit() to register WSACleanup to be called
+ // at normal process termination because:
+ // 1) When exit() is called, there are still threads actively using
+ // Winsock because we don't cleanly shutdown all threads, so it
+ // doesn't make sense to call WSACleanup() and may cause problems
+ // with those threads.
+ // 2) A deadlock can occur when exit() holds a C Runtime lock, then it
+ // calls WSACleanup() which tries to unload a DLL, which tries to
+ // grab the LoaderLock. This conflicts with the device_poll_thread
+ // which holds the LoaderLock because AdbWinApi.dll calls
+ // setupapi.dll which tries to load wintrust.dll which tries to load
+ // crypt32.dll which calls atexit() which tries to acquire the C
+ // Runtime lock that the other thread holds.
}
}
@@ -698,14 +708,19 @@
s = socket(AF_INET, type, 0);
if(s == INVALID_SOCKET) {
- *error = SystemErrorCodeToString(WSAGetLastError());
- D("could not create socket: %s\n", error->c_str());
+ *error = android::base::StringPrintf("cannot create socket: %s",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
+ D("%s\n", error->c_str());
return -1;
}
f->fh_socket = s;
if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
- *error = SystemErrorCodeToString(WSAGetLastError());
+ // Save err just in case inet_ntoa() or ntohs() changes the last error.
+ const DWORD err = WSAGetLastError();
+ *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",
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
@@ -747,31 +762,40 @@
// IPv4 and IPv6.
s = socket(AF_INET, type, 0);
if (s == INVALID_SOCKET) {
- *error = SystemErrorCodeToString(WSAGetLastError());
- D("could not create socket: %s\n", error->c_str());
+ *error = android::base::StringPrintf("cannot create socket: %s",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
+ D("%s\n", error->c_str());
return -1;
}
f->fh_socket = s;
+ // Note: SO_REUSEADDR on Windows allows multiple processes to bind to the
+ // same port, so instead use SO_EXCLUSIVEADDRUSE.
n = 1;
if (setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n,
sizeof(n)) == SOCKET_ERROR) {
- *error = SystemErrorCodeToString(WSAGetLastError());
- D("setsockopt level %d optname %d failed: %s\n",
- SOL_SOCKET, SO_EXCLUSIVEADDRUSE, error->c_str());
+ *error = android::base::StringPrintf(
+ "cannot set socket option SO_EXCLUSIVEADDRUSE: %s",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
+ D("%s\n", error->c_str());
return -1;
}
- if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
- *error = SystemErrorCodeToString(WSAGetLastError());
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
+ // Save err just in case inet_ntoa() or ntohs() changes the last error.
+ const DWORD err = WSAGetLastError();
+ *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",
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
}
if (type == SOCK_STREAM) {
if (listen(s, LISTEN_BACKLOG) == SOCKET_ERROR) {
- *error = SystemErrorCodeToString(WSAGetLastError());
+ *error = android::base::StringPrintf("cannot listen on socket: %s",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
D("could not listen on %s:%d: %s\n",
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
@@ -822,9 +846,10 @@
// with GetProcAddress("GetAddrInfoW").
#endif
if (getaddrinfo(host.c_str(), port_str, &hints, &addrinfo_ptr) != 0) {
- *error = SystemErrorCodeToString(WSAGetLastError());
- D("could not resolve host '%s' and port %s: %s\n", host.c_str(),
- port_str, error->c_str());
+ *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());
return -1;
}
std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*>
@@ -837,8 +862,9 @@
SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype,
addrinfo->ai_protocol);
if(s == INVALID_SOCKET) {
- *error = SystemErrorCodeToString(WSAGetLastError());
- D("could not create socket: %s\n", error->c_str());
+ *error = android::base::StringPrintf("cannot create socket: %s",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
+ D("%s\n", error->c_str());
return -1;
}
f->fh_socket = s;
@@ -846,7 +872,10 @@
// TODO: Implement timeouts for Windows. Seems like the default in theory
// (according to http://serverfault.com/a/671453) and in practice is 21 sec.
if(connect(s, addrinfo->ai_addr, addrinfo->ai_addrlen) == SOCKET_ERROR) {
- *error = SystemErrorCodeToString(WSAGetLastError());
+ // TODO: Use WSAAddressToString or inet_ntop on address.
+ *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",
type != SOCK_STREAM ? "udp" : "tcp", host.c_str(), port_str,
error->c_str());
diff --git a/adb/test_device.py b/adb/test_device.py
index 48a3f6c..c893ad4 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -155,6 +155,31 @@
output = self.device.shell(['uname'])
self.assertEqual(output, 'Linux' + self.device.linesep)
+ def test_pty_logic(self):
+ """Verify PTY logic for shells.
+
+ Interactive shells should use a PTY, non-interactive should not.
+
+ Bug: http://b/21215503
+ """
+ proc = subprocess.Popen(
+ self.device.adb_cmd + ['shell'], stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ # [ -t 0 ] is used (rather than `tty`) to provide portability. This
+ # gives an exit code of 0 iff stdin is connected to a terminal.
+ #
+ # Closing host-side stdin doesn't currently trigger the interactive
+ # shell to exit so we need to explicitly add an exit command to
+ # close the session from the device side, and append \n to complete
+ # the interactive command.
+ result = proc.communicate('[ -t 0 ]; echo x$?; exit 0\n')[0]
+ partition = result.rpartition('x')
+ self.assertEqual(partition[1], 'x')
+ self.assertEqual(int(partition[2]), 0)
+
+ exit_code = self.device.shell_nocheck(['[ -t 0 ]'])[0]
+ self.assertEqual(exit_code, 1)
+
class ArgumentEscapingTest(DeviceTest):
def test_shell_escaping(self):
diff --git a/adb/test_track_devices.cpp b/adb/test_track_devices.cpp
index f78daeb..6f658f6 100644
--- a/adb/test_track_devices.cpp
+++ b/adb/test_track_devices.cpp
@@ -1,12 +1,13 @@
// TODO: replace this with a shell/python script.
/* a simple test program, connects to ADB server, and opens a track-devices session */
-#include <netdb.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <errno.h>
#include <memory.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <unistd.h>
#include <base/file.h>
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 4a273c4..5e4ffbb 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -29,6 +29,7 @@
#include <list>
#include <base/stringprintf.h>
+#include <base/strings.h>
#include "adb.h"
#include "adb_utils.h"
@@ -139,8 +140,7 @@
len -= r;
p += r;
} else {
- D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
- if((r < 0) && (errno == EINTR)) continue;
+ D("%s: read_packet (fd=%d), error ret=%d: %s\n", name, fd, r, strerror(errno));
return -1;
}
}
@@ -170,8 +170,7 @@
len -= r;
p += r;
} else {
- D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
- if((r < 0) && (errno == EINTR)) continue;
+ D("%s: write_packet (fd=%d) error ret=%d: %s\n", name, fd, r, strerror(errno));
return -1;
}
}
@@ -331,10 +330,6 @@
put_apacket(p);
}
- // this is necessary to avoid a race condition that occured when a transport closes
- // while a client socket is still active.
- close_all_sockets(t);
-
D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
kick_transport(t);
transport_unref(t);
@@ -488,9 +483,7 @@
len -= r;
p += r;
} else {
- if((r < 0) && (errno == EINTR)) continue;
- D("transport_read_action: on fd %d, error %d: %s\n",
- fd, errno, strerror(errno));
+ D("transport_read_action: on fd %d: %s\n", fd, strerror(errno));
return -1;
}
}
@@ -510,9 +503,7 @@
len -= r;
p += r;
} else {
- if((r < 0) && (errno == EINTR)) continue;
- D("transport_write_action: on fd %d, error %d: %s\n",
- fd, errno, strerror(errno));
+ D("transport_write_action: on fd %d: %s\n", fd, strerror(errno));
return -1;
}
}
@@ -535,7 +526,7 @@
t = m.transport;
- if(m.action == 0){
+ if (m.action == 0) {
D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
/* IMPORTANT: the remove closes one half of the
@@ -845,6 +836,28 @@
return max_payload;
}
+// The list of features supported by the current system. Will be sent to the
+// other side of the connection in the banner.
+static const FeatureSet gSupportedFeatures = {
+ // None yet.
+};
+
+const FeatureSet& supported_features() {
+ return gSupportedFeatures;
+}
+
+bool atransport::has_feature(const std::string& feature) const {
+ return features_.count(feature) > 0;
+}
+
+void atransport::add_feature(const std::string& feature) {
+ features_.insert(feature);
+}
+
+bool atransport::CanUseFeature(const std::string& feature) const {
+ return has_feature(feature) && supported_features().count(feature) > 0;
+}
+
#if ADB_HOST
static void append_transport_info(std::string* result, const char* key,
@@ -879,6 +892,9 @@
append_transport_info(result, "product:", t->product, false);
append_transport_info(result, "model:", t->model, true);
append_transport_info(result, "device:", t->device, false);
+ append_transport_info(result, "features:",
+ android::base::Join(t->features(), ',').c_str(),
+ false);
}
*result += '\n';
}
diff --git a/adb/transport.h b/adb/transport.h
index edcc99d..e809407 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -20,9 +20,92 @@
#include <sys/types.h>
#include <string>
+#include <unordered_set>
#include "adb.h"
+typedef std::unordered_set<std::string> FeatureSet;
+
+const FeatureSet& supported_features();
+
+class atransport {
+public:
+ // TODO(danalbert): We expose waaaaaaay too much stuff because this was
+ // historically just a struct, but making the whole thing a more idiomatic
+ // class in one go is a very large change. Given how bad our testing is,
+ // it's better to do this piece by piece.
+
+ atransport() {
+ auth_fde = {};
+ transport_fde = {};
+ protocol_version = A_VERSION;
+ max_payload = MAX_PAYLOAD;
+ }
+
+ virtual ~atransport() {}
+
+ int (*read_from_remote)(apacket* p, atransport* t) = nullptr;
+ int (*write_to_remote)(apacket* p, atransport* t) = nullptr;
+ void (*close)(atransport* t) = nullptr;
+ void (*kick)(atransport* t) = nullptr;
+
+ int fd = -1;
+ int transport_socket = -1;
+ fdevent transport_fde;
+ int ref_count = 0;
+ uint32_t sync_token = 0;
+ ConnectionState connection_state = kCsOffline;
+ bool online = false;
+ TransportType type = kTransportAny;
+
+ // USB handle or socket fd as needed.
+ usb_handle* usb = nullptr;
+ int sfd = -1;
+
+ // Used to identify transports for clients.
+ char* serial = nullptr;
+ char* product = nullptr;
+ char* model = nullptr;
+ char* device = nullptr;
+ char* devpath = nullptr;
+ int adb_port = -1; // Use for emulators (local transport)
+ bool kicked = false;
+
+ // A list of adisconnect callbacks called when the transport is kicked.
+ adisconnect disconnects = {};
+
+ void* key = nullptr;
+ unsigned char token[TOKEN_SIZE] = {};
+ fdevent auth_fde;
+ size_t failed_auth_attempts = 0;
+
+ const char* connection_state_name() const;
+
+ void update_version(int version, size_t payload);
+ int get_protocol_version() const;
+ size_t get_max_payload() const;
+
+ inline const FeatureSet features() const {
+ return features_;
+ }
+
+ bool has_feature(const std::string& feature) const;
+ void add_feature(const std::string& feature);
+
+ // Returns true if both we and the other end of the transport support the
+ // feature.
+ bool CanUseFeature(const std::string& feature) const;
+
+private:
+ // A set of features transmitted in the banner with the initial connection.
+ // This is stored in the banner as 'features=feature0,feature1,etc'.
+ FeatureSet features_;
+ int protocol_version;
+ size_t max_payload;
+
+ DISALLOW_COPY_AND_ASSIGN(atransport);
+};
+
/*
* Obtain a transport from the available transports.
* If state is != kCsAny, only transports in that state are considered.
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 650e5ea..6a17497 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -120,10 +120,9 @@
return -1;
}
-
+#if ADB_HOST
static void *client_socket_thread(void *x)
{
-#if ADB_HOST
D("transport: client_socket_thread() starting\n");
while (true) {
int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
@@ -135,10 +134,11 @@
}
sleep(1);
}
-#endif
return 0;
}
+#else // ADB_HOST
+
static void *server_socket_thread(void * arg)
{
int serverfd, fd;
@@ -175,7 +175,6 @@
}
/* This is relevant only for ADB daemon running inside the emulator. */
-#if !ADB_HOST
/*
* Redefine open and write for qemu_pipe.h that contains inlined references
* to those routines. We will redifine them back after qemu_pipe.h inclusion.
@@ -287,31 +286,29 @@
void local_init(int port)
{
void* (*func)(void *);
+ const char* debug_name = "";
- if(HOST) {
- func = client_socket_thread;
- } else {
#if ADB_HOST
- func = server_socket_thread;
+ func = client_socket_thread;
+ debug_name = "client";
#else
- /* For the adbd daemon in the system image we need to distinguish
- * between the device, and the emulator. */
- char is_qemu[PROPERTY_VALUE_MAX];
- property_get("ro.kernel.qemu", is_qemu, "");
- if (!strcmp(is_qemu, "1")) {
- /* Running inside the emulator: use QEMUD pipe as the transport. */
- func = qemu_socket_thread;
- } else {
- /* Running inside the device: use TCP socket as the transport. */
- func = server_socket_thread;
- }
-#endif // !ADB_HOST
+ /* For the adbd daemon in the system image we need to distinguish
+ * between the device, and the emulator. */
+ char is_qemu[PROPERTY_VALUE_MAX];
+ property_get("ro.kernel.qemu", is_qemu, "");
+ if (!strcmp(is_qemu, "1")) {
+ /* Running inside the emulator: use QEMUD pipe as the transport. */
+ func = qemu_socket_thread;
+ } else {
+ /* Running inside the device: use TCP socket as the transport. */
+ func = server_socket_thread;
}
+ debug_name = "server";
+#endif // !ADB_HOST
- D("transport: local %s init\n", HOST ? "client" : "server");
-
+ D("transport: local %s init\n", debug_name);
if (!adb_thread_create(func, (void *) (uintptr_t) port)) {
- fatal_errno("cannot create local socket %s thread", HOST ? "client" : "server");
+ fatal_errno("cannot create local socket %s thread", debug_name);
}
}
@@ -323,17 +320,15 @@
adb_close(fd);
#if ADB_HOST
- if(HOST) {
- int nn;
- adb_mutex_lock( &local_transports_lock );
- for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) {
- if (local_transports[nn] == t) {
- local_transports[nn] = NULL;
- break;
- }
+ int nn;
+ adb_mutex_lock( &local_transports_lock );
+ for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) {
+ if (local_transports[nn] == t) {
+ local_transports[nn] = NULL;
+ break;
}
- adb_mutex_unlock( &local_transports_lock );
}
+ adb_mutex_unlock( &local_transports_lock );
#endif
}
@@ -404,7 +399,7 @@
t->adb_port = 0;
#if ADB_HOST
- if (HOST && local) {
+ if (local) {
adb_mutex_lock( &local_transports_lock );
{
t->adb_port = adb_port;
diff --git a/adb/transport_test.cpp b/adb/transport_test.cpp
index 49deb73..743d97d 100644
--- a/adb/transport_test.cpp
+++ b/adb/transport_test.cpp
@@ -59,6 +59,8 @@
EXPECT_EQ(0, memcmp(&auth_fde, &rhs.auth_fde, sizeof(fdevent)));
EXPECT_EQ(failed_auth_attempts, rhs.failed_auth_attempts);
+ EXPECT_EQ(features(), rhs.features());
+
return true;
}
};
@@ -120,6 +122,73 @@
// want to make sure I understand how this is working at all before I try fixing
// that.
TEST(transport, DISABLED_run_transport_disconnects_zeroed_atransport) {
- atransport t;
- run_transport_disconnects(&t);
+ atransport t;
+ run_transport_disconnects(&t);
+}
+
+TEST(transport, add_feature) {
+ atransport t;
+ ASSERT_EQ(0U, t.features().size());
+
+ t.add_feature("foo");
+ ASSERT_EQ(1U, t.features().size());
+ ASSERT_TRUE(t.has_feature("foo"));
+
+ t.add_feature("bar");
+ ASSERT_EQ(2U, t.features().size());
+ ASSERT_TRUE(t.has_feature("foo"));
+ ASSERT_TRUE(t.has_feature("bar"));
+
+ t.add_feature("foo");
+ ASSERT_EQ(2U, t.features().size());
+ ASSERT_TRUE(t.has_feature("foo"));
+ ASSERT_TRUE(t.has_feature("bar"));
+}
+
+TEST(transport, parse_banner_no_features) {
+ atransport t;
+
+ parse_banner("host::", &t);
+
+ ASSERT_EQ(0U, t.features().size());
+ ASSERT_EQ(kCsHost, t.connection_state);
+
+ ASSERT_EQ(nullptr, t.product);
+ ASSERT_EQ(nullptr, t.model);
+ ASSERT_EQ(nullptr, t.device);
+}
+
+TEST(transport, parse_banner_product_features) {
+ atransport t;
+
+ const char banner[] =
+ "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;";
+ parse_banner(banner, &t);
+
+ ASSERT_EQ(kCsHost, t.connection_state);
+
+ ASSERT_EQ(0U, t.features().size());
+
+ ASSERT_EQ(std::string("foo"), t.product);
+ ASSERT_EQ(std::string("bar"), t.model);
+ ASSERT_EQ(std::string("baz"), t.device);
+}
+
+TEST(transport, parse_banner_features) {
+ atransport t;
+
+ const char banner[] =
+ "host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;"
+ "features=woodly,doodly";
+ parse_banner(banner, &t);
+
+ ASSERT_EQ(kCsHost, t.connection_state);
+
+ ASSERT_EQ(2U, t.features().size());
+ ASSERT_TRUE(t.has_feature("woodly"));
+ ASSERT_TRUE(t.has_feature("doodly"));
+
+ ASSERT_EQ(std::string("foo"), t.product);
+ ASSERT_EQ(std::string("bar"), t.model);
+ ASSERT_EQ(std::string("baz"), t.device);
}
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 2c975a9..96ccdad 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -91,12 +91,6 @@
t->connection_state = state;
t->type = kTransportUsb;
t->usb = h;
-
-#if ADB_HOST
- HOST = 1;
-#else
- HOST = 0;
-#endif
}
#if ADB_HOST
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index b1b3538..dc44f16 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -64,6 +64,14 @@
struct usb_endpoint_descriptor_no_audio sink;
} __attribute__((packed));
+struct ss_func_desc {
+ struct usb_interface_descriptor intf;
+ struct usb_endpoint_descriptor_no_audio source;
+ struct usb_ss_ep_comp_descriptor source_comp;
+ struct usb_endpoint_descriptor_no_audio sink;
+ struct usb_ss_ep_comp_descriptor sink_comp;
+} __attribute__((packed));
+
struct desc_v1 {
struct usb_functionfs_descs_head_v1 {
__le32 magic;
@@ -79,7 +87,9 @@
// The rest of the structure depends on the flags in the header.
__le32 fs_count;
__le32 hs_count;
+ __le32 ss_count;
struct func_desc fs_descs, hs_descs;
+ struct ss_func_desc ss_descs;
} __attribute__((packed));
static struct func_desc fs_descriptors = {
@@ -136,6 +146,41 @@
},
};
+static struct ss_func_desc ss_descriptors = {
+ .intf = {
+ .bLength = sizeof(ss_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = ADB_CLASS,
+ .bInterfaceSubClass = ADB_SUBCLASS,
+ .bInterfaceProtocol = ADB_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
+ },
+ .source = {
+ .bLength = sizeof(ss_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+ },
+ .source_comp = {
+ .bLength = sizeof(ss_descriptors.source_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ },
+ .sink = {
+ .bLength = sizeof(ss_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+ },
+ .sink_comp = {
+ .bLength = sizeof(ss_descriptors.sink_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ },
+};
+
#define STR_INTERFACE_ "ADB Interface"
static const struct {
@@ -284,11 +329,14 @@
v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
- v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC;
+ v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
+ FUNCTIONFS_HAS_SS_DESC;
v2_descriptor.fs_count = 3;
v2_descriptor.hs_count = 3;
+ v2_descriptor.ss_count = 5;
v2_descriptor.fs_descs = fs_descriptors;
v2_descriptor.hs_descs = hs_descriptors;
+ v2_descriptor.ss_descs = ss_descriptors;
if (h->control < 0) { // might have already done this before
D("OPENING %s\n", USB_FFS_ADB_EP0);
@@ -383,17 +431,12 @@
static int bulk_write(int bulk_in, const uint8_t* buf, size_t length)
{
size_t count = 0;
- int ret;
- do {
- ret = adb_write(bulk_in, buf + count, length - count);
- if (ret < 0) {
- if (errno != EINTR)
- return ret;
- } else {
- count += ret;
- }
- } while (count < length);
+ while (count < length) {
+ int ret = adb_write(bulk_in, buf + count, length - count);
+ if (ret < 0) return -1;
+ count += ret;
+ }
D("[ bulk_write done fd=%d ]\n", bulk_in);
return count;
@@ -414,20 +457,15 @@
static int bulk_read(int bulk_out, uint8_t* buf, size_t length)
{
size_t count = 0;
- int ret;
- do {
- ret = adb_read(bulk_out, buf + count, length - count);
+ while (count < length) {
+ int ret = adb_read(bulk_out, buf + count, length - count);
if (ret < 0) {
- if (errno != EINTR) {
- D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n",
- bulk_out, length, count);
- return ret;
- }
- } else {
- count += ret;
+ D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n", bulk_out, length, count);
+ return -1;
}
- } while (count < length);
+ count += ret;
+ }
return count;
}
diff --git a/adb/usb_osx.cpp b/adb/usb_osx.cpp
index 939f319..0ce85f3 100644
--- a/adb/usb_osx.cpp
+++ b/adb/usb_osx.cpp
@@ -29,6 +29,9 @@
#include <inttypes.h>
#include <stdio.h>
+#include <base/logging.h>
+#include <base/stringprintf.h>
+
#include "adb.h"
#include "transport.h"
@@ -43,11 +46,11 @@
struct usb_handle
{
- UInt8 bulkIn;
- UInt8 bulkOut;
- IOUSBInterfaceInterface **interface;
- io_object_t usbNotification;
- unsigned int zero_mask;
+ UInt8 bulkIn;
+ UInt8 bulkOut;
+ IOUSBInterfaceInterface190** interface;
+ io_object_t usbNotification;
+ unsigned int zero_mask;
};
static CFRunLoopRef currentRunLoop = 0;
@@ -59,7 +62,7 @@
static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
natural_t messageType,
void *messageArgument);
-static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
+static usb_handle* CheckInterface(IOUSBInterfaceInterface190 **iface,
UInt16 vendor, UInt16 product);
static int
@@ -81,7 +84,7 @@
matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);
if (!matchingDict) {
- DBG("ERR: Couldn't create USB matching dictionary.\n");
+ LOG(ERROR) << "Couldn't create USB matching dictionary.";
return -1;
}
@@ -115,7 +118,7 @@
IOUSBDeviceInterface197 **dev = NULL;
HRESULT result;
SInt32 score;
- UInt32 locationId;
+ uint32_t locationId;
UInt8 if_class, subclass, protocol;
UInt16 vendor;
UInt16 product;
@@ -132,7 +135,7 @@
&plugInInterface, &score);
IOObjectRelease(usbInterface);
if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
- DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
+ LOG(ERROR) << "Unable to create an interface plug-in (" << std::hex << kr << ")";
continue;
}
@@ -143,7 +146,7 @@
//* We only needed the plugin to get the interface, so discard it
(*plugInInterface)->Release(plugInInterface);
if (result || !iface) {
- DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
+ LOG(ERROR) << "Couldn't query the interface (" << std::hex << result << ")";
continue;
}
@@ -152,7 +155,8 @@
kr = (*iface)->GetInterfaceProtocol(iface, &protocol);
if(if_class != ADB_CLASS || subclass != ADB_SUBCLASS || protocol != ADB_PROTOCOL) {
// Ignore non-ADB devices.
- DBG("Ignoring interface with incorrect class/subclass/protocol - %d, %d, %d\n", if_class, subclass, protocol);
+ LOG(DEBUG) << "Ignoring interface with incorrect class/subclass/protocol - " << if_class
+ << ", " << subclass << ", " << protocol;
(*iface)->Release(iface);
continue;
}
@@ -163,7 +167,7 @@
//* Gotta love OS X
kr = (*iface)->GetDevice(iface, &usbDevice);
if (kIOReturnSuccess != kr || !usbDevice) {
- DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
+ LOG(ERROR) << "Couldn't grab device from interface (" << std::hex << kr << ")";
continue;
}
@@ -177,7 +181,7 @@
//* only needed this to find the plugin
(void)IOObjectRelease(usbDevice);
if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
- DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
+ LOG(ERROR) << "Unable to create a device plug-in (" << std::hex << kr << ")";
continue;
}
@@ -186,8 +190,7 @@
//* only needed this to query the plugin
(*plugInInterface)->Release(plugInInterface);
if (result || !dev) {
- DBG("ERR: Couldn't create a device interface (%08x)\n",
- (int) result);
+ LOG(ERROR) << "Couldn't create a device interface (" << std::hex << result << ")";
continue;
}
@@ -197,74 +200,74 @@
kr = (*dev)->GetDeviceProduct(dev, &product);
kr = (*dev)->GetLocationID(dev, &locationId);
if (kr == 0) {
- snprintf(devpathBuf, sizeof(devpathBuf), "usb:%" PRIu32 "X",
- (unsigned int)locationId);
+ snprintf(devpathBuf, sizeof(devpathBuf), "usb:%" PRIu32 "X", locationId);
devpath = devpathBuf;
}
kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
- if (serialIndex > 0) {
- IOUSBDevRequest req;
- UInt16 buffer[256];
- UInt16 languages[128];
+ if (serialIndex > 0) {
+ IOUSBDevRequest req;
+ UInt16 buffer[256];
+ UInt16 languages[128];
- memset(languages, 0, sizeof(languages));
+ memset(languages, 0, sizeof(languages));
- req.bmRequestType =
- USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
- req.bRequest = kUSBRqGetDescriptor;
- req.wValue = (kUSBStringDesc << 8) | 0;
- req.wIndex = 0;
- req.pData = languages;
- req.wLength = sizeof(languages);
- kr = (*dev)->DeviceRequest(dev, &req);
+ req.bmRequestType =
+ USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
+ req.bRequest = kUSBRqGetDescriptor;
+ req.wValue = (kUSBStringDesc << 8) | 0;
+ req.wIndex = 0;
+ req.pData = languages;
+ req.wLength = sizeof(languages);
+ kr = (*dev)->DeviceRequest(dev, &req);
- if (kr == kIOReturnSuccess && req.wLenDone > 0) {
+ if (kr == kIOReturnSuccess && req.wLenDone > 0) {
- int langCount = (req.wLenDone - 2) / 2, lang;
+ int langCount = (req.wLenDone - 2) / 2, lang;
- for (lang = 1; lang <= langCount; lang++) {
+ for (lang = 1; lang <= langCount; lang++) {
- memset(buffer, 0, sizeof(buffer));
- memset(&req, 0, sizeof(req));
+ memset(buffer, 0, sizeof(buffer));
+ memset(&req, 0, sizeof(req));
- req.bmRequestType =
- USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
- req.bRequest = kUSBRqGetDescriptor;
- req.wValue = (kUSBStringDesc << 8) | serialIndex;
- req.wIndex = languages[lang];
- req.pData = buffer;
- req.wLength = sizeof(buffer);
- kr = (*dev)->DeviceRequest(dev, &req);
+ req.bmRequestType =
+ USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
+ req.bRequest = kUSBRqGetDescriptor;
+ req.wValue = (kUSBStringDesc << 8) | serialIndex;
+ req.wIndex = languages[lang];
+ req.pData = buffer;
+ req.wLength = sizeof(buffer);
+ kr = (*dev)->DeviceRequest(dev, &req);
- if (kr == kIOReturnSuccess && req.wLenDone > 0) {
- int i, count;
+ if (kr == kIOReturnSuccess && req.wLenDone > 0) {
+ int i, count;
- // skip first word, and copy the rest to the serial string,
- // changing shorts to bytes.
- count = (req.wLenDone - 1) / 2;
- for (i = 0; i < count; i++)
- serial[i] = buffer[i + 1];
- serial[i] = 0;
- break;
- }
- }
- }
- }
+ // skip first word, and copy the rest to the serial string,
+ // changing shorts to bytes.
+ count = (req.wLenDone - 1) / 2;
+ for (i = 0; i < count; i++)
+ serial[i] = buffer[i + 1];
+ serial[i] = 0;
+ break;
+ }
+ }
+ }
+ }
+
(*dev)->Release(dev);
- DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
- serial);
+ LOG(INFO) << android::base::StringPrintf("Found vid=%04x pid=%04x serial=%s\n",
+ vendor, product, serial);
- usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
+ usb_handle* handle = CheckInterface((IOUSBInterfaceInterface190**)iface,
vendor, product);
if (handle == NULL) {
- DBG("ERR: Could not find device interface: %08x\n", kr);
+ LOG(ERROR) << "Could not find device interface";
(*iface)->Release(iface);
continue;
}
- DBG("AndroidDeviceAdded calling register_usb_transport\n");
+ LOG(DEBUG) << "AndroidDeviceAdded calling register_usb_transport";
register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);
// Register for an interest notification of this device being removed.
@@ -278,7 +281,7 @@
&handle->usbNotification);
if (kIOReturnSuccess != kr) {
- DBG("ERR: Unable to create interest notification (%08x)\n", kr);
+ LOG(ERROR) << "Unable to create interest notification (" << std::hex << kr << ")";
}
}
}
@@ -290,38 +293,49 @@
if (messageType == kIOMessageServiceIsTerminated) {
if (!handle) {
- DBG("ERR: NULL handle\n");
+ LOG(ERROR) << "NULL handle";
return;
}
- DBG("AndroidInterfaceNotify\n");
+ LOG(DEBUG) << "AndroidInterfaceNotify";
IOObjectRelease(handle->usbNotification);
usb_kick(handle);
}
}
+// Used to clear both the endpoints before starting.
+// When adb quits, we might clear the host endpoint but not the device.
+// So we make sure both sides are clear before starting up.
+static bool ClearPipeStallBothEnds(IOUSBInterfaceInterface190** interface, UInt8 bulkEp) {
+ IOReturn rc = (*interface)->ClearPipeStallBothEnds(interface, bulkEp);
+ if (rc != kIOReturnSuccess) {
+ LOG(ERROR) << "Could not clear pipe stall both ends: " << std::hex << rc;
+ return false;
+ }
+ return true;
+}
+
//* TODO: simplify this further since we only register to get ADB interface
//* subclass+protocol events
static usb_handle*
-CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
+CheckInterface(IOUSBInterfaceInterface190 **interface, UInt16 vendor, UInt16 product)
{
- usb_handle* handle = NULL;
- IOReturn kr;
- UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
- UInt8 endpoint;
-
+ usb_handle* handle;
+ IOReturn kr;
+ UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
+ UInt8 endpoint;
//* Now open the interface. This will cause the pipes associated with
//* the endpoints in the interface descriptor to be instantiated
kr = (*interface)->USBInterfaceOpen(interface);
if (kr != kIOReturnSuccess) {
- DBG("ERR: Could not open interface: (%08x)\n", kr);
+ LOG(ERROR) << "Could not open interface: " << std::hex << kr;
return NULL;
}
//* Get the number of endpoints associated with this interface
kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
if (kr != kIOReturnSuccess) {
- DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
+ LOG(ERROR) << "Unable to get number of endpoints: " << std::hex << kr;
goto err_get_num_ep;
}
@@ -329,22 +343,22 @@
if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
(*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
(*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) {
- DBG("ERR: Unable to get interface class, subclass and protocol\n");
+ LOG(ERROR) << "Unable to get interface class, subclass and protocol";
goto err_get_interface_class;
}
//* check to make sure interface class, subclass and protocol match ADB
//* avoid opening mass storage endpoints
- if (!is_adb_interface(vendor, product, interfaceClass,
- interfaceSubClass, interfaceProtocol))
+ if (!is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) {
goto err_bad_adb_interface;
+ }
handle = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
if (handle == nullptr) goto err_bad_adb_interface;
//* Iterate over the endpoints for this interface and find the first
//* bulk in/out pipes available. These will be our read/write pipes.
- for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
+ for (endpoint = 1; endpoint <= interfaceNumEndpoints; endpoint++) {
UInt8 transferType;
UInt16 maxPacketSize;
UInt8 interval;
@@ -353,22 +367,25 @@
kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
&number, &transferType, &maxPacketSize, &interval);
-
- if (kIOReturnSuccess == kr) {
- if (kUSBBulk != transferType)
- continue;
-
- if (kUSBIn == direction)
- handle->bulkIn = endpoint;
-
- if (kUSBOut == direction)
- handle->bulkOut = endpoint;
-
- handle->zero_mask = maxPacketSize - 1;
- } else {
- DBG("ERR: FindDeviceInterface - could not get pipe properties (%08x)\n", kr);
+ if (kr != kIOReturnSuccess) {
+ LOG(ERROR) << "FindDeviceInterface - could not get pipe properties: "
+ << std::hex << kr;
goto err_get_pipe_props;
}
+
+ if (kUSBBulk != transferType) continue;
+
+ if (kUSBIn == direction) {
+ handle->bulkIn = endpoint;
+ if (!ClearPipeStallBothEnds(interface, handle->bulkIn)) goto err_get_pipe_props;
+ }
+
+ if (kUSBOut == direction) {
+ handle->bulkOut = endpoint;
+ if (!ClearPipeStallBothEnds(interface, handle->bulkOut)) goto err_get_pipe_props;
+ }
+
+ handle->zero_mask = maxPacketSize - 1;
}
handle->interface = interface;
@@ -401,12 +418,12 @@
IOObjectRelease(notificationIterator);
IONotificationPortDestroy(notificationPort);
- DBG("RunLoopThread done\n");
+ LOG(DEBUG) << "RunLoopThread done";
return NULL;
}
static void usb_cleanup() {
- DBG("usb_cleanup\n");
+ LOG(DEBUG) << "usb_cleanup";
close_usb_devices();
if (currentRunLoop)
CFRunLoopStop(currentRunLoop);
@@ -447,18 +464,17 @@
return -1;
if (NULL == handle->interface) {
- DBG("ERR: usb_write interface was null\n");
+ LOG(ERROR) << "usb_write interface was null";
return -1;
}
if (0 == handle->bulkOut) {
- DBG("ERR: bulkOut endpoint not assigned\n");
+ LOG(ERROR) << "bulkOut endpoint not assigned";
return -1;
}
result =
- (*handle->interface)->WritePipe(
- handle->interface, handle->bulkOut, (void *)buf, len);
+ (*handle->interface)->WritePipe(handle->interface, handle->bulkOut, (void *)buf, len);
if ((result == 0) && (handle->zero_mask)) {
/* we need 0-markers and our transfer */
@@ -472,7 +488,7 @@
if (0 == result)
return 0;
- DBG("ERR: usb_write failed with status %d\n", result);
+ LOG(ERROR) << "usb_write failed with status: " << std::hex << result;
return -1;
}
@@ -490,19 +506,19 @@
}
if (NULL == handle->interface) {
- DBG("ERR: usb_read interface was null\n");
+ LOG(ERROR) << "usb_read interface was null";
return -1;
}
if (0 == handle->bulkIn) {
- DBG("ERR: bulkIn endpoint not assigned\n");
+ LOG(ERROR) << "bulkIn endpoint not assigned";
return -1;
}
result = (*handle->interface)->ReadPipe(handle->interface, handle->bulkIn, buf, &numBytes);
if (kIOUSBPipeStalled == result) {
- DBG(" Pipe stalled, clearing stall.\n");
+ LOG(ERROR) << "Pipe stalled, clearing stall.\n";
(*handle->interface)->ClearPipeStall(handle->interface, handle->bulkIn);
result = (*handle->interface)->ReadPipe(handle->interface, handle->bulkIn, buf, &numBytes);
}
@@ -510,7 +526,7 @@
if (kIOReturnSuccess == result)
return 0;
else {
- DBG("ERR: usb_read failed with status %x\n", result);
+ LOG(ERROR) << "usb_read failed with status: " << std::hex << result;
}
return -1;
@@ -523,6 +539,7 @@
void usb_kick(usb_handle *handle)
{
+ LOG(INFO) << "Kicking handle";
/* release the interface */
if (!handle)
return;
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index 4c9a152..b8cc5cf 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -33,6 +33,10 @@
/** Structure usb_handle describes our connection to the usb device via
AdbWinApi.dll. This structure is returned from usb_open() routine and
is expected in each subsequent call that is accessing the device.
+
+ Most members are protected by usb_lock, except for adb_{read,write}_pipe which
+ rely on AdbWinApi.dll's handle validation and AdbCloseHandle(endpoint)'s
+ ability to break a thread out of pipe IO.
*/
struct usb_handle {
/// Previous entry in the list of opened usb handles
@@ -86,6 +90,9 @@
/// registers usb transport for them.
void find_devices();
+/// Kicks all USB devices
+static void kick_devices();
+
/// Entry point for thread that polls (every second) for new usb interfaces.
/// This routine calls find_devices in infinite loop.
void* device_poll_thread(void* unused);
@@ -111,9 +118,6 @@
/// Closes opened usb handle
int usb_close(usb_handle* handle);
-/// Gets interface (device) name for an opened usb handle
-const char *usb_name(usb_handle* handle);
-
int known_device_locked(const char* dev_name) {
usb_handle* usb;
@@ -177,17 +181,99 @@
return NULL;
}
+static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam) {
+ switch (uMsg) {
+ case WM_POWERBROADCAST:
+ switch (wParam) {
+ case PBT_APMRESUMEAUTOMATIC:
+ // Resuming from sleep or hibernation, so kick all existing USB devices
+ // and then allow the device_poll_thread to redetect USB devices from
+ // scratch. If we don't do this, existing USB devices will never respond
+ // to us because they'll be waiting for the connect/auth handshake.
+ D("Received (WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC) notification, "
+ "so kicking all USB devices\n");
+ kick_devices();
+ return TRUE;
+ }
+ }
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+}
+
+static void* _power_notification_thread(void* unused) {
+ // This uses a thread with its own window message pump to get power
+ // notifications. If adb runs from a non-interactive service account, this
+ // might not work (not sure). If that happens to not work, we could use
+ // 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");
+
+ // Window class names are process specific.
+ static const WCHAR kPowerNotificationWindowClassName[] =
+ L"PowerNotificationWindow";
+
+ // Get the HINSTANCE corresponding to the module that _power_window_proc
+ // is in (the main module).
+ const HINSTANCE instance = GetModuleHandleW(NULL);
+ if (!instance) {
+ // This is such a common API call that this should never fail.
+ fatal("GetModuleHandleW failed: %s",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ }
+
+ WNDCLASSEXW wndclass;
+ memset(&wndclass, 0, sizeof(wndclass));
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.lpfnWndProc = _power_window_proc;
+ wndclass.hInstance = instance;
+ wndclass.lpszClassName = kPowerNotificationWindowClassName;
+ if (!RegisterClassExW(&wndclass)) {
+ fatal("RegisterClassExW failed: %s",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ }
+
+ if (!CreateWindowExW(WS_EX_NOACTIVATE, kPowerNotificationWindowClassName,
+ L"ADB Power Notification Window", WS_POPUP, 0, 0, 0, 0,
+ NULL, NULL, instance, NULL)) {
+ fatal("CreateWindowExW failed: %s",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ }
+
+ MSG msg;
+ while (GetMessageW(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+
+ // GetMessageW() will return false if a quit message is posted. We don't
+ // 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");
+
+ return NULL;
+}
+
void usb_init() {
if (!adb_thread_create(device_poll_thread, nullptr)) {
- fatal_errno("cannot create input thread");
+ fatal_errno("cannot create device poll thread");
+ }
+ if (!adb_thread_create(_power_notification_thread, nullptr)) {
+ fatal_errno("cannot create power notification thread");
}
}
usb_handle* do_usb_open(const wchar_t* interface_name) {
+ unsigned long name_len = 0;
+
// Allocate our handle
- usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
- if (NULL == ret)
- return NULL;
+ 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),
+ strerror(errno));
+ goto fail;
+ }
// Set linkers back to the handle
ret->next = ret;
@@ -195,11 +281,10 @@
// Create interface.
ret->adb_interface = AdbCreateInterfaceByName(interface_name);
-
if (NULL == ret->adb_interface) {
- free(ret);
- errno = GetLastError();
- return NULL;
+ D("AdbCreateInterfaceByName failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ goto fail;
}
// Open read pipe (endpoint)
@@ -207,45 +292,60 @@
AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
AdbOpenAccessTypeReadWrite,
AdbOpenSharingModeReadWrite);
- if (NULL != ret->adb_read_pipe) {
- // Open write pipe (endpoint)
- ret->adb_write_pipe =
- AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
- AdbOpenAccessTypeReadWrite,
- AdbOpenSharingModeReadWrite);
- if (NULL != ret->adb_write_pipe) {
- // Save interface name
- unsigned long name_len = 0;
-
- // First get expected name length
- AdbGetInterfaceName(ret->adb_interface,
- NULL,
- &name_len,
- true);
- if (0 != name_len) {
- ret->interface_name = (char*)malloc(name_len);
-
- if (NULL != ret->interface_name) {
- // Now save the name
- if (AdbGetInterfaceName(ret->adb_interface,
- ret->interface_name,
- &name_len,
- true)) {
- // We're done at this point
- return ret;
- }
- } else {
- SetLastError(ERROR_OUTOFMEMORY);
- }
- }
- }
+ if (NULL == ret->adb_read_pipe) {
+ D("AdbOpenDefaultBulkReadEndpoint failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ goto fail;
}
- // Something went wrong.
- int saved_errno = GetLastError();
- usb_cleanup_handle(ret);
- free(ret);
- SetLastError(saved_errno);
+ // Open write pipe (endpoint)
+ ret->adb_write_pipe =
+ AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
+ AdbOpenAccessTypeReadWrite,
+ AdbOpenSharingModeReadWrite);
+ if (NULL == ret->adb_write_pipe) {
+ D("AdbOpenDefaultBulkWriteEndpoint failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ goto fail;
+ }
+
+ // Save interface name
+ // First get expected name length
+ AdbGetInterfaceName(ret->adb_interface,
+ NULL,
+ &name_len,
+ true);
+ if (0 == name_len) {
+ D("AdbGetInterfaceName returned name length of zero: %s\n",
+ 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,
+ strerror(errno));
+ goto fail;
+ }
+
+ // Now save the name
+ if (!AdbGetInterfaceName(ret->adb_interface,
+ ret->interface_name,
+ &name_len,
+ true)) {
+ D("AdbGetInterfaceName failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ goto fail;
+ }
+
+ // We're done at this point
+ return ret;
+
+fail:
+ if (NULL != ret) {
+ usb_cleanup_handle(ret);
+ free(ret);
+ }
return NULL;
}
@@ -253,92 +353,130 @@
int usb_write(usb_handle* handle, const void* data, int len) {
unsigned long time_out = 5000;
unsigned long written = 0;
- int ret;
+ int err = 0;
D("usb_write %d\n", len);
- if (NULL != handle) {
- // Perform write
- ret = AdbWriteEndpointSync(handle->adb_write_pipe,
- (void*)data,
- (unsigned long)len,
- &written,
- time_out);
- int saved_errno = GetLastError();
-
- if (ret) {
- // Make sure that we've written what we were asked to write
- D("usb_write got: %ld, expected: %d\n", written, len);
- if (written == (unsigned long)len) {
- if(handle->zero_mask && (len & handle->zero_mask) == 0) {
- // Send a zero length packet
- AdbWriteEndpointSync(handle->adb_write_pipe,
- (void*)data,
- 0,
- &written,
- time_out);
- }
- return 0;
- }
- } else {
- // assume ERROR_INVALID_HANDLE indicates we are disconnected
- if (saved_errno == ERROR_INVALID_HANDLE)
- usb_kick(handle);
- }
- errno = saved_errno;
- } else {
- D("usb_write NULL handle\n");
- SetLastError(ERROR_INVALID_HANDLE);
+ if (NULL == handle) {
+ D("usb_write was passed NULL handle\n");
+ err = EINVAL;
+ goto fail;
}
- D("usb_write failed: %d\n", errno);
+ // Perform write
+ if (!AdbWriteEndpointSync(handle->adb_write_pipe,
+ (void*)data,
+ (unsigned long)len,
+ &written,
+ time_out)) {
+ D("AdbWriteEndpointSync failed: %s\n",
+ 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);
+ 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",
+ len, written);
+ err = EIO;
+ goto fail;
+ }
+
+ if (handle->zero_mask && (len & handle->zero_mask) == 0) {
+ // Send a zero length packet
+ if (!AdbWriteEndpointSync(handle->adb_write_pipe,
+ (void*)data,
+ 0,
+ &written,
+ time_out)) {
+ D("AdbWriteEndpointSync of zero length packet failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ err = EIO;
+ goto fail;
+ }
+ }
+
+ return 0;
+
+fail:
+ // 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");
+ usb_kick(handle);
+ }
+
+ D("usb_write failed\n");
+ errno = err;
return -1;
}
int usb_read(usb_handle *handle, void* data, int len) {
unsigned long time_out = 0;
unsigned long read = 0;
+ int err = 0;
D("usb_read %d\n", len);
- if (handle != nullptr) {
- while (len > 0) {
- int ret = AdbReadEndpointSync(handle->adb_read_pipe, data, len, &read, time_out);
- int saved_errno = GetLastError();
- D("usb_write got: %ld, expected: %d, errno: %d\n", read, len, saved_errno);
- if (ret) {
- data = (char *)data + read;
- len -= read;
-
- if (len == 0)
- return 0;
- } else {
- // assume ERROR_INVALID_HANDLE indicates we are disconnected
- if (saved_errno == ERROR_INVALID_HANDLE)
- usb_kick(handle);
- break;
- }
- errno = saved_errno;
- }
- } else {
- D("usb_read NULL handle\n");
- SetLastError(ERROR_INVALID_HANDLE);
+ if (NULL == handle) {
+ D("usb_read was passed NULL handle\n");
+ err = EINVAL;
+ goto fail;
}
- D("usb_read failed: %d\n", errno);
+ while (len > 0) {
+ if (!AdbReadEndpointSync(handle->adb_read_pipe, data, len, &read,
+ time_out)) {
+ D("AdbReadEndpointSync failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ err = EIO;
+ goto fail;
+ }
+ D("usb_read got: %ld, expected: %d\n", read, len);
+ data = (char *)data + read;
+ len -= read;
+ }
+
+ return 0;
+
+fail:
+ // 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");
+ usb_kick(handle);
+ }
+
+ D("usb_read failed\n");
+ errno = err;
return -1;
}
+// 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,
+ SystemErrorCodeToString(GetLastError()).c_str());
+ }
+}
+
void usb_cleanup_handle(usb_handle* handle) {
+ D("usb_cleanup_handle\n");
if (NULL != handle) {
if (NULL != handle->interface_name)
free(handle->interface_name);
+ // AdbCloseHandle(pipe) will break any threads out of pending IO calls and
+ // wait until the pipe no longer uses the interface. Then we can
+ // AdbCloseHandle() the interface.
if (NULL != handle->adb_write_pipe)
- AdbCloseHandle(handle->adb_write_pipe);
+ _adb_close_handle(handle->adb_write_pipe);
if (NULL != handle->adb_read_pipe)
- AdbCloseHandle(handle->adb_read_pipe);
+ _adb_close_handle(handle->adb_read_pipe);
if (NULL != handle->adb_interface)
- AdbCloseHandle(handle->adb_interface);
+ _adb_close_handle(handle->adb_interface);
handle->interface_name = NULL;
handle->adb_write_pipe = NULL;
@@ -347,16 +485,22 @@
}
}
+static void usb_kick_locked(usb_handle* handle) {
+ // The reason the lock must be acquired before calling this function is in
+ // case multiple threads are trying to kick the same device at the same time.
+ usb_cleanup_handle(handle);
+}
+
void usb_kick(usb_handle* handle) {
+ D("usb_kick\n");
if (NULL != handle) {
adb_mutex_lock(&usb_lock);
- usb_cleanup_handle(handle);
+ usb_kick_locked(handle);
adb_mutex_unlock(&usb_lock);
} else {
- SetLastError(ERROR_INVALID_HANDLE);
- errno = ERROR_INVALID_HANDLE;
+ errno = EINVAL;
}
}
@@ -384,16 +528,6 @@
return 0;
}
-const char *usb_name(usb_handle* handle) {
- if (NULL == handle) {
- SetLastError(ERROR_INVALID_HANDLE);
- errno = ERROR_INVALID_HANDLE;
- return NULL;
- }
-
- return (const char*)handle->interface_name;
-}
-
int recognized_device(usb_handle* handle) {
if (NULL == handle)
return 0;
@@ -403,6 +537,8 @@
if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
&device_desc)) {
+ D("AdbGetUsbDeviceDescriptor failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
return 0;
}
@@ -411,6 +547,8 @@
if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
&interf_desc)) {
+ D("AdbGetUsbInterfaceDescriptor failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
return 0;
}
@@ -427,6 +565,10 @@
// 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);
+ } else {
+ D("AdbGetEndpointInformation failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
}
}
@@ -448,8 +590,11 @@
ADBAPIHANDLE enum_handle =
AdbEnumInterfaces(usb_class_id, true, true, true);
- if (NULL == enum_handle)
+ if (NULL == enum_handle) {
+ D("AdbEnumInterfaces failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
return;
+ }
while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
// TODO: FIXME - temp hack converting wchar_t into char.
@@ -486,7 +631,8 @@
free(handle);
}
} else {
- D("cannot get serial number\n");
+ D("cannot get serial number: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
usb_cleanup_handle(handle);
free(handle);
}
@@ -500,5 +646,21 @@
entry_buffer_size = sizeof(entry_buffer);
}
- AdbCloseHandle(enum_handle);
+ if (GetLastError() != ERROR_NO_MORE_ITEMS) {
+ // Only ERROR_NO_MORE_ITEMS is expected at the end of enumeration.
+ D("AdbNextInterface failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ }
+
+ _adb_close_handle(enum_handle);
+}
+
+static void kick_devices() {
+ // Need to acquire lock to safely walk the list which might be modified
+ // by another thread.
+ adb_mutex_lock(&usb_lock);
+ for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+ usb_kick_locked(usb);
+ }
+ adb_mutex_unlock(&usb_lock);
}
diff --git a/base/logging.cpp b/base/logging.cpp
index 34229a2..e9e06df 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -70,9 +70,14 @@
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);
+ CHAR longname[MAX_PATH];
+ DWORD nchars = GetModuleFileNameA(nullptr, longname, arraysize(longname));
+ if ((nchars >= arraysize(longname)) || (nchars == 0)) {
+ // String truncation or some other error.
+ strcpy(progname, "<unknown>");
+ } else {
+ strcpy(progname, basename(longname));
+ }
first = false;
}
@@ -82,25 +87,22 @@
class mutex {
public:
mutex() {
- semaphore_ = CreateSemaphore(nullptr, 1, 1, nullptr);
- CHECK(semaphore_ != nullptr) << "Failed to create Mutex";
+ InitializeCriticalSection(&critical_section_);
}
~mutex() {
- CloseHandle(semaphore_);
+ DeleteCriticalSection(&critical_section_);
}
void lock() {
- DWORD result = WaitForSingleObject(semaphore_, INFINITE);
- CHECK_EQ(result, WAIT_OBJECT_0) << GetLastError();
+ EnterCriticalSection(&critical_section_);
}
void unlock() {
- bool result = ReleaseSemaphore(semaphore_, 1, nullptr);
- CHECK(result);
+ LeaveCriticalSection(&critical_section_);
}
private:
- HANDLE semaphore_;
+ CRITICAL_SECTION critical_section_;
};
template <typename LockT>
@@ -147,8 +149,9 @@
void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
unsigned int line, const char* message) {
- static const char* log_characters = "VDIWEF";
- CHECK_EQ(strlen(log_characters), FATAL + 1U);
+ static const char log_characters[] = "VDIWEF";
+ static_assert(arraysize(log_characters) - 1 == FATAL + 1,
+ "Mismatch in size of log_characters and values in LogSeverity");
char severity_char = log_characters[severity];
fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(),
severity_char, getpid(), gettid(), file, line, message);
@@ -197,6 +200,20 @@
InitLogging(argv);
}
+// TODO: make this public; it's independently useful.
+class ErrnoRestorer {
+ public:
+ ErrnoRestorer(int saved_errno) : saved_errno_(saved_errno) {
+ }
+
+ ~ErrnoRestorer() {
+ errno = saved_errno_;
+ }
+
+ private:
+ const int saved_errno_;
+};
+
void InitLogging(char* argv[]) {
if (gInitialized) {
return;
@@ -257,19 +274,25 @@
gLogger = std::move(logger);
}
+// We can't use basename(3) because this code runs on the Mac, which doesn't
+// have a non-modifying basename.
+static const char* GetFileBasename(const char* file) {
+ const char* last_slash = strrchr(file, '/');
+ return (last_slash == nullptr) ? file : last_slash + 1;
+}
+
// This indirection greatly reduces the stack impact of having lots of
// checks/logging in a function.
class LogMessageData {
public:
LogMessageData(const char* file, unsigned int line, LogId id,
- LogSeverity severity, int error)
- : file_(file),
+ LogSeverity severity, int error, int saved_errno)
+ : file_(GetFileBasename(file)),
line_number_(line),
id_(id),
severity_(severity),
- error_(error) {
- const char* last_slash = strrchr(file, '/');
- file = (last_slash == nullptr) ? file : last_slash + 1;
+ error_(error),
+ errno_restorer_(saved_errno) {
}
const char* GetFile() const {
@@ -307,13 +330,14 @@
const LogId id_;
const LogSeverity severity_;
const int error_;
+ ErrnoRestorer errno_restorer_;
DISALLOW_COPY_AND_ASSIGN(LogMessageData);
};
LogMessage::LogMessage(const char* file, unsigned int line, LogId id,
LogSeverity severity, int error)
- : data_(new LogMessageData(file, line, id, severity, error)) {
+ : data_(new LogMessageData(file, line, id, severity, error, errno)) {
}
LogMessage::~LogMessage() {
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 1a92c94..c12dfa5 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -16,6 +16,8 @@
#include "base/logging.h"
+#include <libgen.h>
+
#include <regex>
#include <string>
@@ -76,10 +78,10 @@
const char* message) {
static const char* log_characters = "VDIWEF";
char log_char = log_characters[severity];
+ std::string holder(__FILE__);
return android::base::StringPrintf(
- "%c[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+ " __FILE__
- ":[[:digit:]]+] %s",
- log_char, message);
+ "%c[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+ %s:[[:digit:]]+] %s",
+ log_char, basename(&holder[0]), message);
}
TEST(logging, LOG) {
@@ -100,7 +102,7 @@
#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::WARNING, "foobar"));
- ASSERT_TRUE(std::regex_search(output, message_regex));
+ ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif
}
@@ -116,7 +118,7 @@
#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::INFO, "foobar"));
- ASSERT_TRUE(std::regex_search(output, message_regex));
+ ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif
}
@@ -143,7 +145,7 @@
#if !defined(_WIN32)
std::regex message_regex(
make_log_pattern(android::base::DEBUG, "foobar"));
- ASSERT_TRUE(std::regex_search(output, message_regex));
+ ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif
}
}
@@ -162,7 +164,7 @@
#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));
+ ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif
}
}
@@ -183,7 +185,7 @@
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));
+ ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
#endif
}
}
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
new file mode 100644
index 0000000..6b98af4
--- /dev/null
+++ b/crash_reporter/Android.mk
@@ -0,0 +1,129 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(HOST_OS),linux)
+
+crash_reporter_cpp_extension := .cc
+
+crash_reporter_src := crash_collector.cc \
+ kernel_collector.cc \
+ kernel_warning_collector.cc \
+ udev_collector.cc \
+ unclean_shutdown_collector.cc \
+ user_collector.cc
+
+crash_reporter_includes := external/gtest/include
+
+crash_reporter_test_src := crash_collector_test.cc \
+ crash_reporter_logs_test.cc \
+ kernel_collector_test.cc \
+ testrunner.cc \
+ udev_collector_test.cc \
+ unclean_shutdown_collector_test.cc \
+ user_collector_test.cc
+
+warn_collector_src := warn_collector.l
+
+# Crash reporter static library.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcrash
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_C_INCLUDES := $(crash_reporter_includes)
+LOCAL_RTTI_FLAG := -frtti
+LOCAL_SHARED_LIBRARIES := libchrome \
+ libchromeos \
+ libcutils \
+ libdbus \
+ libmetrics \
+ libpcrecpp
+LOCAL_SRC_FILES := $(crash_reporter_src)
+include $(BUILD_STATIC_LIBRARY)
+
+# Crash reporter client.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_reporter
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_C_INCLUDES := $(crash_reporter_includes)
+LOCAL_REQUIRED_MODULES := core2md \
+ crash_reporter_logs.conf \
+ crash_sender \
+ dbus-send \
+ init.crash_reporter.rc
+LOCAL_RTTI_FLAG := -frtti
+LOCAL_SHARED_LIBRARIES := libchrome \
+ libchromeos \
+ libcutils \
+ libdbus \
+ libmetrics \
+ libpcrecpp
+LOCAL_SRC_FILES := crash_reporter.cc
+LOCAL_STATIC_LIBRARIES := libcrash
+include $(BUILD_EXECUTABLE)
+
+# Crash sender script.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_sender
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
+LOCAL_SRC_FILES := crash_sender
+include $(BUILD_PREBUILT)
+
+# Warn collector client.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := warn_collector
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_SHARED_LIBRARIES := libmetrics
+LOCAL_SRC_FILES := $(warn_collector_src)
+include $(BUILD_EXECUTABLE)
+
+# Crash reporter init script.
+# ========================================================
+ifdef TARGET_COPY_OUT_INITRCD
+include $(CLEAR_VARS)
+LOCAL_MODULE := init.crash_reporter.rc
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_INITRCD)
+LOCAL_SRC_FILES := init.crash_reporter.rc
+include $(BUILD_PREBUILT)
+endif
+
+# Crash reporter logs conf file.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_reporter_logs.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/etc
+LOCAL_SRC_FILES := crash_reporter_logs.conf
+include $(BUILD_PREBUILT)
+
+# Crash reporter tests.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_reporter_tests
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_SHARED_LIBRARIES := libchrome \
+ libchromeos \
+ libdbus \
+ libpcrecpp
+LOCAL_SRC_FILES := $(crash_reporter_test_src)
+LOCAL_STATIC_LIBRARIES := libcrash libgmock
+include $(BUILD_NATIVE_TEST)
+
+endif # HOST_OS == linux
diff --git a/crash_reporter/MODULE_LICENSE_BSD b/crash_reporter/MODULE_LICENSE_BSD
deleted file mode 100644
index e69de29..0000000
--- a/crash_reporter/MODULE_LICENSE_BSD
+++ /dev/null
diff --git a/crash_reporter/NOTICE b/crash_reporter/NOTICE
deleted file mode 100644
index b9e779f..0000000
--- a/crash_reporter/NOTICE
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. 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.
diff --git a/crash_reporter/crash_collector.cc b/crash_reporter/crash_collector.cc
index 69fe939..77755f4 100644
--- a/crash_reporter/crash_collector.cc
+++ b/crash_reporter/crash_collector.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "crash_collector.h"
@@ -36,7 +48,7 @@
const char kLeaveCoreFile[] = "/root/.leave_core";
const char kLsbRelease[] = "/etc/lsb-release";
const char kShellPath[] = "/bin/sh";
-const char kSystemCrashPath[] = "/var/spool/crash";
+const char kSystemCrashPath[] = "/data/misc/crash_reporter/crash";
const char kUploadVarPrefix[] = "upload_var_";
const char kUploadFilePrefix[] = "upload_file_";
@@ -148,23 +160,13 @@
}
FilePath CrashCollector::GetCrashDirectoryInfo(
- uid_t process_euid,
- uid_t default_user_id,
- gid_t default_user_group,
mode_t *mode,
uid_t *directory_owner,
gid_t *directory_group) {
- if (process_euid == default_user_id) {
- *mode = kUserCrashPathMode;
- *directory_owner = default_user_id;
- *directory_group = default_user_group;
- return FilePath(kFallbackUserCrashPath);
- } else {
- *mode = kSystemCrashPathMode;
- *directory_owner = kRootOwner;
- *directory_group = kRootGroup;
- return FilePath(kSystemCrashPath);
- }
+ *mode = kSystemCrashPathMode;
+ *directory_owner = kRootOwner;
+ *directory_group = kRootGroup;
+ return FilePath(kSystemCrashPath);
}
bool CrashCollector::GetUserInfoFromName(const std::string &name,
@@ -188,9 +190,6 @@
bool CrashCollector::GetCreatedCrashDirectoryByEuid(uid_t euid,
FilePath *crash_directory,
bool *out_of_capacity) {
- uid_t default_user_id;
- gid_t default_user_group;
-
if (out_of_capacity) *out_of_capacity = false;
// For testing.
@@ -199,20 +198,11 @@
return true;
}
- if (!GetUserInfoFromName(kDefaultUserName,
- &default_user_id,
- &default_user_group)) {
- LOG(ERROR) << "Could not find default user info";
- return false;
- }
mode_t directory_mode;
uid_t directory_owner;
gid_t directory_group;
*crash_directory =
- GetCrashDirectoryInfo(euid,
- default_user_id,
- default_user_group,
- &directory_mode,
+ GetCrashDirectoryInfo(&directory_mode,
&directory_owner,
&directory_group);
@@ -238,6 +228,8 @@
if (!CheckHasCapacity(*crash_directory)) {
if (out_of_capacity) *out_of_capacity = true;
+ LOG(ERROR) << "Directory " << crash_directory->value()
+ << " is out of capacity.";
return false;
}
@@ -309,6 +301,8 @@
bool CrashCollector::CheckHasCapacity(const FilePath &crash_directory) {
DIR* dir = opendir(crash_directory.value().c_str());
if (!dir) {
+ LOG(WARNING) << "Unable to open crash directory "
+ << crash_directory.value();
return false;
}
struct dirent ent_buf;
diff --git a/crash_reporter/crash_collector.h b/crash_reporter/crash_collector.h
index 0d335cd..cfd76fd 100644
--- a/crash_reporter/crash_collector.h
+++ b/crash_reporter/crash_collector.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 CRASH_REPORTER_CRASH_COLLECTOR_H_
#define CRASH_REPORTER_CRASH_COLLECTOR_H_
@@ -72,12 +84,9 @@
forced_crash_directory_ = forced_directory;
}
- base::FilePath GetCrashDirectoryInfo(uid_t process_euid,
- uid_t default_user_id,
- gid_t default_user_group,
- mode_t *mode,
- uid_t *directory_owner,
- gid_t *directory_group);
+ base::FilePath GetCrashDirectoryInfo(mode_t *mode,
+ uid_t *directory_owner,
+ gid_t *directory_group);
bool GetUserInfoFromName(const std::string &name,
uid_t *uid,
gid_t *gid);
diff --git a/crash_reporter/crash_collector_test.cc b/crash_reporter/crash_collector_test.cc
index 13fb76a..32cbe9f 100644
--- a/crash_reporter/crash_collector_test.cc
+++ b/crash_reporter/crash_collector_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "crash_collector_test.h"
@@ -83,54 +95,6 @@
EXPECT_EQ("_", collector_.Sanitize(" "));
}
-TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
- FilePath path;
- const int kRootUid = 0;
- const int kRootGid = 0;
- const int kNtpUid = 5;
- const int kChronosUid = 1000;
- const int kChronosGid = 1001;
- const mode_t kExpectedSystemMode = 01755;
- const mode_t kExpectedUserMode = 0755;
-
- mode_t directory_mode;
- uid_t directory_owner;
- gid_t directory_group;
-
- path = collector_.GetCrashDirectoryInfo(kRootUid,
- kChronosUid,
- kChronosGid,
- &directory_mode,
- &directory_owner,
- &directory_group);
- EXPECT_EQ("/var/spool/crash", path.value());
- EXPECT_EQ(kExpectedSystemMode, directory_mode);
- EXPECT_EQ(kRootUid, directory_owner);
- EXPECT_EQ(kRootGid, directory_group);
-
- path = collector_.GetCrashDirectoryInfo(kNtpUid,
- kChronosUid,
- kChronosGid,
- &directory_mode,
- &directory_owner,
- &directory_group);
- EXPECT_EQ("/var/spool/crash", path.value());
- EXPECT_EQ(kExpectedSystemMode, directory_mode);
- EXPECT_EQ(kRootUid, directory_owner);
- EXPECT_EQ(kRootGid, directory_group);
-
- path = collector_.GetCrashDirectoryInfo(kChronosUid,
- kChronosUid,
- kChronosGid,
- &directory_mode,
- &directory_owner,
- &directory_group);
- EXPECT_EQ("/var/spool/crash", path.value());
- EXPECT_EQ(kExpectedUserMode, directory_mode);
- EXPECT_EQ(kChronosUid, directory_owner);
- EXPECT_EQ(kChronosGid, directory_group);
-}
-
TEST_F(CrashCollectorTest, FormatDumpBasename) {
struct tm tm = {0};
tm.tm_sec = 15;
diff --git a/crash_reporter/crash_collector_test.h b/crash_reporter/crash_collector_test.h
index c875d44..cfbb97b 100644
--- a/crash_reporter/crash_collector_test.h
+++ b/crash_reporter/crash_collector_test.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2013 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 CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
#define CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
index 0e45992..23bd342 100644
--- a/crash_reporter/crash_reporter.cc
+++ b/crash_reporter/crash_reporter.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 <fcntl.h> // for open
@@ -74,7 +86,7 @@
static void CountUserCrash() {
SendCrashMetrics(kCrashKindUser, "user");
std::string command = StringPrintf(
- "/usr/bin/dbus-send --type=signal --system / \"%s\" &",
+ "/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
diff --git a/crash_reporter/crash_reporter_logs.conf b/crash_reporter/crash_reporter_logs.conf
index f5ca80c..7db308c 100644
--- a/crash_reporter/crash_reporter_logs.conf
+++ b/crash_reporter/crash_reporter_logs.conf
@@ -1,6 +1,16 @@
-# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can
-# be found in the LICENSE file.
+# Copyright (C) 2012 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.
# This file is parsed by chromeos::KeyValueStore. It has the format:
#
diff --git a/crash_reporter/crash_reporter_logs_test.cc b/crash_reporter/crash_reporter_logs_test.cc
index 9879470..c9ca02d 100644
--- a/crash_reporter/crash_reporter_logs_test.cc
+++ b/crash_reporter/crash_reporter_logs_test.cc
@@ -1,6 +1,18 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <string>
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
index 641ae2d..fa2f8fc 100755
--- a/crash_reporter/crash_sender
+++ b/crash_reporter/crash_sender
@@ -1,8 +1,18 @@
#!/bin/sh
-# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
+# Copyright (C) 2010 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.
set -e
diff --git a/crash_reporter/init.crash_reporter.rc b/crash_reporter/init.crash_reporter.rc
new file mode 100644
index 0000000..6882b77
--- /dev/null
+++ b/crash_reporter/init.crash_reporter.rc
@@ -0,0 +1,18 @@
+on property:crash_reporter.coredump.enabled=1
+ write /proc/sys/kernel/core_pattern \
+ "|/system/bin/crash_reporter --user=%P:%s:%u:%e"
+
+on property:crash_reporter.coredump.enabled=0
+ write /proc/sys/kernel/core_pattern "core"
+
+on boot
+ # Allow catching multiple unrelated concurrent crashes, but use a finite
+ # number to prevent infinitely recursing on crash handling.
+ write /proc/sys/kernel/core_pipe_limit 4
+
+ # Create crash directories.
+ mkdir /data/misc/crash_reporter 0700 root root
+
+service crash_reporter /system/bin/crash_reporter --init
+ class late_start
+ oneshot
diff --git a/crash_reporter/kernel_collector.cc b/crash_reporter/kernel_collector.cc
index b3cbede..12b00b9 100644
--- a/crash_reporter/kernel_collector.cc
+++ b/crash_reporter/kernel_collector.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "kernel_collector.h"
diff --git a/crash_reporter/kernel_collector.h b/crash_reporter/kernel_collector.h
index 5fc4ac2..206ee26 100644
--- a/crash_reporter/kernel_collector.h
+++ b/crash_reporter/kernel_collector.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2010 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 CRASH_REPORTER_KERNEL_COLLECTOR_H_
#define CRASH_REPORTER_KERNEL_COLLECTOR_H_
diff --git a/crash_reporter/kernel_collector_test.cc b/crash_reporter/kernel_collector_test.cc
index a534803..e690b77 100644
--- a/crash_reporter/kernel_collector_test.cc
+++ b/crash_reporter/kernel_collector_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "kernel_collector_test.h"
diff --git a/crash_reporter/kernel_collector_test.h b/crash_reporter/kernel_collector_test.h
index d450134..f689e7d 100644
--- a/crash_reporter/kernel_collector_test.h
+++ b/crash_reporter/kernel_collector_test.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2014 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 CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
#define CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
diff --git a/crash_reporter/kernel_log_collector.sh b/crash_reporter/kernel_log_collector.sh
index d38479e..82512c2 100644
--- a/crash_reporter/kernel_log_collector.sh
+++ b/crash_reporter/kernel_log_collector.sh
@@ -1,8 +1,18 @@
#!/bin/sh
-# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
+# Copyright (C) 2013 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.
# Usage example: "kernel_log_collector.sh XXX YYY"
# This script searches logs in the /var/log/messages which have the keyword XXX.
diff --git a/crash_reporter/kernel_warning_collector.cc b/crash_reporter/kernel_warning_collector.cc
index 4cf7640..e28e8fd 100644
--- a/crash_reporter/kernel_warning_collector.cc
+++ b/crash_reporter/kernel_warning_collector.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "kernel_warning_collector.h"
diff --git a/crash_reporter/kernel_warning_collector.h b/crash_reporter/kernel_warning_collector.h
index 82c509c..5ccb780 100644
--- a/crash_reporter/kernel_warning_collector.h
+++ b/crash_reporter/kernel_warning_collector.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2013 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 CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
#define CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
diff --git a/crash_reporter/list_proxies.cc b/crash_reporter/list_proxies.cc
index de6ef0a..a39441d 100644
--- a/crash_reporter/list_proxies.cc
+++ b/crash_reporter/list_proxies.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2011 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 <sysexits.h>
#include <unistd.h> // for isatty()
diff --git a/crash_reporter/testrunner.cc b/crash_reporter/testrunner.cc
index d45bbf8..a8c717e 100644
--- a/crash_reporter/testrunner.cc
+++ b/crash_reporter/testrunner.cc
@@ -1,6 +1,18 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <chromeos/test_helpers.h>
#include <gtest/gtest.h>
diff --git a/crash_reporter/udev_collector.cc b/crash_reporter/udev_collector.cc
index 85f40db..576fdbd 100644
--- a/crash_reporter/udev_collector.cc
+++ b/crash_reporter/udev_collector.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "udev_collector.h"
diff --git a/crash_reporter/udev_collector.h b/crash_reporter/udev_collector.h
index d9b37eb..e267b75 100644
--- a/crash_reporter/udev_collector.h
+++ b/crash_reporter/udev_collector.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 CRASH_REPORTER_UDEV_COLLECTOR_H_
#define CRASH_REPORTER_UDEV_COLLECTOR_H_
diff --git a/crash_reporter/udev_collector_test.cc b/crash_reporter/udev_collector_test.cc
index 4897b91..a6643fb 100644
--- a/crash_reporter/udev_collector_test.cc
+++ b/crash_reporter/udev_collector_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 <base/files/file_enumerator.h>
#include <base/files/file_util.h>
diff --git a/crash_reporter/unclean_shutdown_collector.cc b/crash_reporter/unclean_shutdown_collector.cc
index a6da1bb..8a092ec 100644
--- a/crash_reporter/unclean_shutdown_collector.cc
+++ b/crash_reporter/unclean_shutdown_collector.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2010 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 "unclean_shutdown_collector.h"
diff --git a/crash_reporter/unclean_shutdown_collector.h b/crash_reporter/unclean_shutdown_collector.h
index 2ce0842..5bc9968 100644
--- a/crash_reporter/unclean_shutdown_collector.h
+++ b/crash_reporter/unclean_shutdown_collector.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2010 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 CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
#define CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
diff --git a/crash_reporter/unclean_shutdown_collector_test.cc b/crash_reporter/unclean_shutdown_collector_test.cc
index dc420fb..c5c0662 100644
--- a/crash_reporter/unclean_shutdown_collector_test.cc
+++ b/crash_reporter/unclean_shutdown_collector_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2010 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 "unclean_shutdown_collector.h"
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
index 069b581..61ccc37 100644
--- a/crash_reporter/user_collector.cc
+++ b/crash_reporter/user_collector.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "user_collector.h"
@@ -12,6 +24,7 @@
#include <stdint.h>
#include <sys/cdefs.h> // For __WORDSIZE
#include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS.
+#include <unistd.h> // For setgroups
#include <string>
#include <vector>
@@ -24,21 +37,18 @@
#include <base/strings/stringprintf.h>
#include <chromeos/process.h>
#include <chromeos/syslog_logging.h>
+#include <cutils/properties.h>
+#include <private/android_filesystem_config.h>
static const char kCollectionErrorSignature[] =
"crash_reporter-user-collection";
-// This procfs file is used to cause kernel core file writing to
-// instead pipe the core file into a user space process. See
-// core(5) man page.
-static const char kCorePatternFile[] = "/proc/sys/kernel/core_pattern";
-static const char kCorePipeLimitFile[] = "/proc/sys/kernel/core_pipe_limit";
-// Set core_pipe_limit to 4 so that we can catch a few unrelated concurrent
-// crashes, but finite to avoid infinitely recursing on crash handling.
-static const char kCorePipeLimit[] = "4";
-static const char kCoreToMinidumpConverterPath[] = "/usr/bin/core2md";
+static const char kCorePatternProperty[] = "crash_reporter.coredump.enabled";
+static const char kCoreToMinidumpConverterPath[] = "/system/bin/core2md";
static const char kStatePrefix[] = "State:\t";
+static const char kCoreTempFolder[] = "/data/misc/crash_reporter/tmp";
+
// Define an otherwise invalid value that represents an unknown UID.
static const uid_t kUnknownUid = -1;
@@ -50,8 +60,6 @@
UserCollector::UserCollector()
: generate_diagnostics_(false),
- core_pattern_file_(kCorePatternFile),
- core_pipe_limit_file_(kCorePipeLimitFile),
initialized_(false) {
}
@@ -71,6 +79,11 @@
core2md_failure_ = core2md_failure;
directory_failure_ = directory_failure;
filter_in_ = filter_in;
+
+ gid_t groups[] = { AID_SYSTEM, AID_DBUS };
+ if (setgroups(arraysize(groups), groups) != 0) {
+ PLOG(FATAL) << "Unable to set groups to system and dbus";
+ }
}
UserCollector::~UserCollector() {
@@ -115,18 +128,8 @@
CHECK(initialized_);
LOG(INFO) << (enabled ? "Enabling" : "Disabling") << " user crash handling";
- if (base::WriteFile(FilePath(core_pipe_limit_file_), kCorePipeLimit,
- strlen(kCorePipeLimit)) !=
- static_cast<int>(strlen(kCorePipeLimit))) {
- PLOG(ERROR) << "Unable to write " << core_pipe_limit_file_;
- return false;
- }
- std::string pattern = GetPattern(enabled);
- if (base::WriteFile(FilePath(core_pattern_file_), pattern.c_str(),
- pattern.length()) != static_cast<int>(pattern.length())) {
- PLOG(ERROR) << "Unable to write " << core_pattern_file_;
- return false;
- }
+ property_set(kCorePatternProperty, enabled ? "1" : "0");
+
return true;
}
@@ -342,7 +345,7 @@
bool UserCollector::CopyStdinToCoreFile(const FilePath &core_path) {
// Copy off all stdin to a core file.
- FilePath stdin_path("/dev/fd/0");
+ FilePath stdin_path("/proc/self/fd/0");
if (base::CopyFile(stdin_path, core_path)) {
return true;
}
@@ -438,7 +441,7 @@
// Directory like /tmp/crash_reporter/1234 which contains the
// procfs entries and other temporary files used during conversion.
- FilePath container_dir(StringPrintf("/tmp/crash_reporter/%d", pid));
+ FilePath container_dir(StringPrintf("%s/%d", kCoreTempFolder, pid));
// Delete a pre-existing directory from crash reporter that may have
// been left around for diagnostics from a failed conversion attempt.
// If we don't, existing files can cause forking to fail.
diff --git a/crash_reporter/user_collector.h b/crash_reporter/user_collector.h
index 7b356ee..8c38aa2 100644
--- a/crash_reporter/user_collector.h
+++ b/crash_reporter/user_collector.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2010 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 CRASH_REPORTER_USER_COLLECTOR_H_
#define CRASH_REPORTER_USER_COLLECTOR_H_
@@ -47,16 +59,6 @@
bool HandleCrash(const std::string &crash_attributes,
const char *force_exec);
- // Set (override the default) core file pattern.
- void set_core_pattern_file(const std::string &pattern) {
- core_pattern_file_ = pattern;
- }
-
- // Set (override the default) core pipe limit file.
- void set_core_pipe_limit_file(const std::string &path) {
- core_pipe_limit_file_ = path;
- }
-
private:
friend class UserCollectorTest;
FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPath);
@@ -172,8 +174,6 @@
std::string *reason);
bool generate_diagnostics_;
- std::string core_pattern_file_;
- std::string core_pipe_limit_file_;
std::string our_path_;
bool initialized_;
diff --git a/crash_reporter/user_collector_test.cc b/crash_reporter/user_collector_test.cc
index ee3ca12..4419e7c 100644
--- a/crash_reporter/user_collector_test.cc
+++ b/crash_reporter/user_collector_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2012 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 "user_collector.h"
@@ -60,8 +72,6 @@
"");
base::DeleteFile(FilePath("test"), true);
mkdir("test", 0777);
- collector_.set_core_pattern_file("test/core_pattern");
- collector_.set_core_pipe_limit_file("test/core_pipe_limit");
pid_ = getpid();
chromeos::ClearLog();
}
@@ -84,49 +94,6 @@
pid_t pid_;
};
-TEST_F(UserCollectorTest, EnableOK) {
- ASSERT_TRUE(collector_.Enable());
- ExpectFileEquals("|/my/path --user=%P:%s:%u:%e",
- FilePath("test/core_pattern"));
- ExpectFileEquals("4", FilePath("test/core_pipe_limit"));
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Enabling user crash handling"));
-}
-
-TEST_F(UserCollectorTest, EnableNoPatternFileAccess) {
- collector_.set_core_pattern_file("/does_not_exist");
- ASSERT_FALSE(collector_.Enable());
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Enabling user crash handling"));
- EXPECT_TRUE(FindLog("Unable to write /does_not_exist"));
-}
-
-TEST_F(UserCollectorTest, EnableNoPipeLimitFileAccess) {
- collector_.set_core_pipe_limit_file("/does_not_exist");
- ASSERT_FALSE(collector_.Enable());
- ASSERT_EQ(s_crashes, 0);
- // Core pattern should not be written if we cannot access the pipe limit
- // or otherwise we may set a pattern that results in infinite recursion.
- ASSERT_FALSE(base::PathExists(FilePath("test/core_pattern")));
- EXPECT_TRUE(FindLog("Enabling user crash handling"));
- EXPECT_TRUE(FindLog("Unable to write /does_not_exist"));
-}
-
-TEST_F(UserCollectorTest, DisableOK) {
- ASSERT_TRUE(collector_.Disable());
- ExpectFileEquals("core", FilePath("test/core_pattern"));
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Disabling user crash handling"));
-}
-
-TEST_F(UserCollectorTest, DisableNoFileAccess) {
- collector_.set_core_pattern_file("/does_not_exist");
- ASSERT_FALSE(collector_.Disable());
- ASSERT_EQ(s_crashes, 0);
- EXPECT_TRUE(FindLog("Disabling user crash handling"));
- EXPECT_TRUE(FindLog("Unable to write /does_not_exist"));
-}
-
TEST_F(UserCollectorTest, ParseCrashAttributes) {
pid_t pid;
int signal;
diff --git a/crash_reporter/warn_collector.l b/crash_reporter/warn_collector.l
index de746fe..70ab25c 100644
--- a/crash_reporter/warn_collector.l
+++ b/crash_reporter/warn_collector.l
@@ -1,6 +1,17 @@
-/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
+/*
+ * Copyright (C) 2013 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.
*
* This flex program reads /var/log/messages as it grows and saves kernel
* warnings to files. It keeps track of warnings it has seen (based on
diff --git a/crash_reporter/warn_collector_test.c b/crash_reporter/warn_collector_test.c
index 7e25d01..7ebe0a8 100644
--- a/crash_reporter/warn_collector_test.c
+++ b/crash_reporter/warn_collector_test.c
@@ -1,6 +1,17 @@
-/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
+/*
+ * Copyright (C) 2013 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.
*/
/*
diff --git a/crash_reporter/warn_collector_test.sh b/crash_reporter/warn_collector_test.sh
index d9bb6f9..a5af16c 100755
--- a/crash_reporter/warn_collector_test.sh
+++ b/crash_reporter/warn_collector_test.sh
@@ -1,7 +1,18 @@
#! /bin/bash
-# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
+
+# Copyright (C) 2013 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.
# Test for warn_collector. Run the warn collector in the background, emulate
# the kernel by appending lines to the log file "messages", and observe the log
diff --git a/crash_reporter/warn_collector_test_reporter.sh b/crash_reporter/warn_collector_test_reporter.sh
index d8f3fad..b6096ed 100755
--- a/crash_reporter/warn_collector_test_reporter.sh
+++ b/crash_reporter/warn_collector_test_reporter.sh
@@ -1,7 +1,18 @@
#! /bin/sh
-# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
+
+# Copyright (C) 2013 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.
# Replacement for the crash reporter, for testing. Log the first line of the
# "warning" file, which by convention contains the warning hash, and remove the
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 3fca709..f7a5f82 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -27,6 +27,9 @@
LOCAL_CPPFLAGS := $(common_cppflags)
+LOCAL_INIT_RC_32 := debuggerd.rc
+LOCAL_INIT_RC_64 := debuggerd64.rc
+
ifeq ($(TARGET_IS_64_BIT),true)
LOCAL_CPPFLAGS += -DTARGET_IS_64_BIT
endif
diff --git a/debuggerd/debuggerd.rc b/debuggerd/debuggerd.rc
new file mode 100644
index 0000000..4338ae9
--- /dev/null
+++ b/debuggerd/debuggerd.rc
@@ -0,0 +1,2 @@
+service debuggerd /system/bin/debuggerd
+ class main
diff --git a/debuggerd/debuggerd64.rc b/debuggerd/debuggerd64.rc
new file mode 100644
index 0000000..341a329
--- /dev/null
+++ b/debuggerd/debuggerd64.rc
@@ -0,0 +1,2 @@
+service debuggerd64 /system/bin/debuggerd64
+ class main
diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp
index d8905a6..c1028ef 100644
--- a/fastboot/bootimg_utils.cpp
+++ b/fastboot/bootimg_utils.cpp
@@ -32,32 +32,27 @@
#include <stdlib.h>
#include <string.h>
-void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline)
+void bootimg_set_cmdline(boot_img_hdr* h, const char* cmdline)
{
strcpy((char*) h->cmdline, cmdline);
}
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
- void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
- void *second, unsigned second_size, unsigned second_offset,
- unsigned page_size, unsigned base, unsigned tags_offset,
- unsigned *bootimg_size)
+boot_img_hdr* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset,
+ void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset,
+ void* second, int64_t second_size, off_t second_offset,
+ size_t page_size, size_t base, off_t tags_offset,
+ int64_t* bootimg_size)
{
- unsigned kernel_actual;
- unsigned ramdisk_actual;
- unsigned second_actual;
- unsigned page_mask;
+ size_t page_mask = page_size - 1;
- page_mask = page_size - 1;
-
- kernel_actual = (kernel_size + page_mask) & (~page_mask);
- ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
- second_actual = (second_size + page_mask) & (~page_mask);
+ int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask);
+ int64_t ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
+ int64_t second_actual = (second_size + page_mask) & (~page_mask);
*bootimg_size = page_size + kernel_actual + ramdisk_actual + second_actual;
boot_img_hdr* hdr = reinterpret_cast<boot_img_hdr*>(calloc(*bootimg_size, 1));
- if (hdr == 0) {
+ if (hdr == nullptr) {
return hdr;
}
@@ -74,12 +69,9 @@
hdr->page_size = page_size;
+ memcpy(hdr->magic + page_size, kernel, kernel_size);
+ memcpy(hdr->magic + page_size + kernel_actual, ramdisk, ramdisk_size);
+ memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual, second, second_size);
- memcpy(hdr->magic + page_size,
- kernel, kernel_size);
- memcpy(hdr->magic + page_size + kernel_actual,
- ramdisk, ramdisk_size);
- memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual,
- second, second_size);
return hdr;
}
diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h
index b1a86cd..fcc8662 100644
--- a/fastboot/bootimg_utils.h
+++ b/fastboot/bootimg_utils.h
@@ -30,20 +30,14 @@
#define _FASTBOOT_BOOTIMG_UTILS_H_
#include <bootimg.h>
+#include <inttypes.h>
+#include <sys/types.h>
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
- void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
- void *second, unsigned second_size, unsigned second_offset,
- unsigned page_size, unsigned base, unsigned tags_offset,
- unsigned *bootimg_size);
-
-#if defined(__cplusplus)
-}
-#endif
+void bootimg_set_cmdline(boot_img_hdr* h, const char* cmdline);
+boot_img_hdr* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset,
+ void* ramdisk, int64_t ramdisk_size, off_t ramdisk_offset,
+ void* second, int64_t second_size, off_t second_offset,
+ size_t page_size, size_t base, off_t tags_offset,
+ int64_t* bootimg_size);
#endif
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 66b8140..a0e990a 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -31,7 +31,6 @@
#include <errno.h>
#include <stdarg.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -39,12 +38,6 @@
#include <sys/types.h>
#include <unistd.h>
-#ifdef USE_MINGW
-#include <fcntl.h>
-#else
-#include <sys/mman.h>
-#endif
-
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define OP_DOWNLOAD 1
@@ -58,15 +51,17 @@
#define CMD_SIZE 64
-struct Action
-{
+struct Action {
unsigned op;
- Action *next;
+ Action* next;
char cmd[CMD_SIZE];
- const char *prod;
- void *data;
- unsigned size;
+ const char* prod;
+ void* data;
+
+ // The protocol only supports 32-bit sizes, so you'll have to break
+ // anything larger into chunks.
+ uint32_t size;
const char *msg;
int (*func)(Action* a, int status, const char* resp);
@@ -267,7 +262,7 @@
}
void fb_queue_require(const char *prod, const char *var,
- int invert, unsigned nvalues, const char **value)
+ bool invert, size_t nvalues, const char **value)
{
Action *a;
a = queue_action(OP_QUERY, "getvar:%s", var);
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 5d7b151..e2971f2 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -34,7 +34,6 @@
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
-#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -67,12 +66,12 @@
static int64_t sparse_limit = -1;
static int64_t target_sparse_limit = -1;
-unsigned page_size = 2048;
-unsigned base_addr = 0x10000000;
-unsigned kernel_offset = 0x00008000;
-unsigned ramdisk_offset = 0x01000000;
-unsigned second_offset = 0x00f00000;
-unsigned tags_offset = 0x00000100;
+static unsigned page_size = 2048;
+static unsigned base_addr = 0x10000000;
+static unsigned kernel_offset = 0x00008000;
+static unsigned ramdisk_offset = 0x01000000;
+static unsigned second_offset = 0x00f00000;
+static unsigned tags_offset = 0x00000100;
enum fb_buffer_type {
FB_BUFFER,
@@ -81,8 +80,8 @@
struct fastboot_buffer {
enum fb_buffer_type type;
- void *data;
- unsigned int sz;
+ void* data;
+ int64_t sz;
};
static struct {
@@ -97,8 +96,7 @@
{"vendor.img", "vendor.sig", "vendor", true},
};
-char *find_item(const char *item, const char *product)
-{
+static char* find_item(const char* item, const char* product) {
char *dir;
const char *fn;
char path[PATH_MAX + 128];
@@ -139,36 +137,26 @@
return strdup(path);
}
-static int64_t file_size(int fd)
-{
- struct stat st;
- int ret;
-
- ret = fstat(fd, &st);
-
- return ret ? -1 : st.st_size;
+static int64_t get_file_size(int fd) {
+ struct stat sb;
+ return fstat(fd, &sb) == -1 ? -1 : sb.st_size;
}
-static void *load_fd(int fd, unsigned *_sz)
-{
- char *data;
- int sz;
+static void* load_fd(int fd, int64_t* sz) {
int errno_tmp;
+ char* data = nullptr;
- data = 0;
-
- sz = file_size(fd);
- if (sz < 0) {
+ *sz = get_file_size(fd);
+ if (*sz < 0) {
goto oops;
}
- data = (char*) malloc(sz);
- if(data == 0) goto oops;
+ data = (char*) malloc(*sz);
+ if (data == nullptr) goto oops;
- if(read(fd, data, sz) != sz) goto oops;
+ if(read(fd, data, *sz) != *sz) goto oops;
close(fd);
- if(_sz) *_sz = sz;
return data;
oops:
@@ -179,19 +167,15 @@
return 0;
}
-static void *load_file(const char *fn, unsigned *_sz)
-{
- int fd;
-
- fd = open(fn, O_RDONLY | O_BINARY);
- if(fd < 0) return 0;
-
- return load_fd(fd, _sz);
+static void* load_file(const char* fn, int64_t* sz) {
+ int fd = open(fn, O_RDONLY | O_BINARY);
+ if (fd == -1) return nullptr;
+ return load_fd(fd, sz);
}
-int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
+static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
// Require a matching vendor id if the user specified one with -i.
- if (vendor_id != 0 && info->dev_vendor != vendor_id) {
+ if (vendor_id != 0 && info->dev_vendor != vendor_id) {
return -1;
}
@@ -206,14 +190,12 @@
return 0;
}
-int match_fastboot(usb_ifc_info *info)
-{
+static int match_fastboot(usb_ifc_info* info) {
return match_fastboot_with_serial(info, serial);
}
-int list_devices_callback(usb_ifc_info *info)
-{
- if (match_fastboot_with_serial(info, NULL) == 0) {
+static int list_devices_callback(usb_ifc_info* info) {
+ if (match_fastboot_with_serial(info, nullptr) == 0) {
const char* serial = info->serial_number;
if (!info->writable) {
serial = "no permissions"; // like "adb devices"
@@ -234,8 +216,7 @@
return -1;
}
-usb_handle *open_device(void)
-{
+static usb_handle* open_device() {
static usb_handle *usb = 0;
int announce = 1;
@@ -246,21 +227,20 @@
if(usb) return usb;
if(announce) {
announce = 0;
- fprintf(stderr,"< waiting for device >\n");
+ fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device");
}
usleep(1000);
}
}
-void list_devices(void) {
+static void list_devices() {
// We don't actually open a USB device here,
// just getting our callback called so we can
// list all the connected devices.
usb_open(list_devices_callback);
}
-void usage(void)
-{
+static void usage() {
fprintf(stderr,
/* 1234567890123456789012345678901234567890123456789012345678901234567890123456 */
"usage: fastboot [ <option> ] <command>\n"
@@ -315,31 +295,26 @@
);
}
-void *load_bootable_image(const char *kernel, const char *ramdisk,
- const char *secondstage, unsigned *sz,
- const char *cmdline)
-{
- void *kdata = 0, *rdata = 0, *sdata = 0;
- unsigned ksize = 0, rsize = 0, ssize = 0;
- void *bdata;
- unsigned bsize;
-
- if(kernel == 0) {
+static void* load_bootable_image(const char* kernel, const char* ramdisk,
+ const char* secondstage, int64_t* sz,
+ const char* cmdline) {
+ if (kernel == nullptr) {
fprintf(stderr, "no image specified\n");
return 0;
}
- kdata = load_file(kernel, &ksize);
- if(kdata == 0) {
+ int64_t ksize;
+ void* kdata = load_file(kernel, &ksize);
+ if (kdata == nullptr) {
fprintf(stderr, "cannot load '%s': %s\n", kernel, strerror(errno));
return 0;
}
- /* is this actually a boot image? */
+ // Is this actually a boot image?
if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
- if(cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
+ if (cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline);
- if(ramdisk) {
+ if (ramdisk) {
fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n");
return 0;
}
@@ -348,39 +323,44 @@
return kdata;
}
- if(ramdisk) {
+ void* rdata = nullptr;
+ int64_t rsize = 0;
+ if (ramdisk) {
rdata = load_file(ramdisk, &rsize);
- if(rdata == 0) {
+ if (rdata == nullptr) {
fprintf(stderr,"cannot load '%s': %s\n", ramdisk, strerror(errno));
return 0;
}
}
+ void* sdata = nullptr;
+ int64_t ssize = 0;
if (secondstage) {
sdata = load_file(secondstage, &ssize);
- if(sdata == 0) {
+ if (sdata == nullptr) {
fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
return 0;
}
}
fprintf(stderr,"creating boot image...\n");
- bdata = mkbootimg(kdata, ksize, kernel_offset,
+ int64_t bsize = 0;
+ void* bdata = mkbootimg(kdata, ksize, kernel_offset,
rdata, rsize, ramdisk_offset,
sdata, ssize, second_offset,
page_size, base_addr, tags_offset, &bsize);
- if(bdata == 0) {
+ if (bdata == nullptr) {
fprintf(stderr,"failed to create boot.img\n");
return 0;
}
- if(cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
- fprintf(stderr,"creating boot image - %d bytes\n", bsize);
+ if (cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline);
+ fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize);
*sz = bsize;
return bdata;
}
-static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned* sz)
+static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, int64_t* sz)
{
ZipString zip_entry_name(entry_name);
ZipEntry zip_entry;
@@ -392,8 +372,8 @@
*sz = zip_entry.uncompressed_length;
uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
- if (data == NULL) {
- fprintf(stderr, "failed to allocate %u bytes for '%s'\n", *sz, entry_name);
+ if (data == nullptr) {
+ fprintf(stderr, "failed to allocate %" PRId64 " bytes for '%s'\n", *sz, entry_name);
return 0;
}
@@ -438,7 +418,7 @@
static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
FILE* fp = tmpfile();
- if (fp == NULL) {
+ if (fp == nullptr) {
fprintf(stderr, "failed to create temporary file for '%s': %s\n",
entry_name, strerror(errno));
return -1;
@@ -478,7 +458,7 @@
static int setup_requirement_line(char *name)
{
char *val[MAX_OPTIONS];
- char *prod = NULL;
+ char *prod = nullptr;
unsigned n, count;
char *x;
int invert = 0;
@@ -539,13 +519,10 @@
return 0;
}
-static void setup_requirements(char *data, unsigned sz)
-{
- char *s;
-
- s = data;
+static void setup_requirements(char* data, int64_t sz) {
+ char* s = data;
while (sz-- > 0) {
- if(*s == '\n') {
+ if (*s == '\n') {
*s++ = 0;
if (setup_requirement_line(data)) {
die("out of memory");
@@ -557,8 +534,7 @@
}
}
-void queue_info_dump(void)
-{
+static void queue_info_dump() {
fb_queue_notice("--------------------------------------------");
fb_queue_display("version-bootloader", "Bootloader Version...");
fb_queue_display("version-baseband", "Baseband Version.....");
@@ -573,7 +549,7 @@
die("cannot sparse read file\n");
}
- int files = sparse_file_resparse(s, max_size, NULL, 0);
+ int files = sparse_file_resparse(s, max_size, nullptr, 0);
if (files < 0) {
die("Failed to resparse\n");
}
@@ -598,7 +574,7 @@
int status = fb_getvar(usb, response, "max-download-size");
if (!status) {
- limit = strtoul(response, NULL, 0);
+ limit = strtoul(response, nullptr, 0);
if (limit > 0) {
fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n",
limit);
@@ -643,35 +619,27 @@
/* The function fb_format_supported() currently returns the value
* we want, so just call it.
*/
- return fb_format_supported(usb, part, NULL);
+ return fb_format_supported(usb, part, nullptr);
}
-static int load_buf_fd(usb_handle *usb, int fd,
- struct fastboot_buffer *buf)
-{
- int64_t sz64;
- void *data;
- int64_t limit;
-
-
- sz64 = file_size(fd);
- if (sz64 < 0) {
+static int load_buf_fd(usb_handle* usb, int fd, struct fastboot_buffer* buf) {
+ int64_t sz = get_file_size(fd);
+ if (sz == -1) {
return -1;
}
- lseek(fd, 0, SEEK_SET);
- limit = get_sparse_limit(usb, sz64);
+ lseek64(fd, 0, SEEK_SET);
+ int64_t limit = get_sparse_limit(usb, sz);
if (limit) {
- struct sparse_file **s = load_sparse_files(fd, limit);
- if (s == NULL) {
+ sparse_file** s = load_sparse_files(fd, limit);
+ if (s == nullptr) {
return -1;
}
buf->type = FB_BUFFER_SPARSE;
buf->data = s;
} else {
- unsigned int sz;
- data = load_fd(fd, &sz);
- if (data == 0) return -1;
+ void* data = load_fd(fd, &sz);
+ if (data == nullptr) return -1;
buf->type = FB_BUFFER;
buf->data = data;
buf->sz = sz;
@@ -701,8 +669,8 @@
case FB_BUFFER_SPARSE:
s = reinterpret_cast<sparse_file**>(buf->data);
while (*s) {
- int64_t sz64 = sparse_file_len(*s, true, false);
- fb_queue_flash_sparse(pname, *s++, sz64);
+ int64_t sz = sparse_file_len(*s, true, false);
+ fb_queue_flash_sparse(pname, *s++, sz);
}
break;
case FB_BUFFER:
@@ -713,8 +681,7 @@
}
}
-void do_flash(usb_handle *usb, const char *pname, const char *fname)
-{
+static void do_flash(usb_handle* usb, const char* pname, const char* fname) {
struct fastboot_buffer buf;
if (load_buf(usb, fname, &buf)) {
@@ -723,17 +690,15 @@
flash_buf(pname, &buf);
}
-void do_update_signature(ZipArchiveHandle zip, char *fn)
-{
- unsigned sz;
+static void do_update_signature(ZipArchiveHandle zip, char* fn) {
+ int64_t sz;
void* data = unzip_file(zip, fn, &sz);
- if (data == 0) return;
+ if (data == nullptr) return;
fb_queue_download("signature", data, sz);
fb_queue_command("signature", "installing signature");
}
-void do_update(usb_handle *usb, const char *filename, int erase_first)
-{
+static void do_update(usb_handle* usb, const char* filename, bool erase_first) {
queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product));
@@ -745,9 +710,9 @@
die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
}
- unsigned sz;
+ int64_t sz;
void* data = unzip_file(zip, "android-info.txt", &sz);
- if (data == 0) {
+ if (data == nullptr) {
CloseArchive(zip);
die("update package '%s' has no android-info.txt", filename);
}
@@ -780,36 +745,33 @@
CloseArchive(zip);
}
-void do_send_signature(char *fn)
-{
- void *data;
- unsigned sz;
- char *xtn;
-
- xtn = strrchr(fn, '.');
+static void do_send_signature(char* fn) {
+ char* xtn = strrchr(fn, '.');
if (!xtn) return;
+
if (strcmp(xtn, ".img")) return;
- strcpy(xtn,".sig");
- data = load_file(fn, &sz);
- strcpy(xtn,".img");
- if (data == 0) return;
+ strcpy(xtn, ".sig");
+
+ int64_t sz;
+ void* data = load_file(fn, &sz);
+ strcpy(xtn, ".img");
+ if (data == nullptr) return;
fb_queue_download("signature", data, sz);
fb_queue_command("signature", "installing signature");
}
-void do_flashall(usb_handle *usb, int erase_first)
-{
+static void do_flashall(usb_handle* usb, int erase_first) {
queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product));
char* fname = find_item("info", product);
- if (fname == 0) die("cannot find android-info.txt");
+ if (fname == nullptr) die("cannot find android-info.txt");
- unsigned sz;
+ int64_t sz;
void* data = load_file(fname, &sz);
- if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
+ if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno));
setup_requirements(reinterpret_cast<char*>(data), sz);
@@ -832,8 +794,7 @@
#define skip(n) do { argc -= (n); argv += (n); } while (0)
#define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0)
-int do_oem_command(int argc, char **argv)
-{
+static int do_oem_command(int argc, char** argv) {
char command[256];
if (argc <= 1) return 0;
@@ -890,16 +851,15 @@
return num;
}
-void fb_perform_format(usb_handle* usb,
- const char *partition, int skip_if_not_supported,
- const char *type_override, const char *size_override)
-{
+static void fb_perform_format(usb_handle* usb,
+ const char *partition, int skip_if_not_supported,
+ const char *type_override, const char *size_override) {
char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1];
char *pType = pTypeBuff;
char *pSize = pSizeBuff;
unsigned int limit = INT_MAX;
struct fastboot_buffer buf;
- const char *errMsg = NULL;
+ const char *errMsg = nullptr;
const struct fs_generator *gen;
uint64_t pSz;
int status;
@@ -949,7 +909,7 @@
return;
}
- pSz = strtoll(pSize, (char **)NULL, 16);
+ pSz = strtoll(pSize, (char **)nullptr, 16);
fd = fileno(tmpfile());
if (fs_generator_generate(gen, fd, pSz)) {
@@ -982,9 +942,9 @@
int wants_wipe = 0;
int wants_reboot = 0;
int wants_reboot_bootloader = 0;
- int erase_first = 1;
+ bool erase_first = true;
void *data;
- unsigned sz;
+ int64_t sz;
int status;
int c;
int longindex;
@@ -1020,7 +980,7 @@
usage();
return 1;
case 'i': {
- char *endptr = NULL;
+ char *endptr = nullptr;
unsigned long val;
val = strtoul(optarg, &endptr, 0);
@@ -1036,7 +996,7 @@
long_listing = 1;
break;
case 'n':
- page_size = (unsigned)strtoul(optarg, NULL, 0);
+ page_size = (unsigned)strtoul(optarg, nullptr, 0);
if (!page_size) die("invalid page size");
break;
case 'p':
@@ -1058,7 +1018,7 @@
}
break;
case 'u':
- erase_first = 0;
+ erase_first = false;
break;
case 'w':
wants_wipe = 1;
@@ -1067,8 +1027,8 @@
return 1;
case 0:
if (strcmp("unbuffered", longopts[longindex].name) == 0) {
- setvbuf(stdout, NULL, _IONBF, 0);
- setvbuf(stderr, NULL, _IONBF, 0);
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ setvbuf(stderr, nullptr, _IONBF, 0);
} else if (strcmp("version", longopts[longindex].name) == 0) {
fprintf(stdout, "fastboot version %s\n", FASTBOOT_REVISION);
return 0;
@@ -1108,7 +1068,7 @@
} else if(!strcmp(*argv, "erase")) {
require(2);
- if (fb_format_supported(usb, argv[1], NULL)) {
+ if (fb_format_supported(usb, argv[1], nullptr)) {
fprintf(stderr, "******** Did you mean to fastboot format this partition?\n");
}
@@ -1116,8 +1076,8 @@
skip(2);
} else if(!strncmp(*argv, "format", strlen("format"))) {
char *overrides;
- char *type_override = NULL;
- char *size_override = NULL;
+ char *type_override = nullptr;
+ char *size_override = nullptr;
require(2);
/*
* Parsing for: "format[:[type][:[size]]]"
@@ -1138,8 +1098,8 @@
}
type_override = overrides;
}
- if (type_override && !type_override[0]) type_override = NULL;
- if (size_override && !size_override[0]) size_override = NULL;
+ if (type_override && !type_override[0]) type_override = nullptr;
+ if (size_override && !size_override[0]) size_override = nullptr;
if (erase_first && needs_erase(usb, argv[1])) {
fb_queue_erase(argv[1]);
}
@@ -1148,7 +1108,7 @@
} else if(!strcmp(*argv, "signature")) {
require(2);
data = load_file(argv[1], &sz);
- if (data == 0) die("could not load '%s': %s", argv[1], strerror(errno));
+ if (data == nullptr) die("could not load '%s': %s", argv[1], strerror(errno));
if (sz != 256) die("signature must be 256 bytes");
fb_queue_download("signature", data, sz);
fb_queue_command("signature", "installing signature");
@@ -1258,9 +1218,9 @@
if (wants_wipe) {
fb_queue_erase("userdata");
- fb_perform_format(usb, "userdata", 1, NULL, NULL);
+ fb_perform_format(usb, "userdata", 1, nullptr, nullptr);
fb_queue_erase("cache");
- fb_perform_format(usb, "cache", 1, NULL, NULL);
+ fb_perform_format(usb, "cache", 1, nullptr, nullptr);
}
if (wants_reboot) {
fb_queue_reboot();
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 481c501..091a70f 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -29,18 +29,17 @@
#ifndef _FASTBOOT_H_
#define _FASTBOOT_H_
-#include "usb.h"
+#include <inttypes.h>
+#include <stdlib.h>
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include "usb.h"
struct sparse_file;
/* protocol.c - fastboot protocol */
int fb_command(usb_handle *usb, const char *cmd);
int fb_command_response(usb_handle *usb, const char *cmd, char *response);
-int fb_download_data(usb_handle *usb, const void *data, unsigned size);
+int fb_download_data(usb_handle *usb, const void *data, uint32_t size);
int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s);
char *fb_get_error(void);
@@ -50,17 +49,17 @@
/* engine.c - high level command queue engine */
int fb_getvar(struct usb_handle *usb, char *response, const char *fmt, ...);
int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override);
-void fb_queue_flash(const char *ptn, void *data, unsigned sz);
-void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, unsigned sz);
+void fb_queue_flash(const char *ptn, void *data, uint32_t sz);
+void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, uint32_t sz);
void fb_queue_erase(const char *ptn);
-void fb_queue_format(const char *ptn, int skip_if_not_supported, unsigned int max_chunk_sz);
-void fb_queue_require(const char *prod, const char *var, int invert,
- unsigned nvalues, const char **value);
+void fb_queue_format(const char *ptn, int skip_if_not_supported, int32_t max_chunk_sz);
+void fb_queue_require(const char *prod, const char *var, bool invert,
+ size_t nvalues, const char **value);
void fb_queue_display(const char *var, const char *prettyname);
-void fb_queue_query_save(const char *var, char *dest, unsigned dest_size);
+void fb_queue_query_save(const char *var, char *dest, uint32_t dest_size);
void fb_queue_reboot(void);
void fb_queue_command(const char *cmd, const char *msg);
-void fb_queue_download(const char *name, void *data, unsigned size);
+void fb_queue_download(const char *name, void *data, uint32_t size);
void fb_queue_notice(const char *notice);
void fb_queue_wait_for_disconnect(void);
int fb_execute_queue(usb_handle *usb);
@@ -76,8 +75,4 @@
/* Current product */
extern char cur_product[FB_RESPONSE_SZ + 1];
-#if defined(__cplusplus)
-}
-#endif
-
#endif
diff --git a/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt
index 37b1959..bb73d8a 100644
--- a/fastboot/fastboot_protocol.txt
+++ b/fastboot/fastboot_protocol.txt
@@ -41,7 +41,7 @@
d. DATA -> the requested command is ready for the data phase.
A DATA response packet will be 12 bytes long, in the form of
- DATA00000000 where the 8 digit hexidecimal number represents
+ DATA00000000 where the 8 digit hexadecimal number represents
the total data size to transfer.
3. Data phase. Depending on the command, the host or client will
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index d8f9e16..c58a505 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -6,21 +6,12 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stdarg.h>
-#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sparse/sparse.h>
#include <unistd.h>
-#ifdef USE_MINGW
-#include <fcntl.h>
-#else
-#include <sys/mman.h>
-#endif
-
-
+#include <sparse/sparse.h>
static int generate_ext4_image(int fd, long long partSize)
{
@@ -48,15 +39,13 @@
#endif
};
-const struct fs_generator* fs_get_generator(const char *fs_type)
-{
- unsigned i;
-
- for (i = 0; i < sizeof(generators) / sizeof(*generators); i++)
- if (!strcmp(generators[i].fs_type, fs_type))
+const struct fs_generator* fs_get_generator(const char* fs_type) {
+ for (size_t i = 0; i < sizeof(generators) / sizeof(*generators); i++) {
+ if (strcmp(generators[i].fs_type, fs_type) == 0) {
return generators + i;
-
- return NULL;
+ }
+ }
+ return nullptr;
}
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize)
diff --git a/fastboot/fs.h b/fastboot/fs.h
index 307772b..8444081 100644
--- a/fastboot/fs.h
+++ b/fastboot/fs.h
@@ -3,18 +3,10 @@
#include <stdint.h>
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
struct fs_generator;
const struct fs_generator* fs_get_generator(const char *fs_type);
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize);
-#if defined(__cplusplus)
-}
-#endif
-
#endif
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index 00c8a03..cbd48e8 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -26,8 +26,6 @@
* SUCH DAMAGE.
*/
-#define min(a, b) \
- ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
#define round_down(a, b) \
({ typeof(a) _a = (a); typeof(b) _b = (b); _a - (_a % _b); })
@@ -36,6 +34,8 @@
#include <string.h>
#include <errno.h>
+#include <algorithm>
+
#include <sparse/sparse.h>
#include "fastboot.h"
@@ -47,40 +47,38 @@
return ERROR;
}
-static int check_response(usb_handle *usb, unsigned int size, char *response)
-{
- unsigned char status[65];
- int r;
+static int check_response(usb_handle* usb, uint32_t size, char* response) {
+ char status[65];
- for(;;) {
- r = usb_read(usb, status, 64);
- if(r < 0) {
+ while (true) {
+ int r = usb_read(usb, status, 64);
+ if (r < 0) {
sprintf(ERROR, "status read failed (%s)", strerror(errno));
usb_close(usb);
return -1;
}
status[r] = 0;
- if(r < 4) {
+ if (r < 4) {
sprintf(ERROR, "status malformed (%d bytes)", r);
usb_close(usb);
return -1;
}
- if(!memcmp(status, "INFO", 4)) {
+ if (!memcmp(status, "INFO", 4)) {
fprintf(stderr,"(bootloader) %s\n", status + 4);
continue;
}
- if(!memcmp(status, "OKAY", 4)) {
- if(response) {
+ if (!memcmp(status, "OKAY", 4)) {
+ if (response) {
strcpy(response, (char*) status + 4);
}
return 0;
}
- if(!memcmp(status, "FAIL", 4)) {
- if(r > 4) {
+ if (!memcmp(status, "FAIL", 4)) {
+ if (r > 4) {
sprintf(ERROR, "remote: %s", status + 4);
} else {
strcpy(ERROR, "remote failure");
@@ -88,9 +86,9 @@
return -1;
}
- if(!memcmp(status, "DATA", 4) && size > 0){
- unsigned dsize = strtoul((char*) status + 4, 0, 16);
- if(dsize > size) {
+ if (!memcmp(status, "DATA", 4) && size > 0){
+ uint32_t dsize = strtol(status + 4, 0, 16);
+ if (dsize > size) {
strcpy(ERROR, "data size too large");
usb_close(usb);
return -1;
@@ -106,22 +104,19 @@
return -1;
}
-static int _command_start(usb_handle *usb, const char *cmd, unsigned size,
- char *response)
-{
- int cmdsize = strlen(cmd);
-
- if(response) {
- response[0] = 0;
- }
-
- if(cmdsize > 64) {
- sprintf(ERROR,"command too large");
+static int _command_start(usb_handle* usb, const char* cmd, uint32_t size, char* response) {
+ size_t cmdsize = strlen(cmd);
+ if (cmdsize > 64) {
+ sprintf(ERROR, "command too large");
return -1;
}
- if(usb_write(usb, cmd, cmdsize) != cmdsize) {
- sprintf(ERROR,"command write failed (%s)", strerror(errno));
+ if (response) {
+ response[0] = 0;
+ }
+
+ if (usb_write(usb, cmd, cmdsize) != static_cast<int>(cmdsize)) {
+ sprintf(ERROR, "command write failed (%s)", strerror(errno));
usb_close(usb);
return -1;
}
@@ -129,45 +124,32 @@
return check_response(usb, size, response);
}
-static int _command_data(usb_handle *usb, const void *data, unsigned size)
-{
- int r;
-
- r = usb_write(usb, data, size);
- if(r < 0) {
+static int _command_data(usb_handle* usb, const void* data, uint32_t size) {
+ int r = usb_write(usb, data, size);
+ if (r < 0) {
sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
usb_close(usb);
return -1;
}
- if(r != ((int) size)) {
+ if (r != ((int) size)) {
sprintf(ERROR, "data transfer failure (short transfer)");
usb_close(usb);
return -1;
}
-
return r;
}
-static int _command_end(usb_handle *usb)
-{
- int r;
- r = check_response(usb, 0, 0);
- if(r < 0) {
- return -1;
- }
- return 0;
+static int _command_end(usb_handle* usb) {
+ return check_response(usb, 0, 0) < 0 ? -1 : 0;
}
-static int _command_send(usb_handle *usb, const char *cmd,
- const void *data, unsigned size,
- char *response)
-{
- int r;
+static int _command_send(usb_handle* usb, const char* cmd, const void* data, uint32_t size,
+ char* response) {
if (size == 0) {
return -1;
}
- r = _command_start(usb, cmd, size, response);
+ int r = _command_start(usb, cmd, size, response);
if (r < 0) {
return -1;
}
@@ -178,42 +160,29 @@
}
r = _command_end(usb);
- if(r < 0) {
+ if (r < 0) {
return -1;
}
return size;
}
-static int _command_send_no_data(usb_handle *usb, const char *cmd,
- char *response)
-{
+static int _command_send_no_data(usb_handle* usb, const char* cmd, char* response) {
return _command_start(usb, cmd, 0, response);
}
-int fb_command(usb_handle *usb, const char *cmd)
-{
+int fb_command(usb_handle* usb, const char* cmd) {
return _command_send_no_data(usb, cmd, 0);
}
-int fb_command_response(usb_handle *usb, const char *cmd, char *response)
-{
+int fb_command_response(usb_handle* usb, const char* cmd, char* response) {
return _command_send_no_data(usb, cmd, response);
}
-int fb_download_data(usb_handle *usb, const void *data, unsigned size)
-{
+int fb_download_data(usb_handle* usb, const void* data, uint32_t size) {
char cmd[64];
- int r;
-
sprintf(cmd, "download:%08x", size);
- r = _command_send(usb, cmd, data, size, 0);
-
- if(r < 0) {
- return -1;
- } else {
- return 0;
- }
+ return _command_send(usb, cmd, data, size, 0) < 0 ? -1 : 0;
}
#define USB_BUF_SIZE 1024
@@ -228,7 +197,7 @@
const char* ptr = reinterpret_cast<const char*>(data);
if (usb_buf_len) {
- to_write = min(USB_BUF_SIZE - usb_buf_len, len);
+ to_write = std::min(USB_BUF_SIZE - usb_buf_len, len);
memcpy(usb_buf + usb_buf_len, ptr, to_write);
usb_buf_len += to_write;
@@ -270,32 +239,25 @@
return 0;
}
-static int fb_download_data_sparse_flush(usb_handle *usb)
-{
- int r;
-
+static int fb_download_data_sparse_flush(usb_handle* usb) {
if (usb_buf_len > 0) {
- r = _command_data(usb, usb_buf, usb_buf_len);
- if (r != usb_buf_len) {
+ if (_command_data(usb, usb_buf, usb_buf_len) != usb_buf_len) {
return -1;
}
usb_buf_len = 0;
}
-
return 0;
}
-int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s)
-{
- char cmd[64];
- int r;
+int fb_download_data_sparse(usb_handle* usb, struct sparse_file* s) {
int size = sparse_file_len(s, true, false);
if (size <= 0) {
return -1;
}
+ char cmd[64];
sprintf(cmd, "download:%08x", size);
- r = _command_start(usb, cmd, size, 0);
+ int r = _command_start(usb, cmd, size, 0);
if (r < 0) {
return -1;
}
diff --git a/fastboot/usb.h b/fastboot/usb.h
index c7b748e..0fda41a 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -29,16 +29,9 @@
#ifndef _USB_H_
#define _USB_H_
-#if defined(__cplusplus)
-extern "C" {
-#endif
+struct usb_handle;
-typedef struct usb_handle usb_handle;
-
-typedef struct usb_ifc_info usb_ifc_info;
-
-struct usb_ifc_info
-{
+struct usb_ifc_info {
/* from device descriptor */
unsigned short dev_vendor;
unsigned short dev_product;
@@ -68,8 +61,4 @@
int usb_write(usb_handle *h, const void *_data, int len);
int usb_wait_for_disconnect(usb_handle *h);
-#if defined(__cplusplus)
-}
-#endif
-
#endif
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index abd6eb9..45ae833 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -181,7 +181,7 @@
// Iterate over the endpoints for this interface and see if there
// are any that do bulk in/out.
- for (UInt8 endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
+ for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; endpoint++) {
UInt8 transferType;
UInt16 maxPacketSize;
UInt8 interval;
@@ -293,6 +293,13 @@
// So, we have a device, finally. Grab its vitals.
+
+ kr = (*dev)->USBDeviceOpen(dev);
+ if (kr != 0) {
+ WARN("USBDeviceOpen");
+ goto out;
+ }
+
kr = (*dev)->GetDeviceVendor(dev, &handle->info.dev_vendor);
if (kr != 0) {
ERR("GetDeviceVendor");
@@ -365,12 +372,16 @@
goto error;
}
+ out:
+
+ (*dev)->USBDeviceClose(dev);
(*dev)->Release(dev);
return 0;
error:
if (dev != NULL) {
+ (*dev)->USBDeviceClose(dev);
(*dev)->Release(dev);
}
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 00961c5..c47a585 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -154,8 +154,8 @@
INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
- &status, true, LOG_KLOG | LOG_FILE,
- true, FSCK_LOG_FILE);
+ &status, true, LOG_KLOG | LOG_FILE,
+ true, FSCK_LOG_FILE, NULL, 0);
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
@@ -172,7 +172,7 @@
ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv,
&status, true, LOG_KLOG | LOG_FILE,
- true, FSCK_LOG_FILE);
+ true, FSCK_LOG_FILE, NULL, 0);
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
ERROR("Failed trying to run %s\n", F2FS_FSCK_BIN);
@@ -828,7 +828,8 @@
/* Initialize the swap area */
mkswap_argv[1] = fstab->recs[i].blk_device;
err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv,
- &status, true, LOG_KLOG, false, NULL);
+ &status, true, LOG_KLOG, false, NULL,
+ NULL, 0);
if (err) {
ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device);
ret = -1;
diff --git a/gatekeeperd/Android.mk b/gatekeeperd/Android.mk
index 55b2d5e..3f78955 100644
--- a/gatekeeperd/Android.mk
+++ b/gatekeeperd/Android.mk
@@ -36,6 +36,7 @@
libkeystore_binder
LOCAL_STATIC_LIBRARIES := libscrypt_static
LOCAL_C_INCLUDES := external/scrypt/lib/crypto
+LOCAL_INIT_RC := gatekeeperd.rc
include $(BUILD_EXECUTABLE)
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/gatekeeperd/gatekeeperd.rc b/gatekeeperd/gatekeeperd.rc
new file mode 100644
index 0000000..3f1b92d
--- /dev/null
+++ b/gatekeeperd/gatekeeperd.rc
@@ -0,0 +1,3 @@
+service gatekeeperd /system/bin/gatekeeperd /data/misc/gatekeeper
+ class late_start
+ user system
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 7ea8250..cb77a8e 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -24,11 +24,13 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/types.h>
#include <unistd.h>
+
#include <batteryservice/BatteryService.h>
#include <cutils/klog.h>
#include <cutils/properties.h>
-#include <sys/types.h>
+#include <log/log_read.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -181,6 +183,7 @@
props.chargerWirelessOnline = false;
props.batteryStatus = BATTERY_STATUS_UNKNOWN;
props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
+ props.maxChargingCurrent = 0;
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
@@ -192,6 +195,15 @@
getIntField(mHealthdConfig->batteryCapacityPath);
props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
+ if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
+ props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000;
+
+ if (!mHealthdConfig->batteryFullChargePath.isEmpty())
+ props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
+
+ if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
+ props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
+
props.batteryTemperature = mBatteryFixedTemperature ?
mBatteryFixedTemperature :
getIntField(mHealthdConfig->batteryTemperaturePath);
@@ -235,6 +247,15 @@
KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
mChargerNames[i].string());
}
+ path.clear();
+ path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+ mChargerNames[i].string());
+ if (access(path.string(), R_OK) == 0) {
+ int maxChargingCurrent = getIntField(path);
+ if (props.maxChargingCurrent < maxChargingCurrent) {
+ props.maxChargingCurrent = maxChargingCurrent;
+ }
+ }
}
}
}
@@ -243,7 +264,7 @@
if (logthis) {
char dmesgline[256];
-
+ size_t len;
if (props.batteryPresent) {
snprintf(dmesgline, sizeof(dmesgline),
"battery l=%d v=%d t=%s%d.%d h=%d st=%d",
@@ -253,22 +274,52 @@
abs(props.batteryTemperature % 10), props.batteryHealth,
props.batteryStatus);
+ len = strlen(dmesgline);
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
- int c = getIntField(mHealthdConfig->batteryCurrentNowPath);
- char b[20];
+ len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
+ " c=%d", props.batteryCurrent);
+ }
- snprintf(b, sizeof(b), " c=%d", c / 1000);
- strlcat(dmesgline, b, sizeof(dmesgline));
+ if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+ len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
+ " fc=%d", props.batteryFullCharge);
+ }
+
+ if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+ len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
+ " cc=%d", props.batteryCycleCount);
}
} else {
snprintf(dmesgline, sizeof(dmesgline),
"battery none");
}
- KLOG_WARNING(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
- props.chargerAcOnline ? "a" : "",
- props.chargerUsbOnline ? "u" : "",
- props.chargerWirelessOnline ? "w" : "");
+ len = strlen(dmesgline);
+ snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
+ props.chargerAcOnline ? "a" : "",
+ props.chargerUsbOnline ? "u" : "",
+ props.chargerWirelessOnline ? "w" : "");
+
+ log_time realtime(CLOCK_REALTIME);
+ time_t t = realtime.tv_sec;
+ struct tm *tmp = gmtime(&t);
+ if (tmp) {
+ static const char fmt[] = " %Y-%m-%d %H:%M:%S.XXXXXXXXX UTC";
+ len = strlen(dmesgline);
+ if ((len < (sizeof(dmesgline) - sizeof(fmt) - 8)) // margin
+ && strftime(dmesgline + len, sizeof(dmesgline) - len,
+ fmt, tmp)) {
+ char *usec = strchr(dmesgline + len, 'X');
+ if (usec) {
+ len = usec - dmesgline;
+ snprintf(dmesgline + len, sizeof(dmesgline) - len,
+ "%09u", realtime.tv_nsec);
+ usec[9] = ' ';
+ }
+ }
+ }
+
+ KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
}
healthd_mode_ops->battery_update(&props);
@@ -341,9 +392,9 @@
int v;
char vs[128];
- snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d\n",
+ snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d\n",
props.chargerAcOnline, props.chargerUsbOnline,
- props.chargerWirelessOnline);
+ props.chargerWirelessOnline, props.maxChargingCurrent);
write(fd, vs, strlen(vs));
snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
props.batteryStatus, props.batteryHealth, props.batteryPresent);
@@ -370,6 +421,21 @@
snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
write(fd, vs, strlen(vs));
}
+
+ if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+ snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrent);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+ snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+ snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullCharge);
+ write(fd, vs, strlen(vs));
+ }
}
void BatteryMonitor::init(struct healthd_config *hc) {
@@ -452,6 +518,14 @@
}
}
+ if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/charge_full",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryFullChargePath = path;
+ }
+
if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/current_now",
@@ -460,6 +534,14 @@
mHealthdConfig->batteryCurrentNowPath = path;
}
+ if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/cycle_count",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->batteryCycleCountPath = path;
+ }
+
if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/current_avg",
@@ -529,6 +611,12 @@
KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
if (mHealthdConfig->batteryTechnologyPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
+ if (mHealthdConfig->batteryCurrentNowPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
+ if (mHealthdConfig->batteryFullChargePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
+ if (mHealthdConfig->batteryCycleCountPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
}
if (property_get("ro.boot.fake_battery", pval, NULL) > 0
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index b0002cc..85888c3 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -52,6 +52,8 @@
.batteryCurrentNowPath = String8(String8::kEmptyString),
.batteryCurrentAvgPath = String8(String8::kEmptyString),
.batteryChargeCounterPath = String8(String8::kEmptyString),
+ .batteryFullChargePath = String8(String8::kEmptyString),
+ .batteryCycleCountPath = String8(String8::kEmptyString),
.energyCounter = NULL,
.boot_min_cap = 0,
.screen_on = NULL,
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 84b6d76..34ea55f 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -65,6 +65,8 @@
android::String8 batteryCurrentNowPath;
android::String8 batteryCurrentAvgPath;
android::String8 batteryChargeCounterPath;
+ android::String8 batteryFullChargePath;
+ android::String8 batteryCycleCountPath;
int (*energyCounter)(int64_t *);
int boot_min_cap;
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index 6d9b3bc..9c077d6 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -71,7 +71,7 @@
#define ATRACE_TAG_LAST ATRACE_TAG_PACKAGE_MANAGER
// Reserved for initialization.
-#define ATRACE_TAG_NOT_READY (1LL<<63)
+#define ATRACE_TAG_NOT_READY (1ULL<<63)
#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
index 9402614..08ddcd2 100644
--- a/include/utils/Errors.h
+++ b/include/utils/Errors.h
@@ -23,7 +23,7 @@
namespace android {
// use this type to return error codes
-#ifdef HAVE_MS_C_RUNTIME
+#ifdef _WIN32
typedef int status_t;
#else
typedef int32_t status_t;
@@ -58,7 +58,7 @@
ALREADY_EXISTS = -EEXIST,
DEAD_OBJECT = -EPIPE,
FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),
-#if !defined(HAVE_MS_C_RUNTIME)
+#if !defined(_WIN32)
BAD_INDEX = -EOVERFLOW,
NOT_ENOUGH_DATA = -ENODATA,
WOULD_BLOCK = -EWOULDBLOCK,
diff --git a/include/utils/JenkinsHash.h b/include/utils/JenkinsHash.h
index 7da5dbd..027c10c 100644
--- a/include/utils/JenkinsHash.h
+++ b/include/utils/JenkinsHash.h
@@ -29,6 +29,9 @@
/* The Jenkins hash of a sequence of 32 bit words A, B, C is:
* Whiten(Mix(Mix(Mix(0, A), B), C)) */
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
inline uint32_t JenkinsHashMix(uint32_t hash, uint32_t data) {
hash += data;
hash += (hash << 10);
diff --git a/init/Android.mk b/init/Android.mk
index e9bab63..ff273bb 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -53,6 +53,7 @@
LOCAL_STATIC_LIBRARIES := libbase
LOCAL_MODULE := libinit
+LOCAL_SANITIZE := integer
LOCAL_CLANG := true
include $(BUILD_STATIC_LIBRARY)
@@ -102,6 +103,7 @@
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd
+LOCAL_SANITIZE := integer
LOCAL_CLANG := true
include $(BUILD_EXECUTABLE)
@@ -119,5 +121,6 @@
libbase \
LOCAL_STATIC_LIBRARIES := libinit
+LOCAL_SANITIZE := integer
LOCAL_CLANG := true
include $(BUILD_NATIVE_TEST)
diff --git a/init/action.cpp b/init/action.cpp
index 2eb809e..dd366d3 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -154,7 +154,7 @@
const static std::string prop_str("property:");
for (std::size_t i = 0; i < args.size(); ++i) {
if (i % 2) {
- if (args[i].compare("&&")) {
+ if (args[i] != "&&") {
*err = "&& is the only symbol allowed to concatenate actions";
return false;
} else {
@@ -189,24 +189,24 @@
bool Action::CheckPropertyTriggers(const std::string& name,
const std::string& value) const
{
- bool found = !name.compare("");
+ bool found = name.empty();
if (property_triggers_.empty()) {
return true;
}
for (const auto& t : property_triggers_) {
- if (!t.first.compare(name)) {
- if (t.second.compare("*") &&
- t.second.compare(value)) {
+ const auto& trigger_name = t.first;
+ const auto& trigger_value = t.second;
+ if (trigger_name == name) {
+ if (trigger_value != "*" && trigger_value != value) {
return false;
} else {
found = true;
}
} else {
- std::string prop_val = property_get(t.first.c_str());
- if (prop_val.empty() ||
- (t.second.compare("*") &&
- t.second.compare(prop_val))) {
+ std::string prop_val = property_get(trigger_name.c_str());
+ if (prop_val.empty() || (trigger_value != "*" &&
+ trigger_value != prop_val)) {
return false;
}
}
@@ -217,7 +217,7 @@
bool Action::CheckEventTrigger(const std::string& trigger) const
{
return !event_trigger_.empty() &&
- !trigger.compare(event_trigger_) &&
+ trigger == event_trigger_ &&
CheckPropertyTriggers();
}
@@ -229,10 +229,8 @@
bool Action::TriggersEqual(const class Action& other) const
{
- return property_triggers_.size() == other.property_triggers_.size() &&
- std::equal(property_triggers_.begin(), property_triggers_.end(),
- other.property_triggers_.begin()) &&
- !event_trigger_.compare(other.event_trigger_);
+ return property_triggers_ == other.property_triggers_ &&
+ event_trigger_ == other.event_trigger_;
}
std::string Action::BuildTriggersString() const
@@ -255,19 +253,53 @@
void Action::DumpState() const
{
- INFO("on ");
std::string trigger_name = BuildTriggersString();
- INFO("%s", trigger_name.c_str());
- INFO("\n");
+ INFO("on %s\n", trigger_name.c_str());
for (const auto& c : commands_) {
std::string cmd_str = c->BuildCommandString();
- INFO(" %s", cmd_str.c_str());
+ INFO(" %s\n", cmd_str.c_str());
}
INFO("\n");
}
-ActionManager::ActionManager() : cur_command_(0)
+
+class EventTrigger : public Trigger {
+public:
+ EventTrigger(const std::string& trigger) : trigger_(trigger) {
+ }
+ bool CheckTriggers(const Action* action) override {
+ return action->CheckEventTrigger(trigger_);
+ }
+private:
+ std::string trigger_;
+};
+
+class PropertyTrigger : public Trigger {
+public:
+ PropertyTrigger(const std::string& name, const std::string& value)
+ : name_(name), value_(value) {
+ }
+ bool CheckTriggers(const Action* action) override {
+ return action->CheckPropertyTrigger(name_, value_);
+ }
+private:
+ std::string name_;
+ std::string value_;
+};
+
+class BuiltinTrigger : public Trigger {
+public:
+ BuiltinTrigger(Action* action) : action_(action) {
+ }
+ bool CheckTriggers(const Action* action) override {
+ return action == action_;
+ }
+private:
+ Action* action_;
+};
+
+ActionManager::ActionManager() : current_command_(0)
{
}
@@ -278,21 +310,13 @@
void ActionManager::QueueEventTrigger(const std::string& trigger)
{
- for (const auto& a : action_list_) {
- if (a->CheckEventTrigger(trigger)) {
- action_queue_.push(a);
- }
- }
+ trigger_queue_.push(std::make_unique<EventTrigger>(trigger));
}
void ActionManager::QueuePropertyTrigger(const std::string& name,
const std::string& value)
{
- for (const auto& a : action_list_) {
- if (a->CheckPropertyTrigger(name, value)) {
- action_queue_.push(a);
- }
- }
+ trigger_queue_.push(std::make_unique<PropertyTrigger>(name, value));
}
void ActionManager::QueueAllPropertyTriggers()
@@ -312,35 +336,45 @@
act->AddCommand(func, name_vector);
- action_queue_.push(act);
+ actions_.push_back(act);
+ trigger_queue_.push(std::make_unique<BuiltinTrigger>(act));
}
void ActionManager::ExecuteOneCommand() {
- if (action_queue_.empty()) {
+ 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);
+ });
+ trigger_queue_.pop();
+ }
+
+ if (current_executing_actions_.empty()) {
return;
}
- Action* action = action_queue_.front();
+ Action* action = current_executing_actions_.back();
if (!action->NumCommands()) {
- action_queue_.pop();
+ current_executing_actions_.pop_back();
return;
}
- if (cur_command_ == 0) {
+ if (current_command_ == 0) {
std::string trigger_name = action->BuildTriggersString();
INFO("processing action %p (%s)\n", action, trigger_name.c_str());
}
- action->ExecuteOneCommand(cur_command_++);
- if (cur_command_ == action->NumCommands()) {
- cur_command_ = 0;
- action_queue_.pop();
+ action->ExecuteOneCommand(current_command_++);
+ if (current_command_ == action->NumCommands()) {
+ current_command_ = 0;
+ current_executing_actions_.pop_back();
}
}
bool ActionManager::HasMoreCommands() const
{
- return !action_queue_.empty();
+ return !current_executing_actions_.empty() || !trigger_queue_.empty();
}
Action* ActionManager::AddNewAction(const std::vector<std::string>& triggers,
@@ -357,21 +391,21 @@
}
auto old_act_it =
- std::find_if(action_list_.begin(), action_list_.end(),
+ std::find_if(actions_.begin(), actions_.end(),
[&act] (Action* a) { return act->TriggersEqual(*a); });
- if (old_act_it != action_list_.end()) {
+ if (old_act_it != actions_.end()) {
delete act;
return *old_act_it;
}
- action_list_.push_back(act);
+ actions_.push_back(act);
return act;
}
void ActionManager::DumpState() const
{
- for (const auto& a : action_list_) {
+ for (const auto& a : actions_) {
a->DumpState();
}
INFO("\n");
diff --git a/init/action.h b/init/action.h
index ae28fe1..5088c71 100644
--- a/init/action.h
+++ b/init/action.h
@@ -54,6 +54,12 @@
std::vector<Command*> commands_;
};
+class Trigger {
+public:
+ virtual ~Trigger() { }
+ virtual bool CheckTriggers(const Action* action) = 0;
+};
+
class ActionManager {
public:
static ActionManager& GetInstance();
@@ -74,9 +80,10 @@
ActionManager(ActionManager const&) = delete;
void operator=(ActionManager const&) = delete;
- std::vector<Action*> action_list_;
- std::queue<Action*> action_queue_;
- std::size_t cur_command_;
+ std::vector<Action*> actions_;
+ std::queue<std::unique_ptr<Trigger>> trigger_queue_;
+ std::vector<Action*> current_executing_actions_;
+ std::size_t current_command_;
};
#endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 470437c..7a4f7c1 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -150,13 +150,13 @@
"/system/bin/fsck.f2fs", "-f", entry->mnt_fsname,
};
android_fork_execvp_ext(ARRAY_SIZE(f2fs_argv), (char **)f2fs_argv,
- &st, true, LOG_KLOG, true, NULL);
+ &st, true, LOG_KLOG, true, NULL, NULL, 0);
} else if (!strcmp(entry->mnt_type, "ext4")) {
const char *ext4_argv[] = {
"/system/bin/e2fsck", "-f", "-y", entry->mnt_fsname,
};
android_fork_execvp_ext(ARRAY_SIZE(ext4_argv), (char **)ext4_argv,
- &st, true, LOG_KLOG, true, NULL);
+ &st, true, LOG_KLOG, true, NULL, NULL, 0);
}
}
@@ -427,6 +427,19 @@
while (1) { pause(); } // never reached
}
+void import_late()
+{
+ static const std::vector<std::string> init_directories = {
+ "/system/etc/init",
+ "/vendor/etc/init",
+ "/odm/etc/init"
+ };
+
+ for (const auto& dir : init_directories) {
+ init_parse_config(dir.c_str());
+ }
+}
+
/*
* This function might request a reboot, in which case it will
* not return.
@@ -478,6 +491,8 @@
return -1;
}
+ import_late();
+
if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
property_set("vold.decrypt", "trigger_encryption");
} else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
@@ -822,9 +837,9 @@
return -1;
}
-int do_load_all_props(const std::vector<std::string>& args) {
+int do_load_system_props(const std::vector<std::string>& args) {
if (args.size() == 1) {
- load_all_props();
+ load_system_props();
return 0;
}
return -1;
@@ -852,17 +867,30 @@
return 0;
}
+static bool is_file_crypto() {
+ std::string value = property_get("ro.crypto.type");
+ return value == "file";
+}
+
int do_installkey(const std::vector<std::string>& args)
{
if (args.size() != 2) {
return -1;
}
-
- std::string prop_value = property_get("ro.crypto.type");
- if (prop_value != "file") {
+ if (!is_file_crypto()) {
return 0;
}
-
return e4crypt_create_device_key(args[1].c_str(),
do_installkeys_ensure_dir_exists);
}
+
+int do_setusercryptopolicies(const std::vector<std::string>& args)
+{
+ if (args.size() != 2) {
+ return -1;
+ }
+ if (!is_file_crypto()) {
+ return 0;
+ }
+ return e4crypt_set_user_crypto_policies(args[1].c_str());
+}
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 3ed1d58..983eacd 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -127,7 +127,7 @@
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;
+ if (!strcmp(s, "oad_system_props")) return K_load_system_props;
break;
case 'm':
if (!strcmp(s, "kdir")) return K_mkdir;
@@ -155,6 +155,7 @@
if (!strcmp(s, "etenv")) return K_setenv;
if (!strcmp(s, "etprop")) return K_setprop;
if (!strcmp(s, "etrlimit")) return K_setrlimit;
+ if (!strcmp(s, "etusercryptopolicies")) return K_setusercryptopolicies;
if (!strcmp(s, "ocket")) return K_socket;
if (!strcmp(s, "tart")) return K_start;
if (!strcmp(s, "top")) return K_stop;
@@ -315,10 +316,14 @@
int nargs = 0;
+ //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.line = 0;
- state.ptr = strdup(data.c_str()); // TODO: fix this code!
+ state.ptr = &data_copy[0];
state.nexttoken = 0;
state.parse_line = parse_line_no_op;
diff --git a/init/keywords.h b/init/keywords.h
index 922feee..ddada58 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -24,6 +24,7 @@
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_setusercryptopolicies(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);
@@ -36,7 +37,7 @@
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_load_system_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);
@@ -68,7 +69,7 @@
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_system_props, COMMAND, 0, do_load_system_props)
KEYWORD(load_persist_props, COMMAND, 0, do_load_persist_props)
KEYWORD(loglevel, COMMAND, 1, do_loglevel)
KEYWORD(mkdir, COMMAND, 1, do_mkdir)
@@ -88,6 +89,7 @@
KEYWORD(setenv, OPTION, 2, 0)
KEYWORD(setprop, COMMAND, 2, do_setprop)
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
+ KEYWORD(setusercryptopolicies, COMMAND, 1, do_setusercryptopolicies)
KEYWORD(socket, OPTION, 0, 0)
KEYWORD(start, COMMAND, 1, do_start)
KEYWORD(stop, COMMAND, 1, do_stop)
diff --git a/init/perfboot.py b/init/perfboot.py
index b0efb11..2a17ab6 100755
--- a/init/perfboot.py
+++ b/init/perfboot.py
@@ -408,7 +408,10 @@
parser.add_argument('-t', '--tags', help='Specify the filename from which '
'event tags are read. Every line contains one event '
'tag and the last event tag is used to detect that '
- 'the device has finished booting.')
+ 'the device has finished booting unless --end-tag is '
+ 'specified.')
+ parser.add_argument('--end-tag', help='An event tag on which the script '
+ 'stops measuring the boot time.')
parser.add_argument('--apk-dir', help='Specify the directory which contains '
'APK files to be installed before measuring boot time.')
return parser.parse_args()
@@ -439,10 +442,14 @@
record_list = []
event_tags = filter_event_tags(read_event_tags(args.tags), device)
+ end_tag = args.end_tag or event_tags[-1]
+ if end_tag not in event_tags:
+ sys.exit('%s is not a valid tag.' % end_tag)
+ event_tags = event_tags[0 : event_tags.index(end_tag) + 1]
init_perf(device, args.output, record_list, event_tags)
interval_adjuster = IntervalAdjuster(args.interval, device)
event_tags_re = make_event_tags_re(event_tags)
- end_tag = event_tags[-1]
+
for i in range(args.iterations):
print 'Run #%d ' % i
record = do_iteration(
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 7194820..a37d6f6 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -555,16 +555,10 @@
close(fd);
}
-void load_all_props() {
+void load_system_props() {
load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);
load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);
load_properties_from_file(PROP_PATH_FACTORY, "ro.*");
-
- load_override_properties();
-
- /* Read persistent properties after all default values have been loaded. */
- load_persistent_properties();
-
load_recovery_id_prop();
}
diff --git a/init/property_service.h b/init/property_service.h
index 51d7404..f30577b 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -24,7 +24,7 @@
extern void property_init(void);
extern void property_load_boot_defaults(void);
extern void load_persist_props(void);
-extern void load_all_props(void);
+extern void load_system_props(void);
extern void start_property_service(void);
void get_property_workspace(int *fd, int *sz);
std::string property_get(const char* name);
diff --git a/init/service.cpp b/init/service.cpp
index 5c2a0cb..a370d25 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -20,6 +20,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
+#include <unistd.h>
#include <selinux/selinux.h>
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 128bb04..97f0ef4 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -102,6 +102,11 @@
uintptr_t relative_pc = BacktraceMap::GetRelativePc(frame->map, frame->pc);
std::string line(StringPrintf("#%02zu pc %" PRIPTR " %s", frame->num, relative_pc, map_name));
+ // Special handling for non-zero offset maps, we need to print that
+ // information.
+ if (frame->map.offset != 0) {
+ line += " (offset " + StringPrintf("0x%" PRIxPTR, frame->map.offset) + ")";
+ }
if (!frame->func_name.empty()) {
line += " (" + frame->func_name;
if (frame->func_offset) {
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 6bd7529..9ebd639 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -825,6 +825,15 @@
EXPECT_EQ("#01 pc 123456dc MapFake (ProcFake+645)",
#endif
backtrace->FormatFrameData(&frame));
+
+ // Check a non-zero map offset.
+ frame.map.offset = 0x1000;
+#if defined(__LP64__)
+ EXPECT_EQ("#01 pc 00000000123456dc MapFake (offset 0x1000) (ProcFake+645)",
+#else
+ EXPECT_EQ("#01 pc 123456dc MapFake (offset 0x1000) (ProcFake+645)",
+#endif
+ backtrace->FormatFrameData(&frame));
}
struct map_test_t {
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 6fb8c22..2728a05 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -126,6 +126,8 @@
LOCAL_CFLAGS += -DUSE_CPUSETS
endif
LOCAL_CFLAGS += -Werror -Wall -Wextra -std=gnu90
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
@@ -139,6 +141,8 @@
endif
LOCAL_CFLAGS += -Werror -Wall -Wextra
LOCAL_C_INCLUDES := $(libcutils_c_includes)
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libcutils/hashmap.c b/libcutils/hashmap.c
index 65539ea..ede3b98 100644
--- a/libcutils/hashmap.c
+++ b/libcutils/hashmap.c
@@ -77,6 +77,9 @@
/**
* Hashes the given key.
*/
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
static inline int hashKey(Hashmap* map, void* key) {
int h = map->hash(key);
@@ -152,6 +155,10 @@
free(map);
}
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
+/* FIXME: relies on signed integer overflow, which is undefined behavior */
int hashmapHash(void* key, size_t keySize) {
int h = keySize;
char* data = (char*) key;
diff --git a/libcutils/str_parms.c b/libcutils/str_parms.c
index 924289a..4f23d09 100644
--- a/libcutils/str_parms.c
+++ b/libcutils/str_parms.c
@@ -42,6 +42,9 @@
}
/* use djb hash unless we find it inadequate */
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
static int str_hash_fn(void *str)
{
uint32_t hash = 5381;
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 697db25..11e7988 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -70,10 +70,6 @@
# libhardware, but this at least gets us built.
LOCAL_SHARED_LIBRARIES += libhardware_legacy
LOCAL_CFLAGS += -DWITH_LIB_HARDWARE
-# t32cb16blend.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
-# arch-arm64/col32cb16blend.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libpixelflinger/arch-arm64/col32cb16blend.S b/libpixelflinger/arch-arm64/col32cb16blend.S
index 18a01fd..8d9c7c4 100644
--- a/libpixelflinger/arch-arm64/col32cb16blend.S
+++ b/libpixelflinger/arch-arm64/col32cb16blend.S
@@ -26,7 +26,7 @@
* SUCH DAMAGE.
*/
.text
- .align
+ .align 0
.global scanline_col32cb16blend_arm64
diff --git a/libpixelflinger/arch-arm64/t32cb16blend.S b/libpixelflinger/arch-arm64/t32cb16blend.S
index 7da8cf5..230f47b 100644
--- a/libpixelflinger/arch-arm64/t32cb16blend.S
+++ b/libpixelflinger/arch-arm64/t32cb16blend.S
@@ -26,7 +26,7 @@
* SUCH DAMAGE.
*/
.text
- .align
+ .align 0
.global scanline_t32cb16blend_arm64
diff --git a/libpixelflinger/t32cb16blend.S b/libpixelflinger/t32cb16blend.S
index caf9eb7..1d40ad4 100644
--- a/libpixelflinger/t32cb16blend.S
+++ b/libpixelflinger/t32cb16blend.S
@@ -17,6 +17,7 @@
.text
+ .syntax unified
.align
.global scanline_t32cb16blend_arm
@@ -146,7 +147,7 @@
tst r0, #0x3
beq aligned
subs r2, r2, #1
- ldmlofd sp!, {r4-r7, lr} // return
+ ldmfdlo sp!, {r4-r7, lr} // return
bxlo lr
last:
@@ -197,6 +198,6 @@
mov r4, r5
9: adds r2, r2, #1
- ldmlofd sp!, {r4-r7, lr} // return
+ ldmfdlo sp!, {r4-r7, lr} // return
bxlo lr
b last
diff --git a/libpixelflinger/tests/arch-arm64/assembler/Android.mk b/libpixelflinger/tests/arch-arm64/assembler/Android.mk
index 448d298..bd0f24b 100644
--- a/libpixelflinger/tests/arch-arm64/assembler/Android.mk
+++ b/libpixelflinger/tests/arch-arm64/assembler/Android.mk
@@ -5,9 +5,6 @@
arm64_assembler_test.cpp\
asm_test_jacket.S
-# asm_test_jacket.S does not compile with Clang.
-LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
libpixelflinger
diff --git a/libpixelflinger/tests/arch-arm64/assembler/asm_test_jacket.S b/libpixelflinger/tests/arch-arm64/assembler/asm_test_jacket.S
index a1392c2..f44859f 100644
--- a/libpixelflinger/tests/arch-arm64/assembler/asm_test_jacket.S
+++ b/libpixelflinger/tests/arch-arm64/assembler/asm_test_jacket.S
@@ -27,7 +27,7 @@
*/
.text
- .align
+ .align 0
.global asm_test_jacket
diff --git a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk
index 5d69203..3368eb0 100644
--- a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk
+++ b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk
@@ -5,8 +5,6 @@
col32cb16blend_test.c \
../../../arch-arm64/col32cb16blend.S
-LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
-
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES :=
diff --git a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk
index 2c1379b..8e5ec5e 100644
--- a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk
+++ b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk
@@ -5,8 +5,6 @@
t32cb16blend_test.c \
../../../arch-arm64/t32cb16blend.S
-LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
-
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES :=
diff --git a/libsparse/backed_block.c b/libsparse/backed_block.c
index 3e72b57..794cd6b 100644
--- a/libsparse/backed_block.c
+++ b/libsparse/backed_block.c
@@ -221,7 +221,8 @@
}
break;
case BACKED_BLOCK_FILE:
- if (a->file.filename != b->file.filename ||
+ /* Already make sure b->type is BACKED_BLOCK_FILE */
+ if (strcmp(a->file.filename, b->file.filename) ||
a->file.offset + a->len != b->file.offset) {
return -EINVAL;
}
@@ -279,7 +280,10 @@
}
merge_bb(bbl, new_bb, new_bb->next);
- merge_bb(bbl, bb, new_bb);
+ if (!merge_bb(bbl, bb, new_bb)) {
+ /* new_bb destroyed, point to retained as last_used */
+ bbl->last_used = bb;
+ }
return 0;
}
diff --git a/libutils/Android.mk b/libutils/Android.mk
index 677d1e7..a299962 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -92,6 +92,8 @@
libdl
LOCAL_MODULE := libutils
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
include $(BUILD_STATIC_LIBRARY)
# For the device, shared
@@ -106,8 +108,26 @@
liblog
LOCAL_CFLAGS := -Werror
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
include $(BUILD_SHARED_LIBRARY)
+# Include subdirectory makefiles
+# ============================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := SharedBufferTest
+LOCAL_STATIC_LIBRARIES := libutils libcutils
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := SharedBufferTest.cpp
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := SharedBufferTest
+LOCAL_STATIC_LIBRARIES := libutils libcutils
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := SharedBufferTest.cpp
+include $(BUILD_HOST_NATIVE_TEST)
# Build the tests in the tests/ subdirectory.
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/libutils/JenkinsHash.cpp b/libutils/JenkinsHash.cpp
index 52c9bb7..ff5d252 100644
--- a/libutils/JenkinsHash.cpp
+++ b/libutils/JenkinsHash.cpp
@@ -19,10 +19,14 @@
* should still be quite good.
**/
+#include <stdlib.h>
#include <utils/JenkinsHash.h>
namespace android {
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
hash_t JenkinsHashWhiten(uint32_t hash) {
hash += (hash << 3);
hash ^= (hash >> 11);
@@ -31,6 +35,9 @@
}
uint32_t JenkinsHashMixBytes(uint32_t hash, const uint8_t* bytes, size_t size) {
+ if (size > UINT32_MAX) {
+ abort();
+ }
hash = JenkinsHashMix(hash, (uint32_t)size);
size_t i;
for (i = 0; i < (size & -4); i += 4) {
@@ -47,6 +54,9 @@
}
uint32_t JenkinsHashMixShorts(uint32_t hash, const uint16_t* shorts, size_t size) {
+ if (size > UINT32_MAX) {
+ abort();
+ }
hash = JenkinsHashMix(hash, (uint32_t)size);
size_t i;
for (i = 0; i < (size & -2); i += 2) {
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 3555fb7..947551a 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -14,9 +14,12 @@
* limitations under the License.
*/
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <log/log.h>
#include <utils/SharedBuffer.h>
#include <utils/Atomic.h>
@@ -26,6 +29,11 @@
SharedBuffer* SharedBuffer::alloc(size_t size)
{
+ // Don't overflow if the combined size of the buffer / header is larger than
+ // size_max.
+ LOG_ALWAYS_FATAL_IF((size >= (SIZE_MAX - sizeof(SharedBuffer))),
+ "Invalid buffer size %zu", size);
+
SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
if (sb) {
sb->mRefs = 1;
@@ -52,7 +60,7 @@
memcpy(sb->data(), data(), size());
release();
}
- return sb;
+ return sb;
}
SharedBuffer* SharedBuffer::editResize(size_t newSize) const
@@ -60,6 +68,11 @@
if (onlyOwner()) {
SharedBuffer* buf = const_cast<SharedBuffer*>(this);
if (buf->mSize == newSize) return buf;
+ // Don't overflow if the combined size of the new buffer / header is larger than
+ // size_max.
+ LOG_ALWAYS_FATAL_IF((newSize >= (SIZE_MAX - sizeof(SharedBuffer))),
+ "Invalid buffer size %zu", newSize);
+
buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
if (buf != NULL) {
buf->mSize = newSize;
diff --git a/libutils/SharedBufferTest.cpp b/libutils/SharedBufferTest.cpp
new file mode 100644
index 0000000..d88fbf3
--- /dev/null
+++ b/libutils/SharedBufferTest.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#define __STDC_LIMIT_MACROS
+
+#include <utils/SharedBuffer.h>
+
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <stdint.h>
+
+TEST(SharedBufferTest, TestAlloc) {
+ EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX), "");
+ EXPECT_DEATH(android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+
+ // Make sure we don't die here.
+ // Check that null is returned, as we are asking for the whole address space.
+ android::SharedBuffer* buf =
+ android::SharedBuffer::alloc(SIZE_MAX - sizeof(android::SharedBuffer) - 1);
+ ASSERT_TRUE(NULL == buf);
+
+ buf = android::SharedBuffer::alloc(0);
+ ASSERT_FALSE(NULL == buf);
+ ASSERT_EQ(0U, buf->size());
+ buf->release();
+}
+
+TEST(SharedBufferTest, TestEditResize) {
+ android::SharedBuffer* buf = android::SharedBuffer::alloc(10);
+ EXPECT_DEATH(buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer)), "");
+ buf = android::SharedBuffer::alloc(10);
+ EXPECT_DEATH(buf->editResize(SIZE_MAX), "");
+
+ buf = android::SharedBuffer::alloc(10);
+ // Make sure we don't die here.
+ // Check that null is returned, as we are asking for the whole address space.
+ buf = buf->editResize(SIZE_MAX - sizeof(android::SharedBuffer) - 1);
+ ASSERT_TRUE(NULL == buf);
+
+ buf = android::SharedBuffer::alloc(10);
+ buf = buf->editResize(0);
+ ASSERT_EQ(0U, buf->size());
+ buf->release();
+}
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 28be60f..2d06023 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
#include <utils/String8.h>
#include <utils/Compat.h>
@@ -79,6 +82,9 @@
static char* allocFromUTF8(const char* in, size_t len)
{
if (len > 0) {
+ if (len == SIZE_MAX) {
+ return NULL;
+ }
SharedBuffer* buf = SharedBuffer::alloc(len+1);
ALOG_ASSERT(buf, "Unable to allocate shared buffer");
if (buf) {
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index 30ca663..bdb54b1 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -551,6 +551,10 @@
ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
{
+ if (order) *order = 0;
+ if (isEmpty()) {
+ return NAME_NOT_FOUND;
+ }
// binary search
ssize_t err = NAME_NOT_FOUND;
ssize_t l = 0;
diff --git a/libutils/tests/BitSet_test.cpp b/libutils/tests/BitSet_test.cpp
index 38b668a..59d913e 100644
--- a/libutils/tests/BitSet_test.cpp
+++ b/libutils/tests/BitSet_test.cpp
@@ -138,11 +138,11 @@
TEST_F(BitSet32Test, GetIndexOfBit) {
b1.markBit(1);
b1.markBit(4);
- EXPECT_EQ(b1.getIndexOfBit(1), 0);
- EXPECT_EQ(b1.getIndexOfBit(4), 1);
+ EXPECT_EQ(0U, b1.getIndexOfBit(1));
+ EXPECT_EQ(1U, b1.getIndexOfBit(4));
b1.markFirstUnmarkedBit();
- EXPECT_EQ(b1.getIndexOfBit(1), 1);
- EXPECT_EQ(b1.getIndexOfBit(4), 2);
+ EXPECT_EQ(1U, b1.getIndexOfBit(1));
+ EXPECT_EQ(2U, b1.getIndexOfBit(4));
}
class BitSet64Test : public testing::Test {
@@ -260,11 +260,11 @@
TEST_F(BitSet64Test, GetIndexOfBit) {
b1.markBit(10);
b1.markBit(40);
- EXPECT_EQ(b1.getIndexOfBit(10), 0);
- EXPECT_EQ(b1.getIndexOfBit(40), 1);
+ EXPECT_EQ(0U, b1.getIndexOfBit(10));
+ EXPECT_EQ(1U, b1.getIndexOfBit(40));
b1.markFirstUnmarkedBit();
- EXPECT_EQ(b1.getIndexOfBit(10), 1);
- EXPECT_EQ(b1.getIndexOfBit(40), 2);
+ EXPECT_EQ(1U, b1.getIndexOfBit(10));
+ EXPECT_EQ(2U, b1.getIndexOfBit(40));
}
} // namespace android
diff --git a/libutils/tests/LruCache_test.cpp b/libutils/tests/LruCache_test.cpp
index 6534211..6155def 100644
--- a/libutils/tests/LruCache_test.cpp
+++ b/libutils/tests/LruCache_test.cpp
@@ -220,7 +220,7 @@
cache.put(ComplexKey(0), ComplexValue(0));
cache.put(ComplexKey(1), ComplexValue(1));
- EXPECT_EQ(2, cache.size());
+ EXPECT_EQ(2U, cache.size());
assertInstanceCount(2, 3); // the null value counts as an instance
}
@@ -229,7 +229,7 @@
cache.put(ComplexKey(0), ComplexValue(0));
cache.put(ComplexKey(1), ComplexValue(1));
- EXPECT_EQ(2, cache.size());
+ EXPECT_EQ(2U, cache.size());
assertInstanceCount(2, 3);
cache.clear();
assertInstanceCount(0, 1);
@@ -241,7 +241,7 @@
cache.put(ComplexKey(0), ComplexValue(0));
cache.put(ComplexKey(1), ComplexValue(1));
- EXPECT_EQ(2, cache.size());
+ EXPECT_EQ(2U, cache.size());
assertInstanceCount(2, 3);
cache.removeOldest();
cache.clear();
@@ -255,13 +255,13 @@
cache.put(ComplexKey(0), ComplexValue(0));
cache.put(ComplexKey(1), ComplexValue(1));
- EXPECT_EQ(2, cache.size());
+ EXPECT_EQ(2U, cache.size());
assertInstanceCount(2, 3);
cache.clear();
assertInstanceCount(0, 1);
cache.put(ComplexKey(0), ComplexValue(0));
cache.put(ComplexKey(1), ComplexValue(1));
- EXPECT_EQ(2, cache.size());
+ EXPECT_EQ(2U, cache.size());
assertInstanceCount(2, 3);
}
@@ -273,7 +273,7 @@
cache.put(1, "one");
cache.put(2, "two");
cache.put(3, "three");
- EXPECT_EQ(3, cache.size());
+ EXPECT_EQ(3U, cache.size());
cache.removeOldest();
EXPECT_EQ(1, callback.callbackCount);
EXPECT_EQ(1, callback.lastKey);
@@ -288,7 +288,7 @@
cache.put(1, "one");
cache.put(2, "two");
cache.put(3, "three");
- EXPECT_EQ(3, cache.size());
+ EXPECT_EQ(3U, cache.size());
cache.clear();
EXPECT_EQ(3, callback.callbackCount);
}
diff --git a/libutils/tests/Vector_test.cpp b/libutils/tests/Vector_test.cpp
index d29c054..0ba7161 100644
--- a/libutils/tests/Vector_test.cpp
+++ b/libutils/tests/Vector_test.cpp
@@ -45,26 +45,26 @@
vector.add(2);
vector.add(3);
- EXPECT_EQ(vector.size(), 3);
+ EXPECT_EQ(3U, vector.size());
// copy the vector
other = vector;
- EXPECT_EQ(other.size(), 3);
+ EXPECT_EQ(3U, other.size());
// add an element to the first vector
vector.add(4);
// make sure the sizes are correct
- EXPECT_EQ(vector.size(), 4);
- EXPECT_EQ(other.size(), 3);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(3U, other.size());
// add an element to the copy
other.add(5);
// make sure the sizes are correct
- EXPECT_EQ(vector.size(), 4);
- EXPECT_EQ(other.size(), 4);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, other.size());
// make sure the content of both vectors are correct
EXPECT_EQ(vector[3], 4);
diff --git a/lmkd/Android.mk b/lmkd/Android.mk
index 39081d6..8c88661 100644
--- a/lmkd/Android.mk
+++ b/lmkd/Android.mk
@@ -7,4 +7,6 @@
LOCAL_MODULE := lmkd
+LOCAL_INIT_RC := lmkd.rc
+
include $(BUILD_EXECUTABLE)
diff --git a/lmkd/lmkd.rc b/lmkd/lmkd.rc
new file mode 100644
index 0000000..83c5ff0
--- /dev/null
+++ b/lmkd/lmkd.rc
@@ -0,0 +1,4 @@
+service lmkd /system/bin/lmkd
+ class core
+ critical
+ socket lmkd seqpacket 0660 system system
diff --git a/logcat/Android.mk b/logcat/Android.mk
index 7115f9b..844ab8b 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -11,6 +11,8 @@
LOCAL_CFLAGS := -Werror
+LOCAL_INIT_RC := logcatd.rc
+
include $(BUILD_EXECUTABLE)
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
new file mode 100644
index 0000000..0bc581e
--- /dev/null
+++ b/logcat/logcatd.rc
@@ -0,0 +1,13 @@
+on property:persist.logd.logpersistd=logcatd
+ # all exec/services are called with umask(077), so no gain beyond 0700
+ mkdir /data/misc/logd 0700 logd log
+ # logd for write to /data/misc/logd, log group for read from pstore (-L)
+ exec - logd log -- /system/bin/logcat -L -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
+ start logcatd
+
+service logcatd /system/bin/logcat -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
+ class late_start
+ disabled
+ # logd for write to /data/misc/logd, log group for read from log daemon
+ user logd
+ group log
diff --git a/logd/Android.mk b/logd/Android.mk
index 615d030..01c51c7 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -4,6 +4,8 @@
LOCAL_MODULE:= logd
+LOCAL_INIT_RC := logd.rc
+
LOCAL_SRC_FILES := \
main.cpp \
LogCommand.cpp \
@@ -25,7 +27,7 @@
libsysutils \
liblog \
libcutils \
- libutils
+ libbase
# This is what we want to do:
# event_logtags = $(shell \
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index 489bea6..031c740 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -25,6 +25,9 @@
#include <sys/socket.h>
#include <sys/types.h>
+#include <string>
+
+#include <base/stringprintf.h>
#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
#include <sysutils/SocketClient.h>
@@ -189,22 +192,13 @@
mBuf(*buf) {
}
-static void package_string(char **strp) {
- const char *a = *strp;
- if (!a) {
- a = "";
- }
-
+static std::string package_string(const std::string &str) {
// Calculate total buffer size prefix, count is the string length w/o nul
char fmt[32];
- for(size_t l = strlen(a), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) {
+ for(size_t l = str.length(), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) {
snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
}
-
- char *b = *strp;
- *strp = NULL;
- asprintf(strp, fmt, a);
- free(b);
+ return android::base::StringPrintf(fmt, str.c_str());
}
int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
@@ -228,16 +222,7 @@
}
}
- char *buf = NULL;
-
- mBuf.formatStatistics(&buf, uid, logMask);
- if (!buf) {
- cli->sendMsg("Failed");
- } else {
- package_string(&buf);
- cli->sendMsg(buf);
- free(buf);
- }
+ cli->sendMsg(package_string(mBuf.formatStatistics(uid, logMask)).c_str());
return 0;
}
@@ -249,15 +234,7 @@
int CommandListener::GetPruneListCmd::runCommand(SocketClient *cli,
int /*argc*/, char ** /*argv*/) {
setname();
- char *buf = NULL;
- mBuf.formatPrune(&buf);
- if (!buf) {
- cli->sendMsg("Failed");
- } else {
- package_string(&buf);
- cli->sendMsg(buf);
- free(buf);
- }
+ cli->sendMsg(package_string(mBuf.formatPrune()).c_str());
return 0;
}
@@ -274,20 +251,15 @@
return 0;
}
- char *cp = NULL;
+ std::string str;
for (int i = 1; i < argc; ++i) {
- char *p = cp;
- if (p) {
- cp = NULL;
- asprintf(&cp, "%s %s", p, argv[i]);
- free(p);
- } else {
- asprintf(&cp, "%s", argv[i]);
+ if (str.length()) {
+ str += " ";
}
+ str += argv[i];
}
- int ret = mBuf.initPrune(cp);
- free(cp);
+ int ret = mBuf.initPrune(str.c_str());
if (ret) {
cli->sendMsg("Invalid");
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index d584925..823a842 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -72,7 +72,7 @@
return;
}
entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart);
- times.push_back(entry);
+ times.push_front(entry);
}
client->incRef();
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 0f5071b..c609870 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -217,19 +217,22 @@
return len;
}
-// If we're using more than 256K of memory for log entries, prune
-// at least 10% of the log entries.
+// Prune at most 10% of the log entries or 256, whichever is less.
//
// mLogElementsLock must be held when this function is called.
void LogBuffer::maybePrune(log_id_t id) {
size_t sizes = stats.sizes(id);
- if (sizes > log_buffer_size(id)) {
- size_t sizeOver90Percent = sizes - ((log_buffer_size(id) * 9) / 10);
+ unsigned long maxSize = log_buffer_size(id);
+ if (sizes > maxSize) {
+ size_t sizeOver = sizes - ((maxSize * 9) / 10);
size_t elements = stats.elements(id);
- unsigned long pruneRows = elements * sizeOver90Percent / sizes;
- elements /= 10;
- if (pruneRows <= elements) {
- pruneRows = elements;
+ size_t minElements = elements / 10;
+ unsigned long pruneRows = elements * sizeOver / sizes;
+ if (pruneRows <= minElements) {
+ pruneRows = minElements;
+ }
+ if (pruneRows > 256) {
+ pruneRows = 256;
}
prune(id, pruneRows);
}
@@ -237,7 +240,12 @@
LogBufferElementCollection::iterator LogBuffer::erase(LogBufferElementCollection::iterator it) {
LogBufferElement *e = *it;
+ log_id_t id = e->getLogId();
+ LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(e->getUid());
+ if ((f != mLastWorstUid[id].end()) && (it == f->second)) {
+ mLastWorstUid[id].erase(f);
+ }
it = mLogElements.erase(it);
stats.subtract(e);
delete e;
@@ -396,8 +404,17 @@
bool kick = false;
bool leading = true;
+ it = mLogElements.begin();
+ if (worst != (uid_t) -1) {
+ LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(worst);
+ if ((f != mLastWorstUid[id].end())
+ && (f->second != mLogElements.end())) {
+ leading = false;
+ it = f->second;
+ }
+ }
LogBufferElementLast last;
- for(it = mLogElements.begin(); it != mLogElements.end();) {
+ while (it != mLogElements.end()) {
LogBufferElement *e = *it;
if (oldest && (oldest->mStart <= e->getSequence())) {
@@ -447,8 +464,14 @@
continue;
}
+ // unmerged drop message
if (dropped) {
last.add(e);
+ if ((e->getUid() == worst)
+ || (mLastWorstUid[id].find(e->getUid())
+ == mLastWorstUid[id].end())) {
+ mLastWorstUid[id][e->getUid()] = it;
+ }
++it;
continue;
}
@@ -493,6 +516,7 @@
delete e;
} else {
last.add(e);
+ mLastWorstUid[id][e->getUid()] = it;
++it;
}
}
@@ -670,10 +694,12 @@
return max;
}
-void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
+std::string LogBuffer::formatStatistics(uid_t uid, unsigned int logMask) {
pthread_mutex_lock(&mLogElementsLock);
- stats.format(strp, uid, logMask);
+ std::string ret = stats.format(uid, logMask);
pthread_mutex_unlock(&mLogElementsLock);
+
+ return ret;
}
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index a13fded..fcb05f5 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -19,9 +19,11 @@
#include <sys/types.h>
+#include <list>
+#include <string>
+
#include <log/log.h>
#include <sysutils/SocketClient.h>
-#include <utils/List.h>
#include <private/android_filesystem_config.h>
@@ -30,7 +32,7 @@
#include "LogStatistics.h"
#include "LogWhiteBlackList.h"
-typedef android::List<LogBufferElement *> LogBufferElementCollection;
+typedef std::list<LogBufferElement *> LogBufferElementCollection;
class LogBuffer {
LogBufferElementCollection mLogElements;
@@ -39,6 +41,11 @@
LogStatistics stats;
PruneList mPrune;
+ // watermark of any worst/chatty uid processing
+ typedef std::unordered_map<uid_t,
+ LogBufferElementCollection::iterator>
+ LogBufferIteratorMap;
+ LogBufferIteratorMap mLastWorstUid[LOG_ID_MAX];
unsigned long mMaxSize[LOG_ID_MAX];
@@ -61,15 +68,14 @@
int setSize(log_id_t id, unsigned long size);
unsigned long getSizeUsed(log_id_t id);
// *strp uses malloc, use free to release.
- void formatStatistics(char **strp, uid_t uid, unsigned int logMask);
+ std::string formatStatistics(uid_t uid, unsigned int logMask);
void enableStatistics() {
stats.enableStatistics();
}
- int initPrune(char *cp) { return mPrune.init(cp); }
- // *strp uses malloc, use free to release.
- void formatPrune(char **strp) { mPrune.format(strp); }
+ int initPrune(const char *cp) { return mPrune.init(cp); }
+ std::string formatPrune() { return mPrune.format(); }
// helper must be protected directly or implicitly by lock()/unlock()
char *pidToName(pid_t pid) { return stats.pidToName(pid); }
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index eff26f5..1e6f55f 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -254,6 +254,7 @@
if ((cp = now.strptime(*buf, "[ %s.%q]"))) {
static const char suspend[] = "PM: suspend entry ";
static const char resume[] = "PM: suspend exit ";
+ static const char healthd[] = "healthd: battery ";
static const char suspended[] = "Suspended for ";
if (isspace(*cp)) {
@@ -263,6 +264,15 @@
calculateCorrection(now, cp + sizeof(suspend) - 1);
} else if (!strncmp(cp, resume, sizeof(resume) - 1)) {
calculateCorrection(now, cp + sizeof(resume) - 1);
+ } else if (!strncmp(cp, healthd, sizeof(healthd) - 1)) {
+ // look for " 2???-??-?? ??:??:??.????????? ???"
+ const char *tp;
+ for (tp = cp + sizeof(healthd) - 1; *tp && (*tp != '\n'); ++tp) {
+ if ((tp[0] == ' ') && (tp[1] == '2') && (tp[5] == '-')) {
+ calculateCorrection(now, tp + 1);
+ break;
+ }
+ }
} else if (!strncmp(cp, suspended, sizeof(suspended) - 1)) {
log_time real;
char *endp;
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 48c2fe6..61fd559 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -20,9 +20,9 @@
#include <string.h>
#include <unistd.h>
+#include <base/stringprintf.h>
#include <log/logger.h>
#include <private/android_filesystem_config.h>
-#include <utils/String8.h>
#include "LogStatistics.h"
@@ -183,8 +183,10 @@
return name;
}
-static void format_line(android::String8 &output,
- android::String8 &name, android::String8 &size, android::String8 &pruned) {
+static std::string format_line(
+ const std::string &name,
+ const std::string &size,
+ const std::string &pruned) {
static const size_t pruned_len = 6;
static const size_t total_len = 70 + pruned_len;
@@ -193,26 +195,21 @@
total_len - name.length() - drop_len - 1);
if (pruned.length()) {
- output.appendFormat("%s%*s%*s\n", name.string(),
- (int)size_len, size.string(),
- (int)drop_len, pruned.string());
+ return android::base::StringPrintf("%s%*s%*s\n", name.c_str(),
+ (int)size_len, size.c_str(),
+ (int)drop_len, pruned.c_str());
} else {
- output.appendFormat("%s%*s\n", name.string(),
- (int)size_len, size.string());
+ return android::base::StringPrintf("%s%*s\n", name.c_str(),
+ (int)size_len, size.c_str());
}
}
-void LogStatistics::format(char **buf, uid_t uid, unsigned int logMask) {
+std::string LogStatistics::format(uid_t uid, unsigned int logMask) {
static const unsigned short spaces_total = 19;
- if (*buf) {
- free(*buf);
- *buf = NULL;
- }
-
// Report on total logging, current and for all time
- android::String8 output("size/num");
+ std::string output = "size/num";
size_t oldLength;
short spaces = 1;
@@ -224,12 +221,13 @@
if (spaces < 0) {
spaces = 0;
}
- output.appendFormat("%*s%s", spaces, "", android_log_id_to_name(id));
+ output += android::base::StringPrintf("%*s%s", spaces, "",
+ android_log_id_to_name(id));
spaces += spaces_total + oldLength - output.length();
}
spaces = 4;
- output.appendFormat("\nTotal");
+ output += android::base::StringPrintf("\nTotal");
log_id_for_each(id) {
if (!(logMask & (1 << id))) {
@@ -239,13 +237,14 @@
if (spaces < 0) {
spaces = 0;
}
- output.appendFormat("%*s%zu/%zu", spaces, "",
- sizesTotal(id), elementsTotal(id));
+ output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
+ sizesTotal(id),
+ elementsTotal(id));
spaces += spaces_total + oldLength - output.length();
}
spaces = 6;
- output.appendFormat("\nNow");
+ output += android::base::StringPrintf("\nNow");
log_id_for_each(id) {
if (!(logMask & (1 << id))) {
@@ -258,7 +257,8 @@
if (spaces < 0) {
spaces = 0;
}
- output.appendFormat("%*s%zu/%zu", spaces, "", sizes(id), els);
+ output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
+ sizes(id), els);
spaces -= output.length() - oldLength;
}
spaces += spaces_total;
@@ -284,53 +284,54 @@
}
if (!headerPrinted) {
- output.appendFormat("\n\n");
- android::String8 name("");
+ output += android::base::StringPrintf("\n\n");
+ std::string name;
if (uid == AID_ROOT) {
- name.appendFormat(
+ name = android::base::StringPrintf(
"Chattiest UIDs in %s log buffer:",
android_log_id_to_name(id));
} else {
- name.appendFormat(
+ name = android::base::StringPrintf(
"Logging for your UID in %s log buffer:",
android_log_id_to_name(id));
}
- android::String8 size("Size");
- android::String8 pruned("Pruned");
+ std::string size = "Size";
+ std::string pruned = "Pruned";
if (!worstUidEnabledForLogid(id)) {
- pruned.setTo("");
+ pruned = "";
}
- format_line(output, name, size, pruned);
+ output += format_line(name, size, pruned);
- name.setTo("UID PACKAGE");
- size.setTo("BYTES");
- pruned.setTo("LINES");
+ name = "UID PACKAGE";
+ size = "BYTES";
+ pruned = "LINES";
if (!worstUidEnabledForLogid(id)) {
- pruned.setTo("");
+ pruned = "";
}
- format_line(output, name, size, pruned);
+ output += format_line(name, size, pruned);
headerPrinted = true;
}
- android::String8 name("");
- name.appendFormat("%u", u);
+ std::string name = android::base::StringPrintf("%u", u);
char *n = uidToName(u);
if (n) {
- name.appendFormat("%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", n);
+ name += android::base::StringPrintf(
+ "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
+ "", n);
free(n);
}
- android::String8 size("");
- size.appendFormat("%zu", entry->getSizes());
+ std::string size = android::base::StringPrintf("%zu",
+ entry->getSizes());
- android::String8 pruned("");
+ std::string pruned = "";
size_t dropped = entry->getDropped();
if (dropped) {
- pruned.appendFormat("%zu", dropped);
+ pruned = android::base::StringPrintf("%zu", dropped);
}
- format_line(output, name, size, pruned);
+ output += format_line(name, size, pruned);
}
}
@@ -347,48 +348,52 @@
}
if (!headerPrinted) {
- output.appendFormat("\n\n");
- android::String8 name("");
+ output += android::base::StringPrintf("\n\n");
+ std::string name;
if (uid == AID_ROOT) {
- name.appendFormat("Chattiest PIDs:");
+ name = android::base::StringPrintf("Chattiest PIDs:");
} else {
- name.appendFormat("Logging for this PID:");
+ name = android::base::StringPrintf("Logging for this PID:");
}
- android::String8 size("Size");
- android::String8 pruned("Pruned");
- format_line(output, name, size, pruned);
+ std::string size = "Size";
+ std::string pruned = "Pruned";
+ output += format_line(name, size, pruned);
- name.setTo(" PID/UID COMMAND LINE");
- size.setTo("BYTES");
- pruned.setTo("LINES");
- format_line(output, name, size, pruned);
+ name = " PID/UID COMMAND LINE";
+ size = "BYTES";
+ pruned = "LINES";
+ output += format_line(name, size, pruned);
headerPrinted = true;
}
- android::String8 name("");
- name.appendFormat("%5u/%u", entry->getKey(), u);
+ std::string name = android::base::StringPrintf("%5u/%u",
+ entry->getKey(), u);
const char *n = entry->getName();
if (n) {
- name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n);
+ name += android::base::StringPrintf(
+ "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+ "", n);
} else {
char *un = uidToName(u);
if (un) {
- name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un);
+ name += android::base::StringPrintf(
+ "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+ "", un);
free(un);
}
}
- android::String8 size("");
- size.appendFormat("%zu", entry->getSizes());
+ std::string size = android::base::StringPrintf("%zu",
+ entry->getSizes());
- android::String8 pruned("");
+ std::string pruned = "";
size_t dropped = entry->getDropped();
if (dropped) {
- pruned.appendFormat("%zu", dropped);
+ pruned = android::base::StringPrintf("%zu", dropped);
}
- format_line(output, name, size, pruned);
+ output += format_line(name, size, pruned);
}
}
@@ -406,46 +411,50 @@
}
if (!headerPrinted) { // Only print header if we have table to print
- output.appendFormat("\n\n");
- android::String8 name("Chattiest TIDs:");
- android::String8 size("Size");
- android::String8 pruned("Pruned");
- format_line(output, name, size, pruned);
+ output += android::base::StringPrintf("\n\n");
+ std::string name = "Chattiest TIDs:";
+ std::string size = "Size";
+ std::string pruned = "Pruned";
+ output += format_line(name, size, pruned);
- name.setTo(" TID/UID COMM");
- size.setTo("BYTES");
- pruned.setTo("LINES");
- format_line(output, name, size, pruned);
+ name = " TID/UID COMM";
+ size = "BYTES";
+ pruned = "LINES";
+ output += format_line(name, size, pruned);
headerPrinted = true;
}
- android::String8 name("");
- name.appendFormat("%5u/%u", entry->getKey(), u);
+ std::string name = android::base::StringPrintf("%5u/%u",
+ entry->getKey(), u);
const char *n = entry->getName();
if (n) {
- name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n);
+ name += android::base::StringPrintf(
+ "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+ "", n);
} else {
// if we do not have a PID name, lets punt to try UID name?
char *un = uidToName(u);
if (un) {
- name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un);
+ name += android::base::StringPrintf(
+ "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+ "", un);
free(un);
}
// We tried, better to not have a name at all, we still
// have TID/UID by number to report in any case.
}
- android::String8 size("");
- size.appendFormat("%zu", entry->getSizes());
+ std::string size = android::base::StringPrintf("%zu",
+ entry->getSizes());
- android::String8 pruned("");
+ std::string pruned = "";
size_t dropped = entry->getDropped();
if (dropped) {
- pruned.appendFormat("%zu", dropped);
+ pruned = android::base::StringPrintf("%zu", dropped);
}
- format_line(output, name, size, pruned);
+ output += format_line(name, size, pruned);
}
}
@@ -461,40 +470,44 @@
continue;
}
- android::String8 pruned("");
+ std::string pruned = "";
if (!headerPrinted) {
- output.appendFormat("\n\n");
- android::String8 name("Chattiest events log buffer TAGs:");
- android::String8 size("Size");
- format_line(output, name, size, pruned);
+ output += android::base::StringPrintf("\n\n");
+ std::string name = "Chattiest events log buffer TAGs:";
+ std::string size = "Size";
+ output += format_line(name, size, pruned);
- name.setTo(" TAG/UID TAGNAME");
- size.setTo("BYTES");
- format_line(output, name, size, pruned);
+ name = " TAG/UID TAGNAME";
+ size = "BYTES";
+ output += format_line(name, size, pruned);
headerPrinted = true;
}
- android::String8 name("");
+ std::string name;
if (u == (uid_t)-1) {
- name.appendFormat("%7u", entry->getKey());
+ name = android::base::StringPrintf("%7u",
+ entry->getKey());
} else {
- name.appendFormat("%7u/%u", entry->getKey(), u);
+ name = android::base::StringPrintf("%7u/%u",
+ entry->getKey(), u);
}
const char *n = entry->getName();
if (n) {
- name.appendFormat("%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", n);
+ name += android::base::StringPrintf(
+ "%*s%s", (int)std::max(14 - name.length(), (size_t)1),
+ "", n);
}
- android::String8 size("");
- size.appendFormat("%zu", entry->getSizes());
+ std::string size = android::base::StringPrintf("%zu",
+ entry->getSizes());
- format_line(output, name, size, pruned);
+ output += format_line(name, size, pruned);
}
}
- *buf = strdup(output.string());
+ return output;
}
namespace android {
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 760d6b2..61000d2 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -331,8 +331,7 @@
size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
- // *strp = malloc, balance with free
- void format(char **strp, uid_t uid, unsigned int logMask);
+ std::string format(uid_t uid, unsigned int logMask);
// helper (must be locked directly or implicitly by mLogElementsLock)
char *pidToName(pid_t pid);
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 783bce6..39bcdd4 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -20,8 +20,10 @@
#include <pthread.h>
#include <time.h>
#include <sys/types.h>
+
+#include <list>
+
#include <sysutils/SocketClient.h>
-#include <utils/List.h>
#include <log/log.h>
class LogReader;
@@ -107,6 +109,6 @@
static int FilterSecondPass(const LogBufferElement *element, void *me);
};
-typedef android::List<LogTimeEntry *> LastLogTimes;
+typedef std::list<LogTimeEntry *> LastLogTimes;
-#endif
+#endif // _LOGD_LOG_TIMES_H__
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index 277b3ca..ad005ec 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -16,7 +16,7 @@
#include <ctype.h>
-#include <utils/String8.h>
+#include <base/stringprintf.h>
#include "LogWhiteBlackList.h"
@@ -35,46 +35,40 @@
return uid - mUid;
}
-void Prune::format(char **strp) {
+std::string Prune::format() {
if (mUid != uid_all) {
if (mPid != pid_all) {
- asprintf(strp, "%u/%u", mUid, mPid);
- } else {
- asprintf(strp, "%u", mUid);
+ return android::base::StringPrintf("%u/%u", mUid, mPid);
}
- } else if (mPid != pid_all) {
- asprintf(strp, "/%u", mPid);
- } else { // NB: mPid == pid_all can not happen if mUid == uid_all
- asprintf(strp, "/");
+ return android::base::StringPrintf("%u", mUid);
}
+ if (mPid != pid_all) {
+ return android::base::StringPrintf("/%u", mPid);
+ }
+ // NB: mPid == pid_all can not happen if mUid == uid_all
+ return std::string("/");
}
PruneList::PruneList() : mWorstUidEnabled(true) {
- mNaughty.clear();
- mNice.clear();
}
PruneList::~PruneList() {
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end();) {
- delete (*it);
it = mNice.erase(it);
}
for (it = mNaughty.begin(); it != mNaughty.end();) {
- delete (*it);
it = mNaughty.erase(it);
}
}
-int PruneList::init(char *str) {
+int PruneList::init(const char *str) {
mWorstUidEnabled = true;
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end();) {
- delete (*it);
it = mNice.erase(it);
}
for (it = mNaughty.begin(); it != mNaughty.end();) {
- delete (*it);
it = mNaughty.erase(it);
}
@@ -142,28 +136,28 @@
// insert sequentially into list
PruneCollection::iterator it = list->begin();
while (it != list->end()) {
- Prune *p = *it;
- int m = uid - p->mUid;
+ Prune &p = *it;
+ int m = uid - p.mUid;
if (m == 0) {
- if (p->mPid == p->pid_all) {
+ if (p.mPid == p.pid_all) {
break;
}
- if ((pid == p->pid_all) && (p->mPid != p->pid_all)) {
+ if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
it = list->erase(it);
continue;
}
- m = pid - p->mPid;
+ m = pid - p.mPid;
}
if (m <= 0) {
if (m < 0) {
- list->insert(it, new Prune(uid,pid));
+ list->insert(it, Prune(uid,pid));
}
break;
}
++it;
}
if (it == list->end()) {
- list->push_back(new Prune(uid,pid));
+ list->push_back(Prune(uid,pid));
}
if (!*str) {
break;
@@ -173,47 +167,32 @@
return 0;
}
-void PruneList::format(char **strp) {
- if (*strp) {
- free(*strp);
- *strp = NULL;
- }
-
+std::string PruneList::format() {
static const char nice_format[] = " %s";
const char *fmt = nice_format + 1;
- android::String8 string;
+ std::string string;
if (mWorstUidEnabled) {
- string.setTo("~!");
+ string = "~!";
fmt = nice_format;
}
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end(); ++it) {
- char *a = NULL;
- (*it)->format(&a);
-
- string.appendFormat(fmt, a);
+ string += android::base::StringPrintf(fmt, (*it).format().c_str());
fmt = nice_format;
-
- free(a);
}
static const char naughty_format[] = " ~%s";
fmt = naughty_format + (*fmt != ' ');
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
- char *a = NULL;
- (*it)->format(&a);
-
- string.appendFormat(fmt, a);
+ string += android::base::StringPrintf(fmt, (*it).format().c_str());
fmt = naughty_format;
-
- free(a);
}
- *strp = strdup(string.string());
+ return string;
}
// ToDo: Lists are in sorted order, Prune->cmp() returns + or -
@@ -223,7 +202,7 @@
bool PruneList::naughty(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
- if (!(*it)->cmp(element)) {
+ if (!(*it).cmp(element)) {
return true;
}
}
@@ -233,7 +212,7 @@
bool PruneList::nice(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end(); ++it) {
- if (!(*it)->cmp(element)) {
+ if (!(*it).cmp(element)) {
return true;
}
}
diff --git a/logd/LogWhiteBlackList.h b/logd/LogWhiteBlackList.h
index 5f60801..00e1cad 100644
--- a/logd/LogWhiteBlackList.h
+++ b/logd/LogWhiteBlackList.h
@@ -19,7 +19,8 @@
#include <sys/types.h>
-#include <utils/List.h>
+#include <list>
+#include <string.h>
#include <LogBufferElement.h>
@@ -43,11 +44,10 @@
int cmp(LogBufferElement *e) const { return cmp(e->getUid(), e->getPid()); }
- // *strp is malloc'd, use free to release
- void format(char **strp);
+ std::string format();
};
-typedef android::List<Prune *> PruneCollection;
+typedef std::list<Prune> PruneCollection;
class PruneList {
PruneCollection mNaughty;
@@ -58,7 +58,7 @@
PruneList();
~PruneList();
- int init(char *str);
+ int init(const char *str);
bool naughty(LogBufferElement *element);
bool naughty(void) { return !mNaughty.empty(); }
@@ -66,8 +66,7 @@
bool nice(void) { return !mNice.empty(); }
bool worstUidEnabled() const { return mWorstUidEnabled; }
- // *strp is malloc'd, use free to release
- void format(char **strp);
+ std::string format();
};
#endif // _LOGD_LOG_WHITE_BLACK_LIST_H__
diff --git a/logd/logd.rc b/logd/logd.rc
new file mode 100644
index 0000000..da6a0bc
--- /dev/null
+++ b/logd/logd.rc
@@ -0,0 +1,10 @@
+service logd /system/bin/logd
+ class core
+ socket logd stream 0666 logd logd
+ socket logdr seqpacket 0666 logd logd
+ socket logdw dgram 0222 logd logd
+ group root system
+
+service logd-reinit /system/bin/logd --reinit
+ oneshot
+ disabled
diff --git a/logwrapper/Android.mk b/logwrapper/Android.mk
index 61b4659..ad45b2c 100644
--- a/logwrapper/Android.mk
+++ b/logwrapper/Android.mk
@@ -11,7 +11,7 @@
LOCAL_SHARED_LIBRARIES := libcutils liblog
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
+LOCAL_CFLAGS := -Werror -std=gnu99
include $(BUILD_STATIC_LIBRARY)
# ========================================================
@@ -23,7 +23,7 @@
LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
+LOCAL_CFLAGS := -Werror -std=gnu99
include $(BUILD_SHARED_LIBRARY)
# ========================================================
@@ -33,5 +33,5 @@
LOCAL_SRC_FILES:= logwrapper.c
LOCAL_MODULE := logwrapper
LOCAL_STATIC_LIBRARIES := liblog liblogwrap libcutils
-LOCAL_CFLAGS := -Werror
+LOCAL_CFLAGS := -Werror -std=gnu99
include $(BUILD_EXECUTABLE)
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
index 4307a30..89a8fdd 100644
--- a/logwrapper/include/logwrap/logwrap.h
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -19,6 +19,7 @@
#define __LIBS_LOGWRAP_H
#include <stdbool.h>
+#include <stdint.h>
__BEGIN_DECLS
@@ -53,6 +54,9 @@
* the specified log until the child has exited.
* file_path: if log_target has the LOG_FILE bit set, then this parameter
* must be set to the pathname of the file to log to.
+ * opts: set to non-NULL if you want to use one or more of the
+ * FORK_EXECVP_OPTION_* features.
+ * opts_len: the length of the opts array. When opts is NULL, pass 0.
*
* Return value:
* 0 when logwrap successfully run the child process and captured its status
@@ -68,8 +72,30 @@
#define LOG_KLOG 2
#define LOG_FILE 4
+/* Write data to child's stdin. */
+#define FORK_EXECVP_OPTION_INPUT 0
+/* Capture data from child's stdout and stderr. */
+#define FORK_EXECVP_OPTION_CAPTURE_OUTPUT 1
+
+struct AndroidForkExecvpOption {
+ int opt_type;
+ union {
+ struct {
+ const uint8_t* input;
+ size_t input_len;
+ } opt_input;
+ struct {
+ void (*on_output)(const uint8_t* /*output*/,
+ size_t /*output_len*/,
+ void* /* user_pointer */);
+ void* user_pointer;
+ } opt_capture_output;
+ };
+};
+
int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
- int log_target, bool abbreviated, char *file_path);
+ int log_target, bool abbreviated, char *file_path,
+ const struct AndroidForkExecvpOption* opts, size_t opts_len);
/* Similar to above, except abbreviated logging is not available, and if logwrap
* is true, logging is to the Android system log, and if false, there is no
@@ -79,7 +105,8 @@
bool ignore_int_quit, bool logwrap)
{
return android_fork_execvp_ext(argc, argv, status, ignore_int_quit,
- (logwrap ? LOG_ALOG : LOG_NONE), false, NULL);
+ (logwrap ? LOG_ALOG : LOG_NONE), false, NULL,
+ NULL, 0);
}
__END_DECLS
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 44455d1..28d6de7 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -291,7 +291,8 @@
}
static int parent(const char *tag, int parent_read, pid_t pid,
- int *chld_sts, int log_target, bool abbreviated, char *file_path) {
+ int *chld_sts, int log_target, bool abbreviated, char *file_path,
+ const struct AndroidForkExecvpOption* opts, size_t opts_len) {
int status = 0;
char buffer[4096];
struct pollfd poll_fds[] = {
@@ -358,6 +359,13 @@
sz = TEMP_FAILURE_RETRY(
read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
+ for (size_t i = 0; sz > 0 && i < opts_len; ++i) {
+ if (opts[i].opt_type == FORK_EXECVP_OPTION_CAPTURE_OUTPUT) {
+ opts[i].opt_capture_output.on_output(
+ (uint8_t*)&buffer[b], sz, opts[i].opt_capture_output.user_pointer);
+ }
+ }
+
sz += b;
// Log one line at a time
for (b = 0; b < sz; b++) {
@@ -474,7 +482,8 @@
}
int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
- int log_target, bool abbreviated, char *file_path) {
+ int log_target, bool abbreviated, char *file_path,
+ const struct AndroidForkExecvpOption* opts, size_t opts_len) {
pid_t pid;
int parent_ptty;
int child_ptty;
@@ -529,7 +538,13 @@
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
close(parent_ptty);
- // redirect stdout and stderr
+ // redirect stdin, stdout and stderr
+ for (size_t i = 0; i < opts_len; ++i) {
+ if (opts[i].opt_type == FORK_EXECVP_OPTION_INPUT) {
+ dup2(child_ptty, 0);
+ break;
+ }
+ }
dup2(child_ptty, 1);
dup2(child_ptty, 2);
close(child_ptty);
@@ -546,8 +561,24 @@
sigaction(SIGQUIT, &ignact, &quitact);
}
+ for (size_t i = 0; i < opts_len; ++i) {
+ if (opts[i].opt_type == FORK_EXECVP_OPTION_INPUT) {
+ size_t left = opts[i].opt_input.input_len;
+ const uint8_t* input = opts[i].opt_input.input;
+ while (left > 0) {
+ ssize_t res =
+ TEMP_FAILURE_RETRY(write(parent_ptty, input, left));
+ if (res < 0) {
+ break;
+ }
+ left -= res;
+ input += res;
+ }
+ }
+ }
+
rc = parent(argv[0], parent_ptty, pid, status, log_target,
- abbreviated, file_path);
+ abbreviated, file_path, opts, opts_len);
}
if (ignore_int_quit) {
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index 9e0385d..55b71c7 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -81,7 +81,7 @@
}
rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
- log_target, abbreviated, NULL);
+ log_target, abbreviated, NULL, NULL, 0);
if (!rc) {
if (WIFEXITED(status))
rc = WEXITSTATUS(status);
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index 17fb278..9fd8eda 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -14,6 +14,10 @@
LOCAL_PATH := $(call my-dir)
+ifeq ($(HOST_OS),linux)
+
+LOCAL_INIT_SERVICE := metrics_daemon
+
metrics_cpp_extension := .cc
libmetrics_sources := \
c_metrics_library.cc \
@@ -38,7 +42,6 @@
serialization/serialization_utils.cc
metrics_CFLAGS := -Wall \
- -D__BRILLO__ \
-Wno-char-subscripts \
-Wno-missing-field-initializers \
-Wno-unused-function \
@@ -94,12 +97,13 @@
# metrics daemon.
# ========================================================
include $(CLEAR_VARS)
-LOCAL_MODULE := metrics_daemon
+LOCAL_MODULE := $(LOCAL_INIT_SERVICE)
LOCAL_C_INCLUDES := $(metrics_includes) \
external/libchromeos
LOCAL_CFLAGS := $(metrics_CFLAGS)
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
+LOCAL_REQUIRED_MODULES := init.$(LOCAL_INIT_SERVICE).rc
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES := $(metrics_shared_libraries) \
libmetrics \
@@ -110,3 +114,14 @@
LOCAL_SRC_FILES := $(metrics_daemon_sources)
LOCAL_STATIC_LIBRARIES := metrics_daemon_protos
include $(BUILD_EXECUTABLE)
+
+ifdef INITRC_TEMPLATE
+include $(CLEAR_VARS)
+LOCAL_MODULE := init.$(LOCAL_INIT_SERVICE).rc
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_INITRCD)
+LOCAL_SRC_FILES := init.$(LOCAL_INIT_SERVICE).rc
+include $(BUILD_PREBUILT)
+endif # INITRC_TEMPLATE
+
+endif # HOST_OS == linux
diff --git a/metricsd/MODULE_LICENSE_BSD b/metricsd/MODULE_LICENSE_BSD
deleted file mode 100644
index e69de29..0000000
--- a/metricsd/MODULE_LICENSE_BSD
+++ /dev/null
diff --git a/metricsd/NOTICE b/metricsd/NOTICE
deleted file mode 100644
index b9e779f..0000000
--- a/metricsd/NOTICE
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. 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.
diff --git a/metricsd/README b/metricsd/README
index 4b92af3..d4c9a0e 100644
--- a/metricsd/README
+++ b/metricsd/README
@@ -1,6 +1,18 @@
-Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
+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.
+
+================================================================================
The Chrome OS "metrics" package contains utilities for client-side user metric
collection.
diff --git a/metricsd/c_metrics_library.cc b/metricsd/c_metrics_library.cc
index 90a2d59..0503876 100644
--- a/metricsd/c_metrics_library.cc
+++ b/metricsd/c_metrics_library.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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.
+ */
//
// C wrapper to libmetrics
diff --git a/metricsd/constants.h b/metricsd/constants.h
index d65e0e0..56dac0d 100644
--- a/metricsd/constants.h
+++ b/metricsd/constants.h
@@ -21,7 +21,7 @@
static const char kMetricsDirectory[] = "/data/misc/metrics/";
static const char kMetricsEventsFilePath[] = "/data/misc/metrics/uma-events";
static const char kMetricsGUIDFilePath[] = "/data/misc/metrics/Sysinfo.GUID";
-static const char kMetricsServer[] = "http://clients4.google.com/uma/v2";
+static const char kMetricsServer[] = "https://clients4.google.com/uma/v2";
static const char kConsentFilePath[] = "/data/misc/metrics/enabled";
static const char kDefaultVersion[] = "0.0.0.0";
} // namespace metrics
diff --git a/metricsd/include/metrics/c_metrics_library.h b/metricsd/include/metrics/c_metrics_library.h
index 7f78e43..4e7e666 100644
--- a/metricsd/include/metrics/c_metrics_library.h
+++ b/metricsd/include/metrics/c_metrics_library.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_C_METRICS_LIBRARY_H_
#define METRICS_C_METRICS_LIBRARY_H_
diff --git a/metricsd/include/metrics/metrics_library.h b/metricsd/include/metrics/metrics_library.h
index 1c124d2..4917a7c 100644
--- a/metricsd/include/metrics/metrics_library.h
+++ b/metricsd/include/metrics/metrics_library.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_METRICS_LIBRARY_H_
#define METRICS_METRICS_LIBRARY_H_
diff --git a/metricsd/init.metrics_daemon.rc b/metricsd/init.metrics_daemon.rc
new file mode 100644
index 0000000..73ce673
--- /dev/null
+++ b/metricsd/init.metrics_daemon.rc
@@ -0,0 +1,8 @@
+on boot
+ mkdir /data/misc/metrics 0770 system system
+
+service metrics_daemon /system/bin/metrics_daemon --uploader -nodaemon
+ class late_start
+ user system
+ group system dbus inet
+ seclabel u:r:brillo:s0
diff --git a/metricsd/init/metrics_daemon.conf b/metricsd/init/metrics_daemon.conf
deleted file mode 100644
index e6932cf..0000000
--- a/metricsd/init/metrics_daemon.conf
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description "Metrics collection daemon"
-author "chromium-os-dev@chromium.org"
-
-# The metrics daemon is responsible for receiving and forwarding to
-# chrome UMA statistics not produced by chrome.
-start on starting system-services
-stop on stopping system-services
-respawn
-
-# metrics will update the next line to add -uploader for embedded builds.
-env DAEMON_FLAGS=""
-
-expect fork
-exec metrics_daemon ${DAEMON_FLAGS}
diff --git a/metricsd/init/metrics_library.conf b/metricsd/init/metrics_library.conf
deleted file mode 100644
index 03016d1..0000000
--- a/metricsd/init/metrics_library.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description "Metrics Library upstart file"
-author "chromium-os-dev@chromium.org"
-
-# The metrics library is used by several programs (daemons and others)
-# to send UMA stats.
-start on starting boot-services
-
-pre-start script
- # Create the file used as communication endpoint for metrics.
- METRICS_DIR=/var/lib/metrics
- EVENTS_FILE=${METRICS_DIR}/uma-events
- mkdir -p ${METRICS_DIR}
- touch ${EVENTS_FILE}
- chown chronos.chronos ${EVENTS_FILE}
- chmod 666 ${EVENTS_FILE}
- # TRANSITION ONLY.
- # TODO(semenzato) Remove after Chrome change, see issue 447256.
- # Let Chrome read the metrics file from the old location.
- mkdir -p /var/run/metrics
- ln -sf ${EVENTS_FILE} /var/run/metrics
-end script
diff --git a/metricsd/make_tests.sh b/metricsd/make_tests.sh
deleted file mode 100755
index 9dcc804..0000000
--- a/metricsd/make_tests.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Builds tests.
-
-set -e
-make tests
-mkdir -p "${OUT_DIR}"
-cp *_test "${OUT_DIR}"
diff --git a/metricsd/metrics_client.cc b/metricsd/metrics_client.cc
index b587e3a..57e96c2 100644
--- a/metricsd/metrics_client.cc
+++ b/metricsd/metrics_client.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <cstdio>
#include <cstdlib>
diff --git a/metricsd/metrics_daemon.cc b/metricsd/metrics_daemon.cc
index f9061d5..069f68e 100644
--- a/metricsd/metrics_daemon.cc
+++ b/metricsd/metrics_daemon.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 "metrics_daemon.h"
diff --git a/metricsd/metrics_daemon.h b/metricsd/metrics_daemon.h
index ccac52a..6f5a3bf 100644
--- a/metricsd/metrics_daemon.h
+++ b/metricsd/metrics_daemon.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_METRICS_DAEMON_H_
#define METRICS_METRICS_DAEMON_H_
diff --git a/metricsd/metrics_daemon_main.cc b/metricsd/metrics_daemon_main.cc
index 6c580ba..c3d5cab 100644
--- a/metricsd/metrics_daemon_main.cc
+++ b/metricsd/metrics_daemon_main.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <base/at_exit.h>
#include <base/command_line.h>
diff --git a/metricsd/metrics_daemon_test.cc b/metricsd/metrics_daemon_test.cc
index 5aa7ab8..9b5b58e 100644
--- a/metricsd/metrics_daemon_test.cc
+++ b/metricsd/metrics_daemon_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <inttypes.h>
#include <utime.h>
diff --git a/metricsd/metrics_library.cc b/metricsd/metrics_library.cc
index f777f28..c1998a6 100644
--- a/metricsd/metrics_library.cc
+++ b/metricsd/metrics_library.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 "metrics/metrics_library.h"
diff --git a/metricsd/metrics_library_mock.h b/metricsd/metrics_library_mock.h
index 99892bf..3de87a9 100644
--- a/metricsd/metrics_library_mock.h
+++ b/metricsd/metrics_library_mock.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_METRICS_LIBRARY_MOCK_H_
#define METRICS_METRICS_LIBRARY_MOCK_H_
diff --git a/metricsd/metrics_library_test.cc b/metricsd/metrics_library_test.cc
index 7ede303..c58e3fb 100644
--- a/metricsd/metrics_library_test.cc
+++ b/metricsd/metrics_library_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <cstring>
diff --git a/metricsd/persistent_integer.cc b/metricsd/persistent_integer.cc
index 0dcd52a..9fa5c1e 100644
--- a/metricsd/persistent_integer.cc
+++ b/metricsd/persistent_integer.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 "persistent_integer.h"
diff --git a/metricsd/persistent_integer.h b/metricsd/persistent_integer.h
index b1cfcf4..fec001f 100644
--- a/metricsd/persistent_integer.h
+++ b/metricsd/persistent_integer.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_PERSISTENT_INTEGER_H_
#define METRICS_PERSISTENT_INTEGER_H_
diff --git a/metricsd/persistent_integer_mock.h b/metricsd/persistent_integer_mock.h
index 31bfc35..acc5389 100644
--- a/metricsd/persistent_integer_mock.h
+++ b/metricsd/persistent_integer_mock.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_PERSISTENT_INTEGER_MOCK_H_
#define METRICS_PERSISTENT_INTEGER_MOCK_H_
diff --git a/metricsd/persistent_integer_test.cc b/metricsd/persistent_integer_test.cc
index 4fccb72..19801f9 100644
--- a/metricsd/persistent_integer_test.cc
+++ b/metricsd/persistent_integer_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <gtest/gtest.h>
diff --git a/metricsd/platform2_preinstall.sh b/metricsd/platform2_preinstall.sh
deleted file mode 100755
index ccf353f..0000000
--- a/metricsd/platform2_preinstall.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-set -e
-
-OUT=$1
-shift
-for v; do
- sed -e "s/@BSLOT@/${v}/g" libmetrics.pc.in > "${OUT}/lib/libmetrics-${v}.pc"
-done
diff --git a/metricsd/serialization/metric_sample.cc b/metricsd/serialization/metric_sample.cc
index bc6583d..76a47c0 100644
--- a/metricsd/serialization/metric_sample.cc
+++ b/metricsd/serialization/metric_sample.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "serialization/metric_sample.h"
diff --git a/metricsd/serialization/metric_sample.h b/metricsd/serialization/metric_sample.h
index 877114d..5a4e4ae 100644
--- a/metricsd/serialization/metric_sample.h
+++ b/metricsd/serialization/metric_sample.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_SERIALIZATION_METRIC_SAMPLE_H_
#define METRICS_SERIALIZATION_METRIC_SAMPLE_H_
diff --git a/metricsd/serialization/serialization_utils.cc b/metricsd/serialization/serialization_utils.cc
index d18dcd7..6dd8258 100644
--- a/metricsd/serialization/serialization_utils.cc
+++ b/metricsd/serialization/serialization_utils.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "serialization/serialization_utils.h"
diff --git a/metricsd/serialization/serialization_utils.h b/metricsd/serialization/serialization_utils.h
index 5af6166..67d4675 100644
--- a/metricsd/serialization/serialization_utils.h
+++ b/metricsd/serialization/serialization_utils.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_SERIALIZATION_SERIALIZATION_UTILS_H_
#define METRICS_SERIALIZATION_SERIALIZATION_UTILS_H_
diff --git a/metricsd/serialization/serialization_utils_unittest.cc b/metricsd/serialization/serialization_utils_unittest.cc
index fb802bc..7a572de 100644
--- a/metricsd/serialization/serialization_utils_unittest.cc
+++ b/metricsd/serialization/serialization_utils_unittest.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "serialization/serialization_utils.h"
diff --git a/metricsd/syslog_parser.sh b/metricsd/syslog_parser.sh
deleted file mode 100755
index 7d064be..0000000
--- a/metricsd/syslog_parser.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#! /bin/sh
-
-# This script parses /var/log/syslog for messages from programs that log
-# uptime and disk stats (number of sectors read). It then outputs
-# these stats in a format usable by the metrics collector, which forwards
-# them to autotest and UMA.
-
-# To add a new metric add a line below, as PROGRAM_NAME METRIC_NAME.
-# PROGRAM_NAME is the name of the job whose start time we
-# are interested in. METRIC_NAME is the prefix we want to use for
-# reporting to UMA and autotest. The script prepends "Time" and
-# "Sectors" to METRIC_NAME for the two available measurements, uptime
-# and number of sectors read thus far.
-
-# You will need to emit messages similar to the following in order to add a
-# a metric using this process. You will need to emit both a start and stop
-# time and the metric reported will be the difference in values
-
-# Nov 15 08:05 localhost PROGRAM_NAME[822]: start METRIC_NAME time 12 sectors 56
-# Nov 15 08:05 localhost PROGRAM_NAME[822]: stop METRIC_NAME time 24 sectors 68
-
-# If you add metrics without a start, it is assumed you are requesting the
-# time differece from system start
-
-# Metrics we are interested in measuring
-METRICS="
-upstart start_x
-"
-
-first=1
-program=""
-
-# Get the metrics for all things
-for m in $METRICS
-do
- if [ $first -eq 1 ]
- then
- first=0
- program_name=$m
- else
- first=1
- metrics_name=$m
-
- # Example of line from /var/log/messages:
- # Nov 15 08:05:42 localhost connmand[822]: start metric time 12 sectors 56
- # "upstart:" is $5, 1234 is $9, etc.
- program="${program}/$program_name([[0-9]+]:|:) start $metrics_name/\
- {
- metrics_start[\"${metrics_name}Time\"] = \$9;
- metrics_start[\"${metrics_name}Sectors\"] = \$11;
- }"
- program="${program}/$program_name([[0-9]+]:|:) stop $metrics_name/\
- {
- metrics_stop[\"${metrics_name}Time\"] = \$9;
- metrics_stop[\"${metrics_name}Sectors\"] = \$11;
- }"
- fi
-done
-
-# Do all the differencing here
-program="${program}\
-END{
- for (i in metrics_stop) {
- value_time = metrics_stop[i] - metrics_start[i];
- print i \"=\" value_time;
- }
-}"
-
-exec awk "$program" /var/log/syslog
diff --git a/metricsd/timer.cc b/metricsd/timer.cc
index ce4bf67..7b00cc0 100644
--- a/metricsd/timer.cc
+++ b/metricsd/timer.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 "timer.h"
diff --git a/metricsd/timer.h b/metricsd/timer.h
index 52cc578..b36ffff 100644
--- a/metricsd/timer.h
+++ b/metricsd/timer.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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.
+ */
// Timer - class that provides timer tracking.
diff --git a/metricsd/timer_mock.h b/metricsd/timer_mock.h
index ed76f12..8c9e8d8 100644
--- a/metricsd/timer_mock.h
+++ b/metricsd/timer_mock.h
@@ -1,6 +1,18 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_TIMER_MOCK_H_
#define METRICS_TIMER_MOCK_H_
diff --git a/metricsd/timer_test.cc b/metricsd/timer_test.cc
index b1689bf..ab027d4 100644
--- a/metricsd/timer_test.cc
+++ b/metricsd/timer_test.cc
@@ -1,6 +1,18 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <stdint.h>
diff --git a/metricsd/uploader/metrics_hashes.cc b/metricsd/uploader/metrics_hashes.cc
index f9d0cfe..208c560 100644
--- a/metricsd/uploader/metrics_hashes.cc
+++ b/metricsd/uploader/metrics_hashes.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/metrics_hashes.h"
diff --git a/metricsd/uploader/metrics_hashes.h b/metricsd/uploader/metrics_hashes.h
index 8679077..1082b42 100644
--- a/metricsd/uploader/metrics_hashes.h
+++ b/metricsd/uploader/metrics_hashes.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_METRICS_HASHES_H_
#define METRICS_UPLOADER_METRICS_HASHES_H_
diff --git a/metricsd/uploader/metrics_hashes_unittest.cc b/metricsd/uploader/metrics_hashes_unittest.cc
index 8cdc7a9..b8c2575 100644
--- a/metricsd/uploader/metrics_hashes_unittest.cc
+++ b/metricsd/uploader/metrics_hashes_unittest.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/metrics_hashes.h"
diff --git a/metricsd/uploader/metrics_log.cc b/metricsd/uploader/metrics_log.cc
index 6f11f8a..1f16ca1 100644
--- a/metricsd/uploader/metrics_log.cc
+++ b/metricsd/uploader/metrics_log.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/metrics_log.h"
@@ -36,6 +48,6 @@
stability->set_unclean_system_shutdown_count(current + 1);
}
-void MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
- profile_setter->Populate(uma_proto());
+bool MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
+ return profile_setter->Populate(uma_proto());
}
diff --git a/metricsd/uploader/metrics_log.h b/metricsd/uploader/metrics_log.h
index a62798f..5e09070 100644
--- a/metricsd/uploader/metrics_log.h
+++ b/metricsd/uploader/metrics_log.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_METRICS_LOG_H_
#define METRICS_UPLOADER_METRICS_LOG_H_
@@ -27,7 +39,7 @@
void IncrementUncleanShutdownCount();
// Populate the system profile with system information using setter.
- void PopulateSystemProfile(SystemProfileSetter* setter);
+ bool PopulateSystemProfile(SystemProfileSetter* setter);
private:
FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
diff --git a/metricsd/uploader/metrics_log_base.cc b/metricsd/uploader/metrics_log_base.cc
index 3ae01e8..ee325ae 100644
--- a/metricsd/uploader/metrics_log_base.cc
+++ b/metricsd/uploader/metrics_log_base.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/metrics_log_base.h"
diff --git a/metricsd/uploader/metrics_log_base.h b/metricsd/uploader/metrics_log_base.h
index 4173335..f4e1995 100644
--- a/metricsd/uploader/metrics_log_base.h
+++ b/metricsd/uploader/metrics_log_base.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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.
+ */
// This file defines a set of user experience metrics data recorded by
// the MetricsService. This is the unit of data that is sent to the server.
diff --git a/metricsd/uploader/metrics_log_base_unittest.cc b/metricsd/uploader/metrics_log_base_unittest.cc
index dc03f00..980afd5 100644
--- a/metricsd/uploader/metrics_log_base_unittest.cc
+++ b/metricsd/uploader/metrics_log_base_unittest.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/metrics_log_base.h"
diff --git a/metricsd/uploader/mock/mock_system_profile_setter.h b/metricsd/uploader/mock/mock_system_profile_setter.h
index c6e8f0d..c714e9c 100644
--- a/metricsd/uploader/mock/mock_system_profile_setter.h
+++ b/metricsd/uploader/mock/mock_system_profile_setter.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
#define METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/mock/sender_mock.cc b/metricsd/uploader/mock/sender_mock.cc
index 064ec6d..bb4dc7d 100644
--- a/metricsd/uploader/mock/sender_mock.cc
+++ b/metricsd/uploader/mock/sender_mock.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/mock/sender_mock.h"
diff --git a/metricsd/uploader/mock/sender_mock.h b/metricsd/uploader/mock/sender_mock.h
index 0a15d61..e79233f 100644
--- a/metricsd/uploader/mock/sender_mock.h
+++ b/metricsd/uploader/mock/sender_mock.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
#define METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
diff --git a/metricsd/uploader/proto/README b/metricsd/uploader/proto/README
index 9bd3249..4292a40 100644
--- a/metricsd/uploader/proto/README
+++ b/metricsd/uploader/proto/README
@@ -1,6 +1,18 @@
-Copyright 2015 The Chromium OS Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
+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.
+
+
This directory contains the protocol buffers used by the standalone metrics
diff --git a/metricsd/uploader/proto/chrome_user_metrics_extension.proto b/metricsd/uploader/proto/chrome_user_metrics_extension.proto
index d4d4f24..a07830f 100644
--- a/metricsd/uploader/proto/chrome_user_metrics_extension.proto
+++ b/metricsd/uploader/proto/chrome_user_metrics_extension.proto
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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.
+ */
//
// Protocol buffer for Chrome UMA (User Metrics Analysis).
//
diff --git a/metricsd/uploader/proto/histogram_event.proto b/metricsd/uploader/proto/histogram_event.proto
index 4b68094..3825063 100644
--- a/metricsd/uploader/proto/histogram_event.proto
+++ b/metricsd/uploader/proto/histogram_event.proto
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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.
+ */
//
// Histogram-collected metrics.
diff --git a/metricsd/uploader/proto/system_profile.proto b/metricsd/uploader/proto/system_profile.proto
index d33ff60..4cab0d9 100644
--- a/metricsd/uploader/proto/system_profile.proto
+++ b/metricsd/uploader/proto/system_profile.proto
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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.
+ */
//
// Stores information about the user's brower and system configuration.
// The system configuration fields are recorded once per client session.
diff --git a/metricsd/uploader/proto/user_action_event.proto b/metricsd/uploader/proto/user_action_event.proto
index 30a9318..464f3c8 100644
--- a/metricsd/uploader/proto/user_action_event.proto
+++ b/metricsd/uploader/proto/user_action_event.proto
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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.
+ */
//
// Stores information about an event that occurs in response to a user action,
// e.g. an interaction with a browser UI element.
diff --git a/metricsd/uploader/sender.h b/metricsd/uploader/sender.h
index 5211834..369c9c2 100644
--- a/metricsd/uploader/sender.h
+++ b/metricsd/uploader/sender.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_SENDER_H_
#define METRICS_UPLOADER_SENDER_H_
diff --git a/metricsd/uploader/sender_http.cc b/metricsd/uploader/sender_http.cc
index a740310..953afc1 100644
--- a/metricsd/uploader/sender_http.cc
+++ b/metricsd/uploader/sender_http.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/sender_http.h"
diff --git a/metricsd/uploader/sender_http.h b/metricsd/uploader/sender_http.h
index 380cad8..6249d90 100644
--- a/metricsd/uploader/sender_http.h
+++ b/metricsd/uploader/sender_http.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_SENDER_HTTP_H_
#define METRICS_UPLOADER_SENDER_HTTP_H_
diff --git a/metricsd/uploader/system_profile_cache.cc b/metricsd/uploader/system_profile_cache.cc
index adbe0ae..7dd0323 100644
--- a/metricsd/uploader/system_profile_cache.cc
+++ b/metricsd/uploader/system_profile_cache.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/system_profile_cache.h"
@@ -63,7 +75,7 @@
if (!base::SysInfo::GetLsbReleaseValue("BRILLO_BUILD_TARGET_ID",
&profile_.build_target_id)) {
- LOG(ERROR) << "Could not initialize system profile.";
+ LOG(ERROR) << "BRILLO_BUILD_TARGET_ID is not set in /etc/lsb-release.";
return false;
}
@@ -97,11 +109,12 @@
return initialized_ || Initialize();
}
-void SystemProfileCache::Populate(
+bool SystemProfileCache::Populate(
metrics::ChromeUserMetricsExtension* metrics_proto) {
CHECK(metrics_proto);
- CHECK(InitializeOrCheck())
- << "failed to initialize system information.";
+ if (not InitializeOrCheck()) {
+ return false;
+ }
// The client id is hashed before being sent.
metrics_proto->set_client_id(
@@ -120,6 +133,8 @@
metrics::SystemProfileProto_BrilloDeviceData* device_data =
profile_proto->mutable_brillo();
device_data->set_build_target_id(profile_.build_target_id);
+
+ return true;
}
std::string SystemProfileCache::GetPersistentGUID(
diff --git a/metricsd/uploader/system_profile_cache.h b/metricsd/uploader/system_profile_cache.h
index b6ff337..ac80b47 100644
--- a/metricsd/uploader/system_profile_cache.h
+++ b/metricsd/uploader/system_profile_cache.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
#define METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
@@ -40,7 +52,7 @@
SystemProfileCache(bool testing, const std::string& config_root);
// Populates the ProfileSystem protobuf with system information.
- void Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
+ bool Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
// Converts a string representation of the channel to a
// SystemProfileProto_Channel
diff --git a/metricsd/uploader/system_profile_setter.h b/metricsd/uploader/system_profile_setter.h
index c535664..bd3ff42 100644
--- a/metricsd/uploader/system_profile_setter.h
+++ b/metricsd/uploader/system_profile_setter.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
#define METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
@@ -15,7 +27,7 @@
public:
virtual ~SystemProfileSetter() {}
// Populates the protobuf with system informations.
- virtual void Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
+ virtual bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
};
#endif // METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/upload_service.cc b/metricsd/uploader/upload_service.cc
index 3411004..2335630 100644
--- a/metricsd/uploader/upload_service.cc
+++ b/metricsd/uploader/upload_service.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "uploader/upload_service.h"
@@ -61,7 +73,6 @@
CHECK(!staged_log_) << "the staged log should be discarded before starting "
"a new metrics log";
MetricsLog* log = new MetricsLog();
- log->PopulateSystemProfile(system_profile_setter_.get());
current_log_.reset(log);
}
@@ -85,13 +96,12 @@
// Previous upload successful, reading metrics sample from the file.
ReadMetrics();
GatherHistograms();
-
- // No samples found. Exit to avoid sending an empty log.
- if (!current_log_)
- return;
-
StageCurrentLog();
- SendStagedLog();
+
+ // If a log is available for upload, upload it.
+ if (staged_log_) {
+ SendStagedLog();
+ }
}
void UploadService::SendStagedLog() {
@@ -213,6 +223,11 @@
staged_log_.swap(current_log_);
staged_log_->CloseLog();
+ if (!staged_log_->PopulateSystemProfile(system_profile_setter_.get())) {
+ LOG(WARNING) << "Error while adding metadata to the log. Discarding the "
+ << "log.";
+ staged_log_.reset();
+ }
failed_upload_count_ = 0;
}
diff --git a/metricsd/uploader/upload_service.h b/metricsd/uploader/upload_service.h
index c08fc1a..7f2f413 100644
--- a/metricsd/uploader/upload_service.h
+++ b/metricsd/uploader/upload_service.h
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef METRICS_UPLOADER_UPLOAD_SERVICE_H_
#define METRICS_UPLOADER_UPLOAD_SERVICE_H_
diff --git a/metricsd/uploader/upload_service_test.cc b/metricsd/uploader/upload_service_test.cc
index efd0a56..cbb5277 100644
--- a/metricsd/uploader/upload_service_test.cc
+++ b/metricsd/uploader/upload_service_test.cc
@@ -1,6 +1,18 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+/*
+ * 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 <gtest/gtest.h>
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 30a2851..f853fac 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -2,8 +2,6 @@
#######################################
# init.rc
-# Only copy init.rc if the target doesn't have its own.
-ifneq ($(TARGET_PROVIDES_INIT_RC),true)
include $(CLEAR_VARS)
LOCAL_MODULE := init.rc
@@ -12,7 +10,20 @@
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
include $(BUILD_PREBUILT)
+
+#######################################
+# asan.options
+ifeq (address,$(strip $(SANITIZE_TARGET)))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := asan.options
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_PATH := $(TARGET_OUT)
+
+include $(BUILD_PREBUILT)
endif
+
#######################################
# init.environ.rc
@@ -21,6 +32,11 @@
LOCAL_MODULE := init.environ.rc
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+EXPORT_GLOBAL_ASAN_OPTIONS :=
+ifeq (address,$(strip $(SANITIZE_TARGET)))
+ EXPORT_GLOBAL_ASAN_OPTIONS := export ASAN_OPTIONS include=/system/asan.options
+ LOCAL_REQUIRED_MODULES := asan.options
+endif
# Put it here instead of in init.rc module definition,
# because init.rc is conditionally included.
#
@@ -39,11 +55,6 @@
include $(BUILD_SYSTEM)/base_rules.mk
-EXPORT_GLOBAL_ASAN_OPTIONS :=
-ifeq (address,$(strip $(SANITIZE_TARGET)))
- EXPORT_GLOBAL_ASAN_OPTIONS := export ASAN_OPTIONS allow_user_segv_handler=1:detect_odr_violation=0:alloc_dealloc_mismatch=0
-endif
-
# Regenerate init.environ.rc if PRODUCT_BOOTCLASSPATH has changed.
bcp_md5 := $(word 1, $(shell echo $(PRODUCT_BOOTCLASSPATH) $(PRODUCT_SYSTEM_SERVER_CLASSPATH) | $(MD5SUM)))
bcp_dep := $(intermediates)/$(bcp_md5).bcp.dep
diff --git a/rootdir/asan.options b/rootdir/asan.options
new file mode 100644
index 0000000..2f12341
--- /dev/null
+++ b/rootdir/asan.options
@@ -0,0 +1 @@
+allow_user_segv_handler=1:detect_odr_violation=0:alloc_dealloc_mismatch=0:allocator_may_return_null=1
diff --git a/rootdir/init.rc b/rootdir/init.rc
index b48c72b..5febc60 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -84,10 +84,17 @@
write /proc/sys/kernel/panic_on_oops 1
write /proc/sys/kernel/hung_task_timeout_secs 0
write /proc/cpu/alignment 4
+
+ # scheduler tunables
+ # Disable auto-scaling of scheduler tunables with hotplug. The tunables
+ # will vary across devices in unpredictable ways if allowed to scale with
+ # cpu cores.
+ write /proc/sys/kernel/sched_tunable_scaling 0
write /proc/sys/kernel/sched_latency_ns 10000000
write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
write /proc/sys/kernel/sched_compat_yield 1
write /proc/sys/kernel/sched_child_runs_first 0
+
write /proc/sys/kernel/randomize_va_space 2
write /proc/sys/kernel/kptr_restrict 2
write /proc/sys/vm/mmap_min_addr 32768
@@ -178,8 +185,11 @@
trigger late-init
# Load properties from /system/ + /factory after fs mount.
-on load_all_props_action
- load_all_props
+on load_system_props_action
+ load_system_props
+
+on load_persist_props_action
+ load_persist_props
start logd
start logd-reinit
@@ -192,12 +202,16 @@
trigger early-fs
trigger fs
trigger post-fs
- trigger post-fs-data
# Load properties from /system/ + /factory after fs mount. Place
# this in another action so that the load will be scheduled after the prior
# issued fs triggers have completed.
- trigger load_all_props_action
+ trigger load_system_props_action
+
+ # Now we can mount /data. File encryption requires keymaster to decrypt
+ # /data, which in turn can only be loaded when system properties are present
+ trigger post-fs-data
+ trigger load_persist_props_action
# Remove a file to wake up anything waiting for firmware.
trigger firmware_mounts_complete
@@ -270,7 +284,6 @@
# create basic filesystem structure
mkdir /data/misc 01771 system misc
- mkdir /data/misc/adb 02750 system shell
mkdir /data/misc/bluedroid 02770 bluetooth net_bt_stack
# Fix the access permissions and group ownership for 'bt_config.conf'
chmod 0660 /data/misc/bluedroid/bt_config.conf
@@ -330,7 +343,6 @@
# the following directory.
mkdir /data/mediadrm 0770 mediadrm mediadrm
- mkdir /data/adb 0700 root root
mkdir /data/anr 0775 system system
# symlink to bugreport storage location
@@ -348,6 +360,8 @@
mkdir /data/system/heapdump 0700 system system
mkdir /data/user 0711 system system
+ setusercryptopolicies /data/user
+
# Reload policy from /data/security if present.
setprop selinux.reload_policy 1
@@ -515,17 +529,6 @@
critical
seclabel u:r:ueventd:s0
-service logd /system/bin/logd
- class core
- socket logd stream 0666 logd logd
- socket logdr seqpacket 0666 logd logd
- socket logdw dgram 0222 logd logd
- group root system
-
-service logd-reinit /system/bin/logd --reinit
- oneshot
- disabled
-
service healthd /sbin/healthd
class core
critical
@@ -543,147 +546,10 @@
on property:ro.debuggable=1
start console
-# adbd is controlled via property triggers in init.<platform>.usb.rc
-service adbd /sbin/adbd --root_seclabel=u:r:su:s0
- class core
- socket adbd stream 660 system system
- disabled
- seclabel u:r:adbd:s0
-
-# adbd on at boot in emulator
-on property:ro.kernel.qemu=1
- start adbd
-
-service lmkd /system/bin/lmkd
- class core
- critical
- socket lmkd seqpacket 0660 system system
-
-service servicemanager /system/bin/servicemanager
- class core
- user system
- group system
- critical
- onrestart restart healthd
- onrestart restart zygote
- onrestart restart media
- onrestart restart surfaceflinger
- onrestart restart drm
-
-service vold /system/bin/vold \
- --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
- --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
- class core
- socket vold stream 0660 root mount
- socket cryptd stream 0660 root mount
- ioprio be 2
-
-service netd /system/bin/netd
- class main
- socket netd stream 0660 root system
- socket dnsproxyd stream 0660 root inet
- socket mdns stream 0660 root system
- socket fwmarkd stream 0660 root inet
-
-service debuggerd /system/bin/debuggerd
- class main
-
-service debuggerd64 /system/bin/debuggerd64
- class main
-
-service ril-daemon /system/bin/rild
- class main
- socket rild stream 660 root radio
- socket sap_uim_socket1 stream 660 bluetooth bluetooth
- socket rild-debug stream 660 radio system
- user root
- group radio cache inet misc audio log
-
-service surfaceflinger /system/bin/surfaceflinger
- class core
- user system
- group graphics drmrpc
- onrestart restart zygote
-
-service drm /system/bin/drmserver
- class main
- user drm
- group drm system inet drmrpc
-
-service media /system/bin/mediaserver
- class main
- user media
- group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
- ioprio rt 4
-
-# One shot invocation to deal with encrypted volume.
-service defaultcrypto /system/bin/vdc --wait cryptfs mountdefaultencrypted
- disabled
- oneshot
- # vold will set vold.decrypt to trigger_restart_framework (default
- # encryption) or trigger_restart_min_framework (other encryption)
-
-# One shot invocation to encrypt unencrypted volumes
-service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default
- disabled
- oneshot
- # vold will set vold.decrypt to trigger_restart_framework (default
- # encryption)
-
-service bootanim /system/bin/bootanimation
- class core
- user graphics
- group graphics audio
- disabled
- oneshot
-
-service gatekeeperd /system/bin/gatekeeperd /data/misc/gatekeeper
- class late_start
- user system
-
-service installd /system/bin/installd
- class main
- socket installd stream 600 system system
-
service flash_recovery /system/bin/install-recovery.sh
class main
oneshot
-service racoon /system/bin/racoon
- class main
- socket racoon stream 600 system system
- # IKE uses UDP port 500. Racoon will setuid to vpn after binding the port.
- group vpn net_admin inet
- disabled
- oneshot
-
-service mtpd /system/bin/mtpd
- class main
- socket mtpd stream 600 system system
- user vpn
- group vpn net_admin inet net_raw
- disabled
- oneshot
-
-service keystore /system/bin/keystore /data/misc/keystore
- class main
- user keystore
- group keystore drmrpc
-
-service dumpstate /system/bin/dumpstate -s
- class main
- socket dumpstate stream 0660 shell log
- disabled
- oneshot
-
-service mdnsd /system/bin/mdnsd
- class main
- user mdnsr
- group inet net_raw
- socket mdnsd stream 0660 mdnsr inet
- disabled
- oneshot
-
service uncrypt /system/bin/uncrypt
class main
disabled
@@ -693,22 +559,3 @@
class main
disabled
oneshot
-
-service perfprofd /system/xbin/perfprofd
- class late_start
- user root
- oneshot
-
-on property:persist.logd.logpersistd=logcatd
- # all exec/services are called with umask(077), so no gain beyond 0700
- mkdir /data/misc/logd 0700 logd log
- # logd for write to /data/misc/logd, log group for read from pstore (-L)
- exec - logd log -- /system/bin/logcat -L -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
- start logcatd
-
-service logcatd /system/bin/logcat -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
- class late_start
- disabled
- # logd for write to /data/misc/logd, log group for read from log daemon
- user logd
- group log
diff --git a/rootdir/init.trace.rc b/rootdir/init.trace.rc
index ed4629e..cde9c37 100644
--- a/rootdir/init.trace.rc
+++ b/rootdir/init.trace.rc
@@ -16,6 +16,16 @@
chown root shell /sys/kernel/debug/tracing/events/power/cpu_idle/enable
chown root shell /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
chown root shell /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
+ chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+ chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
+ chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
+ chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
+ chown root shell /sys/kernel/debug/tracing/events/binder/binder_transaction/enable
+ chown root shell /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
+ chown root shell /sys/kernel/debug/tracing/events/binder/binder_lock/enable
+ chown root shell /sys/kernel/debug/tracing/events/binder/binder_locked/enable
+ chown root shell /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
+
chown root shell /sys/kernel/debug/tracing/tracing_on
chmod 0664 /sys/kernel/debug/tracing/trace_clock
@@ -28,7 +38,16 @@
chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
chmod 0664 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
chmod 0664 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
chmod 0664 /sys/kernel/debug/tracing/tracing_on
+ chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_transaction/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_lock/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_locked/enable
+ chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
# Allow only the shell group to read and truncate the kernel trace.
chown root shell /sys/kernel/debug/tracing/trace
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index e290ca4..6482230 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -89,3 +89,34 @@
# when changing the default configuration
on property:persist.sys.usb.config=*
setprop sys.usb.config ${persist.sys.usb.config}
+
+#
+# USB type C
+#
+
+# USB mode changes
+on property:sys.usb.typec.mode=dfp
+ write /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}
+ setprop sys.usb.typec.state ${sys.usb.typec.mode}
+
+on property:sys.usb.typec.mode=ufp
+ write /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}
+ setprop sys.usb.typec.state ${sys.usb.typec.mode}
+
+# USB data role changes
+on property:sys.usb.typec.data_role=device
+ write /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data}
+ setprop sys.usb.typec.state ${sys.usb.typec.data_role}
+
+on property:sys.usb.typec.data_role=host
+ write /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data}
+ setprop sys.usb.typec.state ${sys.usb.typec.data_role}
+
+# USB power role changes
+on property:sys.usb.typec.power_role=source
+ write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power}
+ setprop sys.usb.typec.state ${sys.usb.typec.power_role}
+
+on property:sys.usb.typec.power_role=sink
+ write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power}
+ setprop sys.usb.typec.state ${sys.usb.typec.power_role}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index ae880c3..2ae7ed2 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -42,7 +42,6 @@
getevent \
iftop \
ioctl \
- ionice \
log \
ls \
lsof \
@@ -50,7 +49,6 @@
newfs_msdos \
ps \
prlimit \
- renice \
sendevent \
start \
stop \
diff --git a/toolbox/ionice.c b/toolbox/ionice.c
deleted file mode 100644
index 7abc261..0000000
--- a/toolbox/ionice.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <cutils/iosched_policy.h>
-
-static char *classes[] = {"none", "rt", "be", "idle", NULL};
-
-int ionice_main(int argc, char *argv[])
-{
- IoSchedClass clazz = IoSchedClass_NONE;
- int ioprio = 0;
- int pid;
-
- if(argc != 2 && argc != 4) {
- fprintf(stderr, "usage: ionice <pid> [none|rt|be|idle] [prio]\n");
- return 1;
- }
-
- if (!(pid = atoi(argv[1]))) {
- fprintf(stderr, "Invalid pid specified\n");
- return 1;
- }
-
- if (argc == 2) {
- if (android_get_ioprio(pid, &clazz, &ioprio)) {
- fprintf(stderr, "Failed to read priority (%s)\n", strerror(errno));
- return 1;
- }
- fprintf(stdout, "Pid %d, class %s (%d), prio %d\n", pid, classes[clazz], clazz, ioprio);
- return 0;
- }
-
- if (!strcmp(argv[2], "none")) {
- clazz = IoSchedClass_NONE;
- } else if (!strcmp(argv[2], "rt")) {
- clazz = IoSchedClass_RT;
- } else if (!strcmp(argv[2], "be")) {
- clazz = IoSchedClass_BE;
- } else if (!strcmp(argv[2], "idle")) {
- clazz = IoSchedClass_IDLE;
- } else {
- fprintf(stderr, "Unsupported class '%s'\n", argv[2]);
- return 1;
- }
-
- ioprio = atoi(argv[3]);
-
- printf("Setting pid %d i/o class to %d, prio %d\n", pid, clazz, ioprio);
- if (android_set_ioprio(pid, clazz, ioprio)) {
- fprintf(stderr, "Failed to set priority (%s)\n", strerror(errno));
- return 1;
- }
-
- return 0;
-}
diff --git a/toolbox/lsof.c b/toolbox/lsof.c
index 982f5aa..198ca52 100644
--- a/toolbox/lsof.c
+++ b/toolbox/lsof.c
@@ -29,6 +29,7 @@
* SUCH DAMAGE.
*/
+#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -57,7 +58,7 @@
static void print_header()
{
- printf("%-9s %5s %10s %4s %9s %18s %9s %10s %s\n",
+ printf("%-9s %5s %10s %4s %9s %18s %9s %10s %s\n",
"COMMAND",
"PID",
"USER",
@@ -69,12 +70,12 @@
"NAME");
}
-static void print_type(char *type, struct pid_info_t* info)
+static void print_symlink(const char* name, const char* path, struct pid_info_t* info)
{
static ssize_t link_dest_size;
static char link_dest[PATH_MAX];
- strlcat(info->path, type, sizeof(info->path));
+ strlcat(info->path, path, sizeof(info->path));
if ((link_dest_size = readlink(info->path, link_dest, sizeof(link_dest)-1)) < 0) {
if (errno == ENOENT)
goto out;
@@ -88,9 +89,53 @@
if (!strcmp(link_dest, "/"))
goto out;
- printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n",
- info->cmdline, info->pid, info->user, type,
- "???", "???", "???", "???", link_dest);
+ const char* fd = name;
+ char rw = ' ';
+ char locks = ' '; // TODO: read /proc/locks
+
+ const char* type = "unknown";
+ char device[32] = "?";
+ char size_off[32] = "?";
+ char node[32] = "?";
+
+ struct stat sb;
+ if (lstat(link_dest, &sb) != -1) {
+ switch ((sb.st_mode & S_IFMT)) {
+ case S_IFSOCK: type = "sock"; break; // TODO: what domain?
+ case S_IFLNK: type = "LINK"; break;
+ case S_IFREG: type = "REG"; break;
+ case S_IFBLK: type = "BLK"; break;
+ case S_IFDIR: type = "DIR"; break;
+ case S_IFCHR: type = "CHR"; break;
+ case S_IFIFO: type = "FIFO"; break;
+ }
+ snprintf(device, sizeof(device), "%d,%d", (int) sb.st_dev, (int) sb.st_rdev);
+ snprintf(node, sizeof(node), "%d", (int) sb.st_ino);
+ snprintf(size_off, sizeof(size_off), "%d", (int) sb.st_size);
+ }
+
+ if (!name) {
+ // We're looking at an fd, so read its flags.
+ fd = path;
+ char fdinfo_path[PATH_MAX];
+ snprintf(fdinfo_path, sizeof(fdinfo_path), "/proc/%d/fdinfo/%s", info->pid, path);
+ FILE* fp = fopen(fdinfo_path, "r");
+ if (fp != NULL) {
+ int pos;
+ unsigned flags;
+
+ if (fscanf(fp, "pos: %d flags: %o", &pos, &flags) == 2) {
+ flags &= O_ACCMODE;
+ if (flags == O_RDONLY) rw = 'r';
+ else if (flags == O_WRONLY) rw = 'w';
+ else rw = 'u';
+ }
+ fclose(fp);
+ }
+ }
+
+ printf("%-9s %5d %10s %4s%c%c %9s %18s %9s %10s %s\n",
+ info->cmdline, info->pid, info->user, fd, rw, locks, type, device, size_off, node, link_dest);
out:
info->path[info->parent_length] = '\0';
@@ -111,15 +156,14 @@
if (!maps)
goto out;
- while (fscanf(maps, "%*x-%*x %*s %zx %s %ld %s\n", &offset, device, &inode,
- file) == 4) {
+ while (fscanf(maps, "%*x-%*x %*s %zx %s %ld %s\n", &offset, device, &inode, file) == 4) {
// We don't care about non-file maps
if (inode == 0 || !strcmp(device, "00:00"))
continue;
- printf("%-9s %5d %10s %4s %9s %18s %9zd %10ld %s\n",
+ printf("%-9s %5d %10s %4s %9s %18s %9zd %10ld %s\n",
info->cmdline, info->pid, info->user, "mem",
- "???", device, offset, inode, file);
+ "REG", device, offset, inode, file);
}
fclose(maps);
@@ -141,7 +185,7 @@
if (dir == NULL) {
char msg[BUF_MAX];
snprintf(msg, sizeof(msg), "%s (opendir: %s)", info->path, strerror(errno));
- printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n",
+ printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n",
info->cmdline, info->pid, info->user, "FDS",
"", "", "", "", msg);
goto out;
@@ -152,7 +196,7 @@
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
- print_type(de->d_name, info);
+ print_symlink(NULL, de->d_name, info);
}
closedir(dir);
@@ -207,10 +251,9 @@
strlcpy(info.cmdline, basename(cmdline), sizeof(info.cmdline));
// Read each of these symlinks
- print_type("cwd", &info);
- print_type("exe", &info);
- print_type("root", &info);
-
+ print_symlink("cwd", "cwd", &info);
+ print_symlink("txt", "exe", &info);
+ print_symlink("rtd", "root", &info);
print_fds(&info);
print_maps(&info);
}
diff --git a/toolbox/renice.c b/toolbox/renice.c
deleted file mode 100644
index 99a06f4..0000000
--- a/toolbox/renice.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2008, 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sched.h>
-#include <getopt.h>
-
-static void
-usage(const char *s)
-{
- fprintf(stderr, "USAGE: %s [[-r] [-t TYPE] priority pids ...] [-g pid]\n", s);
- exit(EXIT_FAILURE);
-}
-
-void print_prio(pid_t pid)
-{
- int sched;
- struct sched_param sp;
-
- printf("pid %d's priority: %d\n", pid, getpriority(PRIO_PROCESS, pid));
-
- printf("scheduling class: ");
- sched = sched_getscheduler(pid);
- switch (sched) {
- case SCHED_FIFO:
- printf("FIFO\n");
- break;
- case SCHED_RR:
- printf("RR\n");
- break;
- case SCHED_OTHER:
- printf("Normal\n");
- break;
- case -1:
- perror("sched_getscheduler");
- break;
- default:
- printf("Unknown\n");
- }
-
- sched_getparam(pid, &sp);
- printf("RT prio: %d (of %d to %d)\n", sp.sched_priority,
- sched_get_priority_min(sched), sched_get_priority_max(sched));
-}
-
-int get_sched(char *str)
-{
- if (strcasecmp(str, "RR") == 0)
- return SCHED_RR;
- else if (strcasecmp(str, "FIFO") == 0)
- return SCHED_FIFO;
- else if (strcasecmp(str, "NORMAL") == 0)
- return SCHED_OTHER;
- else if (strcasecmp(str, "OTHER") == 0)
- return SCHED_OTHER;
- return SCHED_RR;
-}
-
-int renice_main(int argc, char *argv[])
-{
- int prio;
- int realtime = 0;
- int opt;
- int sched = SCHED_RR;
- char *cmd = argv[0];
-
- do {
- opt = getopt(argc, argv, "rt:g:");
- if (opt == -1)
- break;
- switch (opt) {
- case 'r':
- // do realtime priority adjustment
- realtime = 1;
- break;
- case 't':
- sched = get_sched(optarg);
- break;
- case 'g':
- print_prio(atoi(optarg));
- return 0;
- default:
- usage(cmd);
- }
- } while (1);
-
- argc -= optind;
- argv += optind;
-
- if (argc < 1)
- usage(cmd);
-
- prio = atoi(argv[0]);
- argc--;
- argv++;
-
- if (argc < 1)
- usage(cmd);
-
- while(argc) {
- pid_t pid;
-
- pid = atoi(argv[0]);
- argc--;
- argv++;
-
- if (realtime) {
- struct sched_param sp = { .sched_priority = prio };
- int ret;
-
- ret = sched_setscheduler(pid, sched, &sp);
- if (ret) {
- perror("sched_set_scheduler");
- exit(EXIT_FAILURE);
- }
- } else {
- int ret;
-
- ret = setpriority(PRIO_PROCESS, pid, prio);
- if (ret) {
- perror("setpriority");
- exit(EXIT_FAILURE);
- }
- }
- }
-
- return 0;
-}