Merge "Add ability to have a callback when wakeups happen."
diff --git a/adb/adb.c b/adb/adb.c
index e116414..018dd3c 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -318,6 +318,15 @@
 #endif
 }
 
+static void send_msg_with_okay(int fd, char* msg, size_t msglen) {
+    char header[9];
+    if (msglen > 0xffff)
+        msglen = 0xffff;
+    snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
+    writex(fd, header, 8);
+    writex(fd, msg, msglen);
+}
+
 static void send_connect(atransport *t)
 {
     D("Calling send_connect \n");
@@ -1421,7 +1430,6 @@
 int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
 {
     atransport *transport = NULL;
-    char buf[4096];
 
     if(!strcmp(service, "kill")) {
         fprintf(stderr,"adb server killed by remote request\n");
@@ -1467,13 +1475,11 @@
         char buffer[4096];
         int use_long = !strcmp(service+7, "-l");
         if (use_long || service[7] == 0) {
-            memset(buf, 0, sizeof(buf));
             memset(buffer, 0, sizeof(buffer));
             D("Getting device list \n");
             list_transports(buffer, sizeof(buffer), use_long);
-            snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
             D("Wrote device list \n");
-            writex(reply_fd, buf, strlen(buf));
+            send_msg_with_okay(reply_fd, buffer, strlen(buffer));
             return 0;
         }
     }
@@ -1502,8 +1508,7 @@
             }
         }
 
-        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
-        writex(reply_fd, buf, strlen(buf));
+        send_msg_with_okay(reply_fd, buffer, strlen(buffer));
         return 0;
     }
 
@@ -1511,8 +1516,7 @@
     if (!strcmp(service, "version")) {
         char version[12];
         snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
-        snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version);
-        writex(reply_fd, buf, strlen(buf));
+        send_msg_with_okay(reply_fd, version, strlen(version));
         return 0;
     }
 
@@ -1522,8 +1526,7 @@
        if (transport && transport->serial) {
             out = transport->serial;
         }
-        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
-        writex(reply_fd, buf, strlen(buf));
+        send_msg_with_okay(reply_fd, out, strlen(out));
         return 0;
     }
     if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
@@ -1532,8 +1535,7 @@
        if (transport && transport->devpath) {
             out = transport->devpath;
         }
-        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
-        writex(reply_fd, buf, strlen(buf));
+        send_msg_with_okay(reply_fd, out, strlen(out));
         return 0;
     }
     // indicates a new emulator instance has started
@@ -1547,14 +1549,11 @@
 
     if(!strcmp(service,"list-forward")) {
         // Create the list of forward redirections.
-        char header[9];
         int buffer_size = format_listeners(NULL, 0);
         // Add one byte for the trailing zero.
         char* buffer = malloc(buffer_size+1);
         (void) format_listeners(buffer, buffer_size+1);
-        snprintf(header, sizeof header, "OKAY%04x", buffer_size);
-        writex(reply_fd, header, 8);
-        writex(reply_fd, buffer, buffer_size);
+        send_msg_with_okay(reply_fd, buffer, buffer_size);
         free(buffer);
         return 0;
     }
@@ -1643,8 +1642,7 @@
     if(!strncmp(service,"get-state",strlen("get-state"))) {
         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
         char *state = connection_state_name(transport);
-        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);
-        writex(reply_fd, buf, strlen(buf));
+        send_msg_with_okay(reply_fd, state, strlen(state));
         return 0;
     }
     return -1;
diff --git a/adb/adb_client.c b/adb/adb_client.c
index 586cd7b..1e47486 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -324,7 +324,10 @@
 
     buf[4] = 0;
     n = strtoul(buf, 0, 16);
-    if(n > 1024) goto oops;
+    if(n >= 0xffff) {
+        strcpy(__adb_error, "reply is too long (>= 64kB)");
+        goto oops;
+    }
 
     tmp = malloc(n + 1);
     if(tmp == 0) goto oops;
diff --git a/adb/transport.c b/adb/transport.c
index 6002530..f35880c 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -1188,6 +1188,10 @@
                 D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
                 if (errno == EINTR)
                     continue;
+                if (errno == EAGAIN) {
+                    adb_sleep_ms(1); // just yield some cpu time
+                    continue;
+                }
             } else {
                 D("writex: fd=%d disconnected\n", fd);
             }
diff --git a/include/log/log_read.h b/include/log/log_read.h
index 2601622..7edfe3c 100644
--- a/include/log/log_read.h
+++ b/include/log/log_read.h
@@ -19,21 +19,38 @@
 
 #include <time.h>
 
+/* struct log_time is a wire-format variant of struct timespec */
 #define NS_PER_SEC 1000000000ULL
 #ifdef __cplusplus
