Merge "Improve top(1) compatibility and interactive usefulness."
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index d811b24..8d3501e 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -55,7 +55,7 @@
ADBAPIHANDLE adb_write_pipe;
/// Interface name
- char* interface_name;
+ wchar_t* interface_name;
/// Mask for determining when to use zero length packets
unsigned zero_mask;
@@ -74,11 +74,11 @@
ADB_MUTEX_DEFINE( usb_lock );
/// Checks if there is opened usb handle in handle_list for this device.
-int known_device(const char* dev_name);
+int known_device(const wchar_t* dev_name);
/// Checks if there is opened usb handle in handle_list for this device.
/// usb_lock mutex must be held before calling this routine.
-int known_device_locked(const char* dev_name);
+int known_device_locked(const wchar_t* dev_name);
/// Registers opened usb handle (adds it to handle_list).
int register_new_device(usb_handle* handle);
@@ -118,7 +118,7 @@
/// Closes opened usb handle
int usb_close(usb_handle* handle);
-int known_device_locked(const char* dev_name) {
+int known_device_locked(const wchar_t* dev_name) {
usb_handle* usb;
if (NULL != dev_name) {
@@ -126,7 +126,7 @@
for(usb = handle_list.next; usb != &handle_list; usb = usb->next) {
// In Windows names are not case sensetive!
if((NULL != usb->interface_name) &&
- (0 == stricmp(usb->interface_name, dev_name))) {
+ (0 == wcsicmp(usb->interface_name, dev_name))) {
return 1;
}
}
@@ -135,7 +135,7 @@
return 0;
}
-int known_device(const char* dev_name) {
+int known_device(const wchar_t* dev_name) {
int ret = 0;
if (NULL != dev_name) {
@@ -316,17 +316,16 @@
AdbGetInterfaceName(ret->adb_interface,
NULL,
&name_len,
- true);
+ false);
if (0 == name_len) {
D("AdbGetInterfaceName returned name length of zero: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
}
- ret->interface_name = (char*)malloc(name_len);
+ ret->interface_name = (wchar_t*)malloc(name_len * sizeof(ret->interface_name[0]));
if (NULL == ret->interface_name) {
- D("Could not allocate %lu bytes for interface_name: %s", name_len,
- strerror(errno));
+ D("Could not allocate %lu characters for interface_name: %s", name_len, strerror(errno));
goto fail;
}
@@ -334,7 +333,7 @@
if (!AdbGetInterfaceName(ret->adb_interface,
ret->interface_name,
&name_len,
- true)) {
+ false)) {
D("AdbGetInterfaceName failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
@@ -581,12 +580,10 @@
}
void find_devices() {
- usb_handle* handle = NULL;
+ usb_handle* handle = NULL;
char entry_buffer[2048];
- char interf_name[2048];
AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
unsigned long entry_buffer_size = sizeof(entry_buffer);
- char* copy_name;
// Enumerate all present and active interfaces.
ADBAPIHANDLE enum_handle =
@@ -599,25 +596,21 @@
}
while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
- // TODO: FIXME - temp hack converting wchar_t into char.
- // It would be better to change AdbNextInterface so it will return
- // interface name as single char string.
- const wchar_t* wchar_name = next_interface->device_name;
- for(copy_name = interf_name;
- L'\0' != *wchar_name;
- wchar_name++, copy_name++) {
- *copy_name = (char)(*wchar_name);
- }
- *copy_name = '\0';
-
// Lets see if we already have this device in the list
- if (!known_device(interf_name)) {
+ if (!known_device(next_interface->device_name)) {
// This seems to be a new device. Open it!
- handle = do_usb_open(next_interface->device_name);
- if (NULL != handle) {
+ handle = do_usb_open(next_interface->device_name);
+ if (NULL != handle) {
// Lets see if this interface (device) belongs to us
if (recognized_device(handle)) {
- D("adding a new device %s", interf_name);
+ D("adding a new device %ls", next_interface->device_name);
+
+ // We don't request a wchar_t string from AdbGetSerialNumber() because of a bug in
+ // adb_winusb_interface.cpp:CopyMemory(buffer, ser_num->bString, bytes_written) where the
+ // last parameter should be (str_len * sizeof(wchar_t)). The bug reads 2 bytes past the
+ // end of a stack buffer in the best case, and in the unlikely case of a long serial
+ // number, it will read 2 bytes past the end of a heap allocation. This doesn't affect the
+ // resulting string, but we should avoid the bad reads in the first place.
char serial_number[512];
unsigned long serial_number_len = sizeof(serial_number);
if (AdbGetSerialNumber(handle->adb_interface,
@@ -628,7 +621,7 @@
if (register_new_device(handle)) {
register_usb_transport(handle, serial_number, NULL, 1);
} else {
- D("register_new_device failed for %s", interf_name);
+ D("register_new_device failed for %ls", next_interface->device_name);
usb_cleanup_handle(handle);
free(handle);
}
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index cb77a8e..63904b6 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -136,6 +136,9 @@
{ "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB },
{ "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
{ NULL, 0 },
};
diff --git a/include/log/log.h b/include/log/log.h
index 1cdf7bc..e0dc3a3 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -616,7 +616,12 @@
* Use the per-tag properties "log.tag.<tagname>" to generate a runtime
* result of non-zero to expose a log.
*/
-int __android_log_is_loggable(int prio, const char *tag, int def);
+/* default prio ANDROID_LOG_VERBOSE to ANDROID_LOG_FATAL if no property */
+#define ANDROID_LOGGABLE_FLAG_DEFAULT_MASK 0x000F
+/* Save 2 syscalls if caller guarantees to never call within signal handler */
+#define ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL 0x8000
+
+int __android_log_is_loggable(int prio, const char *tag, int flag);
int __android_log_error_write(int tag, const char *subTag, int32_t uid, const char *data,
uint32_t dataLen);
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index 8a8ece2..fcdb6c9 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -24,6 +24,7 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
@@ -97,18 +98,33 @@
*/
static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER;
-static void lock()
+static void lock(sigset_t *sigflags)
{
+ /*
+ * If we trigger a signal handler in the middle of locked activity and the
+ * signal handler logs a message, we could get into a deadlock state.
+ */
+ sigset_t all;
+
+ sigfillset(&all);
+ pthread_sigmask(SIG_BLOCK, &all, sigflags);
pthread_mutex_lock(&fakeLogDeviceLock);
}
-static void unlock()
+static void unlock(sigset_t *sigflags)
{
pthread_mutex_unlock(&fakeLogDeviceLock);
+ pthread_sigmask(SIG_UNBLOCK, sigflags, NULL);
}
+
+#define DECLARE_SIGSET(name) sigset_t name
+
#else // !defined(_WIN32)
-#define lock() ((void)0)
-#define unlock() ((void)0)
+
+#define lock(sigflags) ((void)0)
+#define unlock(sigflags) ((void)0)
+#define DECLARE_SIGSET(name)
+
#endif // !defined(_WIN32)
@@ -154,8 +170,9 @@
static void deleteFakeFd(int fd)
{
LogState *ls;
+ DECLARE_SIGSET(sigflags);
- lock();
+ lock(&sigflags);
ls = fdToLogState(fd);
if (ls != NULL) {
@@ -164,7 +181,7 @@
free(ls);
}
- unlock();
+ unlock(&sigflags);
}
/*
@@ -548,12 +565,13 @@
static ssize_t logWritev(int fd, const struct iovec* vector, int count)
{
LogState* state;
+ DECLARE_SIGSET(sigflags);
/* Make sure that no-one frees the LogState while we're using it.
* Also guarantees that only one thread is in showLog() at a given
* time (if it matters).
*/
- lock();
+ lock(&sigflags);
state = fdToLogState(fd);
if (state == NULL) {
@@ -598,10 +616,10 @@
}
bail:
- unlock();
+ unlock(&sigflags);
return vector[0].iov_len + vector[1].iov_len + vector[2].iov_len;
error:
- unlock();
+ unlock(&sigflags);
return -1;
}
@@ -621,8 +639,9 @@
{
LogState *logState;
int fd = -1;
+ DECLARE_SIGSET(sigflags);
- lock();
+ lock(&sigflags);
logState = createLogState();
if (logState != NULL) {
@@ -632,7 +651,7 @@
errno = ENFILE;
}
- unlock();
+ unlock(&sigflags);
return fd;
}
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 814d96d..9d043ff 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -16,12 +16,39 @@
#include <ctype.h>
#include <pthread.h>
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#include <android/log.h>
+#include <log/log.h>
+
+static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
+
+static void lock(sigset_t *sigflags)
+{
+ /*
+ * If we trigger a signal handler in the middle of locked activity and the
+ * signal handler logs a message, we could get into a deadlock state.
+ */
+ if (sigflags) {
+ sigset_t all;
+
+ sigfillset(&all);
+ pthread_sigmask(SIG_BLOCK, &all, sigflags);
+ }
+ pthread_mutex_lock(&lock_loggable);
+}
+
+static void unlock(sigset_t *sigflags)
+{
+ pthread_mutex_unlock(&lock_loggable);
+ if (sigflags) {
+ pthread_sigmask(SIG_UNBLOCK, sigflags, NULL);
+ }
+}
struct cache {
const prop_info *pinfo;
@@ -49,9 +76,7 @@
cache->c = buf[0];
}
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
-static int __android_log_level(const char *tag, int def)
+static int __android_log_level(const char *tag, int flag)
{
/* sizeof() is used on this array below */
static const char log_namespace[] = "persist.log.tag.";
@@ -83,10 +108,11 @@
{ NULL, -1, 0 },
{ NULL, -1, 0 }
};
+ sigset_t sigflags;
strcpy(key, log_namespace);
- pthread_mutex_lock(&lock);
+ lock((flag & ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL) ? NULL : &sigflags);
current_global_serial = __system_property_area_serial();
@@ -156,7 +182,7 @@
global_serial = current_global_serial;
- pthread_mutex_unlock(&lock);
+ unlock((flag & ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL) ? NULL : &sigflags);
switch (toupper(c)) {
case 'V': return ANDROID_LOG_VERBOSE;
@@ -168,36 +194,46 @@
case 'A': return ANDROID_LOG_FATAL;
case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
}
- return def;
+ return flag & ANDROID_LOGGABLE_FLAG_DEFAULT_MASK;
}
-int __android_log_is_loggable(int prio, const char *tag, int def)
+int __android_log_is_loggable(int prio, const char *tag, int flag)
{
- int logLevel = __android_log_level(tag, def);
+ int logLevel = __android_log_level(tag, flag);
return logLevel >= 0 && prio >= logLevel;
}
+/*
+ * Timestamp state generally remains constant, since a change is
+ * rare, we can accept a trylock failure gracefully.
+ */
+static pthread_mutex_t lock_timestamp = PTHREAD_MUTEX_INITIALIZER;
+
char android_log_timestamp()
{
static struct cache r_time_cache = { NULL, -1, 0 };
static struct cache p_time_cache = { NULL, -1, 0 };
- static uint32_t serial;
- uint32_t current_serial;
char retval;
- pthread_mutex_lock(&lock);
+ if (pthread_mutex_trylock(&lock_timestamp)) {
+ /* We are willing to accept some race in this context */
+ if (!(retval = p_time_cache.c)) {
+ retval = r_time_cache.c;
+ }
+ } else {
+ static uint32_t serial;
+ uint32_t current_serial = __system_property_area_serial();
+ if (current_serial != serial) {
+ refresh_cache(&r_time_cache, "ro.logd.timestamp");
+ refresh_cache(&p_time_cache, "persist.logd.timestamp");
+ serial = current_serial;
+ }
+ if (!(retval = p_time_cache.c)) {
+ retval = r_time_cache.c;
+ }
- current_serial = __system_property_area_serial();
- if (current_serial != serial) {
- refresh_cache(&r_time_cache, "ro.logd.timestamp");
- refresh_cache(&p_time_cache, "persist.logd.timestamp");
- serial = current_serial;
+ pthread_mutex_unlock(&lock_timestamp);
}
- if (!(retval = p_time_cache.c)) {
- retval = r_time_cache.c;
- }
-
- pthread_mutex_unlock(&lock);
return tolower(retval ?: 'r');
}
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index a4310ae..a8ecc8d 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -20,6 +20,7 @@
#include <fcntl.h>
#if !defined(_WIN32)
#include <pthread.h>
+#include <signal.h>
#endif
#include <stdarg.h>
#include <stdatomic.h>
@@ -54,14 +55,43 @@
static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
-#if !defined(_WIN32)
-static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
+#if !defined(_WIN32)
+static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static void lock(sigset_t *sigflags)
+{
+ /*
+ * If we trigger a signal handler in the middle of locked activity and the
+ * signal handler logs a message, we could get into a deadlock state.
+ */
+ sigset_t all;
+
+ sigfillset(&all);
+ pthread_sigmask(SIG_BLOCK, &all, sigflags);
+ pthread_mutex_lock(&log_init_lock);
+}
+
+static void unlock(sigset_t *sigflags)
+{
+ pthread_mutex_unlock(&log_init_lock);
+ pthread_sigmask(SIG_UNBLOCK, sigflags, NULL);
+}
+
+#define DECLARE_SIGSET(name) sigset_t name
+
+#else /* !defined(_WIN32) */
+
+#define lock(sigflags) ((void)0)
+#define unlock(sigflags) ((void)0)
+#define DECLARE_SIGSET(name)
+
+#endif /* !defined(_WIN32) */
+
#if FAKE_LOG_DEVICE
static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
#else
@@ -275,17 +305,15 @@
*/
ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
if (ret < 0) {
+ DECLARE_SIGSET(sigflags);
+
ret = -errno;
if (ret == -ENOTCONN) {
-#if !defined(_WIN32)
- pthread_mutex_lock(&log_init_lock);
-#endif
+ lock(&sigflags);
close(logd_fd);
logd_fd = -1;
ret = __write_to_log_initialize();
-#if !defined(_WIN32)
- pthread_mutex_unlock(&log_init_lock);
-#endif
+ unlock(&sigflags);
if (ret < 0) {
return ret;
@@ -329,18 +357,16 @@
static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
{
-#if !defined(_WIN32)
- pthread_mutex_lock(&log_init_lock);
-#endif
+ DECLARE_SIGSET(sigflags);
+
+ lock(&sigflags);
if (write_to_log == __write_to_log_init) {
int ret;
ret = __write_to_log_initialize();
if (ret < 0) {
-#if !defined(_WIN32)
- pthread_mutex_unlock(&log_init_lock);
-#endif
+ unlock(&sigflags);
#if (FAKE_LOG_DEVICE == 0)
if (pstore_fd >= 0) {
__write_to_log_daemon(log_id, vec, nr);
@@ -352,9 +378,7 @@
write_to_log = __write_to_log_daemon;
}
-#if !defined(_WIN32)
- pthread_mutex_unlock(&log_init_lock);
-#endif
+ unlock(&sigflags);
return write_to_log(log_id, vec, nr);
}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index fd5c066..c2f71d1 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -191,7 +191,9 @@
prio = *msg;
tag = msg + 1;
}
- if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
+ if (!__android_log_is_loggable(prio, tag,
+ ANDROID_LOG_VERBOSE |
+ ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL)) {
// Log traffic received to total
pthread_mutex_lock(&mLogElementsLock);
stats.add(elem);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index c4c302b..f10dccf 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -107,7 +107,9 @@
LogBuffer *parent) {
static const char tag[] = "chatty";
- if (!__android_log_is_loggable(ANDROID_LOG_INFO, tag, ANDROID_LOG_VERBOSE)) {
+ if (!__android_log_is_loggable(ANDROID_LOG_INFO, tag,
+ ANDROID_LOG_VERBOSE |
+ ANDROID_LOGGABLE_FLAG_NOT_WITHIN_SIGNAL)) {
return 0;
}
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index da5e78d..2a3f52f 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -582,7 +582,7 @@
// Some may view the following as an ugly heuristic, the desire is to
// beautify the kernel logs into an Android Logging format; the goal is
// admirable but costly.
- while ((isspace(*p) || !*p) && (p < &buf[len])) {
+ while ((p < &buf[len]) && (isspace(*p) || !*p)) {
++p;
}
if (p >= &buf[len]) { // timestamp, no content
@@ -596,7 +596,7 @@
const char *bt, *et, *cp;
bt = p;
- if (!fast<strncmp>(p, "[INFO]", 6)) {
+ if ((taglen >= 6) && !fast<strncmp>(p, "[INFO]", 6)) {
// <PRI>[<TIME>] "[INFO]"<tag> ":" message
bt = p + 6;
taglen -= 6;
@@ -620,7 +620,9 @@
p = cp + 1;
} else if (taglen) {
size = et - bt;
- if ((*bt == *cp) && fast<strncmp>(bt + 1, cp + 1, size - 1)) {
+ if ((taglen > size) && // enough space for match plus trailing :
+ (*bt == *cp) && // ubber fast<strncmp> pair
+ fast<strncmp>(bt + 1, cp + 1, size - 1)) {
// <PRI>[<TIME>] <tag>_host '<tag>.<num>' : message
if (!fast<strncmp>(bt + size - 5, "_host", 5)
&& !fast<strncmp>(bt + 1, cp + 1, size - 6)) {
@@ -694,7 +696,7 @@
p = cp + 1;
}
}
- }
+ } /* else no tag */
size = etag - tag;
if ((size <= 1)
// register names like x9
@@ -721,8 +723,12 @@
taglen = mp - tag;
}
}
+ // Deal with sloppy and simplistic harmless p = cp + 1 etc above.
+ if (len < (size_t)(p - buf)) {
+ p = &buf[len];
+ }
// skip leading space
- while ((isspace(*p) || !*p) && (p < &buf[len])) {
+ while ((p < &buf[len]) && (isspace(*p) || !*p)) {
++p;
}
// truncate trailing space or nuls
@@ -735,16 +741,26 @@
p = " ";
b = 1;
}
+ // paranoid sanity check, can not happen ...
if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
b = LOGGER_ENTRY_MAX_PAYLOAD;
}
+ if (taglen > LOGGER_ENTRY_MAX_PAYLOAD) {
+ taglen = LOGGER_ENTRY_MAX_PAYLOAD;
+ }
+ // calculate buffer copy requirements
size_t n = 1 + taglen + 1 + b + 1;
- int rc = n;
- if ((taglen > n) || (b > n)) { // Can not happen ...
- rc = -EINVAL;
- return rc;
+ // paranoid sanity check, first two just can not happen ...
+ if ((taglen > n) || (b > n) || (n > USHRT_MAX)) {
+ return -EINVAL;
}
+ // Careful.
+ // We are using the stack to house the log buffer for speed reasons.
+ // If we malloc'd this buffer, we could get away without n's USHRT_MAX
+ // test above, but we would then required a max(n, USHRT_MAX) as
+ // truncating length argument to logbuf->log() below. Gain is protection
+ // of stack sanity and speedup, loss is truncated long-line content.
char newstr[n];
char *np = newstr;
@@ -763,8 +779,8 @@
np[b] = '\0';
// Log message
- rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr,
- (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+ int rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr,
+ (unsigned short) n);
// notify readers
if (!rc) {