-struct log_time : public timespec {
+struct log_time {
 public:
+    uint32_t tv_sec; // good to Feb 5 2106
+    uint32_t tv_nsec;
+
     log_time(const timespec &T)
     {
         tv_sec = T.tv_sec;
         tv_nsec = T.tv_nsec;
     }
+    log_time(const log_time &T)
+    {
+        tv_sec = T.tv_sec;
+        tv_nsec = T.tv_nsec;
+    }
+    log_time(uint32_t sec, uint32_t nsec)
+    {
+        tv_sec = sec;
+        tv_nsec = nsec;
+    }
     log_time()
     {
     }
     log_time(clockid_t id)
     {
-        clock_gettime(id, (timespec *) this);
+        timespec T;
+        clock_gettime(id, &T);
+        tv_sec = T.tv_sec;
+        tv_nsec = T.tv_nsec;
     }
     log_time(const char *T)
     {
@@ -41,6 +58,8 @@
         tv_sec = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
         tv_nsec = c[4] | (c[5] << 8) | (c[6] << 16) | (c[7] << 24);
     }
+
+    // timespec
     bool operator== (const timespec &T) const
     {
         return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec);
@@ -67,13 +86,45 @@
     {
         return !(*this > T);
     }
+
+    // log_time
+    bool operator== (const log_time &T) const
+    {
+        return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec);
+    }
+    bool operator!= (const log_time &T) const
+    {
+        return !(*this == T);
+    }
+    bool operator< (const log_time &T) const
+    {
+        return (tv_sec < T.tv_sec)
+            || ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec));
+    }
+    bool operator>= (const log_time &T) const
+    {
+        return !(*this < T);
+    }
+    bool operator> (const log_time &T) const
+    {
+        return (tv_sec > T.tv_sec)
+            || ((tv_sec == T.tv_sec) && (tv_nsec > T.tv_nsec));
+    }
+    bool operator<= (const log_time &T) const
+    {
+        return !(*this > T);
+    }
+
     uint64_t nsec() const
     {
         return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
     }
-};
+} __attribute__((__packed__));
 #else
-typedef struct timespec log_time;
+typedef struct log_time {
+    uint32_t tv_sec;
+    uint32_t tv_nsec;
+} __attribute__((__packed__)) log_time;
 #endif
 
 #endif /* define _LIBS_LOG_LOG_READ_H */
diff --git a/include/log/logger.h b/include/log/logger.h
index bea0022..8810615 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -30,7 +30,7 @@
     int32_t     sec;    /* seconds since Epoch */
     int32_t     nsec;   /* nanoseconds */
     char        msg[0]; /* the entry's payload */
-};
+} __attribute__((__packed__));
 
 /*
  * The userspace structure for version 2 of the logger_entry ABI.
@@ -46,18 +46,18 @@
     int32_t     nsec;      /* nanoseconds */
     uint32_t    euid;      /* effective UID of logger */
     char        msg[0];    /* the entry's payload */
-};
+} __attribute__((__packed__));
 
 struct logger_entry_v3 {
     uint16_t    len;       /* length of the payload */
-    uint16_t    hdr_size;  /* sizeof(struct logger_entry_v2) */
+    uint16_t    hdr_size;  /* sizeof(struct logger_entry_v3) */
     int32_t     pid;       /* generating process's pid */
     int32_t     tid;       /* generating process's tid */
     int32_t     sec;       /* seconds since Epoch */
     int32_t     nsec;      /* nanoseconds */
     uint32_t    lid;       /* log id of the payload */
     char        msg[0];    /* the entry's payload */
-};
+} __attribute__((__packed__));
 
 /*
  * The maximum size of the log entry payload that can be
diff --git a/include/system/audio.h b/include/system/audio.h
index 294139d..4ccf262 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -602,10 +602,18 @@
 {
     switch (format & AUDIO_FORMAT_MAIN_MASK) {
     case AUDIO_FORMAT_PCM:
-        if (format != AUDIO_FORMAT_PCM_16_BIT &&
-                format != AUDIO_FORMAT_PCM_8_BIT && format != AUDIO_FORMAT_PCM_FLOAT) {
+        switch (format) {
+        case AUDIO_FORMAT_PCM_16_BIT:
+        case AUDIO_FORMAT_PCM_8_BIT:
+        case AUDIO_FORMAT_PCM_32_BIT:
+        case AUDIO_FORMAT_PCM_8_24_BIT:
+        case AUDIO_FORMAT_PCM_FLOAT:
+        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+            return true;
+        default:
             return false;
         }
+        /* not reached */
     case AUDIO_FORMAT_MP3:
     case AUDIO_FORMAT_AMR_NB:
     case AUDIO_FORMAT_AMR_WB:
@@ -633,6 +641,9 @@
     case AUDIO_FORMAT_PCM_8_24_BIT:
         size = sizeof(int32_t);
         break;
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+        size = sizeof(uint8_t) * 3;
+        break;
     case AUDIO_FORMAT_PCM_16_BIT:
         size = sizeof(int16_t);
         break;
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index d3ee167..c3efc33 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -117,8 +117,11 @@
     newVec[0].iov_base   = (unsigned char *) &log_id_buf;
     newVec[0].iov_len    = sizeof_log_id_t;
 
+    struct timespec ts;
+    clock_gettime(CLOCK_REALTIME, &ts);
     log_time realtime_ts;
-    clock_gettime(CLOCK_REALTIME, &realtime_ts);
+    realtime_ts.tv_sec = ts.tv_sec;
+    realtime_ts.tv_nsec = ts.tv_nsec;
 
     newVec[1].iov_base   = (unsigned char *) &realtime_ts;
     newVec[1].iov_len    = sizeof(log_time);
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 19406fb..39fe2ad 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -143,7 +143,7 @@
     for (int j = 0, i = 0; i < iters && j < 10*iters; ++i, ++j) {
         log_time ts;
         LOG_FAILURE_RETRY((
-            clock_gettime(CLOCK_REALTIME, &ts),
+            ts = log_time(CLOCK_REALTIME),
             android_btWriteLog(0, EVENT_TYPE_LONG, &ts, sizeof(ts))));
 
         for (;;) {
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index d71d97a..ffb7fd1 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -171,7 +171,7 @@
 
     ++signaled;
     if ((signal_time.tv_sec == 0) && (signal_time.tv_nsec == 0)) {
-        clock_gettime(CLOCK_MONOTONIC, &signal_time);
+        signal_time = log_time(CLOCK_MONOTONIC);
         signal_time.tv_sec += 2;
     }
 
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index c24384c..484cf50 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -34,7 +34,7 @@
 	col32cb16blend.S \
 	t32cb16blend.S \
 
-ifeq ($(ARCH_ARM_HAVE_NEON),armv7-a)
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
 PIXELFLINGER_SRC_FILES_arm += col32cb16blend_neon.S
 endif
 
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index cb2b811..f84a28a 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -26,6 +26,10 @@
 #include <cutils/memory.h>
 #include <cutils/log.h>
 
+#ifdef __arm__
+#include <machine/cpu-features.h>
+#endif
+
 #include "buffer.h"
 #include "scanline.h"
 
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 7340a36..c5760f7 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -36,7 +36,7 @@
     pthread_mutex_init(&mLogElementsLock, NULL);
 }
 
-void LogBuffer::log(log_id_t log_id, struct timespec realtime,
+void LogBuffer::log(log_id_t log_id, log_time realtime,
                     uid_t uid, pid_t pid, const char *msg,
                     unsigned short len) {
     if ((log_id >= LOG_ID_MAX) || (log_id < 0)) {
@@ -182,8 +182,8 @@
     return LOG_BUFFER_SIZE;
 }
 
-struct timespec LogBuffer::flushTo(
-        SocketClient *reader, const struct timespec start, bool privileged,
+log_time LogBuffer::flushTo(
+        SocketClient *reader, const log_time start, bool privileged,
         bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
     LogBufferElementCollection::iterator it;
     log_time max = start;
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 7c69f1b..1b50a8f 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -40,12 +40,12 @@
 
     LogBuffer(LastLogTimes *times);
 
-    void log(log_id_t log_id, struct timespec realtime,
+    void log(log_id_t log_id, log_time realtime,
              uid_t uid, pid_t pid, const char *msg, unsigned short len);
-    struct timespec flushTo(SocketClient *writer, const struct timespec start,
-                            bool privileged,
-                            bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
-                            void *arg = NULL);
+    log_time flushTo(SocketClient *writer, const log_time start,
+                     bool privileged,
+                     bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
+                     void *arg = NULL);
 
     void clear(log_id_t id);
     unsigned long getSize(log_id_t id);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 1c55623..01cc9de 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -24,9 +24,11 @@
 #include "LogBufferElement.h"
 #include "LogReader.h"
 
-const struct timespec LogBufferElement::FLUSH_ERROR = { 0, 0 };
+const log_time LogBufferElement::FLUSH_ERROR(0, 0);
 
-LogBufferElement::LogBufferElement(log_id_t log_id, struct timespec realtime, uid_t uid, pid_t pid, const char *msg, unsigned short len)
+LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
+                                   uid_t uid, pid_t pid, const char *msg,
+                                   unsigned short len)
         : mLogId(log_id)
         , mUid(uid)
         , mPid(pid)
@@ -41,7 +43,7 @@
     delete [] mMsg;
 }
 
-struct timespec LogBufferElement::flushTo(SocketClient *reader) {
+log_time LogBufferElement::flushTo(SocketClient *reader) {
     struct logger_entry_v3 entry;
     memset(&entry, 0, sizeof(struct logger_entry_v3));
     entry.hdr_size = sizeof(struct logger_entry_v3);
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 390c97c..1da09ae 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -32,7 +32,7 @@
     const log_time mRealTime;
 
 public:
-    LogBufferElement(log_id_t log_id, struct timespec realtime,
+    LogBufferElement(log_id_t log_id, log_time realtime,
                      uid_t uid, pid_t pid, const char *msg, unsigned short len);
     virtual ~LogBufferElement();
 
@@ -43,8 +43,8 @@
     log_time getMonotonicTime(void) const { return mMonotonicTime; }
     log_time getRealTime(void) const { return mRealTime; }
 
-    static const struct timespec FLUSH_ERROR;
-    struct timespec flushTo(SocketClient *writer);
+    static const log_time FLUSH_ERROR;
+    log_time flushTo(SocketClient *writer);
 };
 
 #endif