Merge commit '2f169162462e44d7aa6443e682b15fc756c2e4ad' into honeycomb-mr1-release-to-dalvik-dev
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index bd3e4d4..d698133 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -174,6 +174,7 @@
 int           __timer_getoverrun:timer_getoverrun(timer_t)                                              260,262
 int           __timer_delete:timer_delete(timer_t)                                                      261,263
 int           utimes(const char*, const struct timeval tvp[2])                          269, 271
+int           utimensat(int, const char *, const struct timespec times[2], int)         348, 320, 320
 
 # signals
 int     sigaction(int, const struct sigaction *, struct sigaction *)  67
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 5210d6c..e6c84f6 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -124,6 +124,7 @@
 syscall_src += arch-arm/syscalls/__timer_getoverrun.S
 syscall_src += arch-arm/syscalls/__timer_delete.S
 syscall_src += arch-arm/syscalls/utimes.S
+syscall_src += arch-arm/syscalls/utimensat.S
 syscall_src += arch-arm/syscalls/sigaction.S
 syscall_src += arch-arm/syscalls/sigprocmask.S
 syscall_src += arch-arm/syscalls/__sigsuspend.S
diff --git a/libc/arch-arm/syscalls/utimensat.S b/libc/arch-arm/syscalls/utimensat.S
new file mode 100644
index 0000000..ceae7fa
--- /dev/null
+++ b/libc/arch-arm/syscalls/utimensat.S
@@ -0,0 +1,14 @@
+/* autogenerated by gensyscalls.py */
+#include <machine/asm.h>
+#include <sys/linux-syscalls.h>
+
+ENTRY(utimensat)
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_utimensat
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+END(utimensat)
diff --git a/libc/arch-sh/syscalls.mk b/libc/arch-sh/syscalls.mk
index 9575905..1d87600 100644
--- a/libc/arch-sh/syscalls.mk
+++ b/libc/arch-sh/syscalls.mk
@@ -127,6 +127,7 @@
 syscall_src += arch-sh/syscalls/__timer_getoverrun.S
 syscall_src += arch-sh/syscalls/__timer_delete.S
 syscall_src += arch-sh/syscalls/utimes.S
+syscall_src += arch-sh/syscalls/utimensat.S
 syscall_src += arch-sh/syscalls/sigaction.S
 syscall_src += arch-sh/syscalls/sigprocmask.S
 syscall_src += arch-sh/syscalls/__sigsuspend.S
diff --git a/libc/arch-sh/syscalls/utimensat.S b/libc/arch-sh/syscalls/utimensat.S
new file mode 100644
index 0000000..28e7ec6
--- /dev/null
+++ b/libc/arch-sh/syscalls/utimensat.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type utimensat, @function
+    .globl utimensat
+    .align 4
+
+utimensat:
+
+    /* invoke trap */
+    mov.l   0f, r3  /* trap num */
+    trapa   #(4 + 0x10)
+
+    /* check return value */
+    cmp/pz  r0
+    bt      __NR_utimensat_end
+
+    /* keep error number */
+    sts.l   pr, @-r15
+    mov.l   1f, r1
+    jsr     @r1
+    mov     r0, r4
+    lds.l   @r15+, pr
+
+__NR_utimensat_end:
+    rts
+    nop
+
+    .align  2
+0:  .long   __NR_utimensat
+1:  .long   __set_syscall_errno
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index e8c6a77..3b85025 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -127,6 +127,7 @@
 syscall_src += arch-x86/syscalls/__timer_getoverrun.S
 syscall_src += arch-x86/syscalls/__timer_delete.S
 syscall_src += arch-x86/syscalls/utimes.S
+syscall_src += arch-x86/syscalls/utimensat.S
 syscall_src += arch-x86/syscalls/sigaction.S
 syscall_src += arch-x86/syscalls/sigprocmask.S
 syscall_src += arch-x86/syscalls/__sigsuspend.S
diff --git a/libc/arch-x86/syscalls/utimensat.S b/libc/arch-x86/syscalls/utimensat.S
new file mode 100644
index 0000000..e2032b5
--- /dev/null
+++ b/libc/arch-x86/syscalls/utimensat.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type utimensat, @function
+    .globl utimensat
+    .align 4
+
+utimensat:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    pushl   %esi
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
+    mov     32(%esp), %esi
+    movl    $__NR_utimensat, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %esi
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c
index 767baa3..c40950f 100644
--- a/libc/bionic/system_properties.c
+++ b/libc/bionic/system_properties.c
@@ -38,13 +38,14 @@
 #include <sys/select.h>
 #include <sys/types.h>
 #include <netinet/in.h>
+#include <unistd.h>
 
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
 #include <sys/atomics.h>
 
-static const char property_service_name[] = PROP_SERVICE_NAME;
+static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
 
 static unsigned dummy_props = 0;
 
@@ -152,6 +153,114 @@
     }
 }
 
+
+static int send_prop_msg(prop_msg *msg)
+{
+    struct sockaddr_un addr;
+    socklen_t alen;
+    size_t namelen;
+    int s;
+    int r;
+
+    s = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if(s < 0) {
+        return -1;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    namelen = strlen(property_service_socket);
+    strlcpy(addr.sun_path, property_service_socket, sizeof addr.sun_path);
+    addr.sun_family = AF_LOCAL;
+    alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
+
+    if(TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen) < 0)) {
+        close(s);
+        return -1;
+    }
+
+    r = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
+
+    if(r == sizeof(prop_msg)) {
+        r = 0;
+    } else {
+        r = -1;
+    }
+
+    close(s);
+    return r;
+}
+
+int __system_property_set(const char *key, const char *value)
+{
+    unsigned old_serial;
+    volatile unsigned *serial;
+    prop_msg msg;
+    int err;
+    prop_area *pa = __system_property_area__;
+    int tries = 0;
+    int update_seen = 0;
+
+    if(key == 0) return -1;
+    if(value == 0) value = "";
+    if(strlen(key) >= PROP_NAME_MAX) return -1;
+    if(strlen(value) >= PROP_VALUE_MAX) return -1;
+
+    memset(&msg, 0, sizeof msg);
+    msg.cmd = PROP_MSG_SETPROP;
+    strlcpy(msg.name, key, sizeof msg.name);
+    strlcpy(msg.value, value, sizeof msg.value);
+
+    /* Note the system properties serial number before we do our update. */
+    const prop_info *pi = __system_property_find(key);
+    if(pi != NULL) {
+        serial = &pi->serial;
+    } else {
+        serial = &pa->serial;
+    }
+    old_serial = *serial;
+
+    err = send_prop_msg(&msg);
+    if(err < 0) {
+        return err;
+    }
+
+    /**
+     * Wait for the shared memory page to be written back and be
+     * visible in our address space before returning to the caller
+     * who might reasonably expect subsequent reads to match what was
+     * just written.
+     *
+     * Sleep 5 ms after failed checks and only wait up to a 500 ms
+     * total, just in case the system property server fails to update
+     * for whatever reason.
+     */
+    do {
+        struct timespec timeout;
+        timeout.tv_sec = 0;
+        timeout.tv_nsec = 2500000;  // 2.5 ms
+
+        if(tries++ > 0) {
+            usleep(2500); // 2.5 ms
+        }
+        __futex_wait(serial, old_serial, &timeout);
+        if(pi != NULL) {
+            unsigned new_serial = *serial;
+            /* Waiting on a specific prop_info to be updated. */
+            if (old_serial != new_serial && !SERIAL_DIRTY(new_serial)) {
+                update_seen = 1;
+            }
+        } else {
+            /* Waiting for a prop_info to be created. */
+            const prop_info *new_pi = __system_property_find(key);
+            if(new_pi != NULL && !SERIAL_DIRTY(new_pi->serial)) {
+                update_seen = 1;
+            }
+        }
+    } while (!update_seen && tries < 100);
+
+    return 0;
+}
+
 int __system_property_wait(const prop_info *pi)
 {
     unsigned n;
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 5b8e2b4..7b74a4b 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -162,6 +162,7 @@
 #define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 260)
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 261)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 269)
+#define __NR_utimensat                    (__NR_SYSCALL_BASE + 348)
 #define __NR_socket                       (__NR_SYSCALL_BASE + 281)
 #define __NR_socketpair                   (__NR_SYSCALL_BASE + 288)
 #define __NR_bind                         (__NR_SYSCALL_BASE + 282)
@@ -221,6 +222,7 @@
 #define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 262)
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 263)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 271)
+#define __NR_utimensat                    (__NR_SYSCALL_BASE + 320)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 289)
@@ -265,6 +267,7 @@
 #define __NR_timer_getoverrun             (__NR_SYSCALL_BASE + 262)
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 263)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 271)
+#define __NR_utimensat                    (__NR_SYSCALL_BASE + 320)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h
index f706d00..ae9077f 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -138,6 +138,7 @@
 int              __timer_getoverrun (timer_t);
 int              __timer_delete (timer_t);
 int              utimes (const char*, const struct timeval tvp[2]);
+int              utimensat (int, const char *, const struct timespec times[2], int);
 int              sigaction (int, const struct sigaction *, struct sigaction *);
 int              sigprocmask (int, const sigset_t *, sigset_t *);
 int              __sigsuspend (int unused1, int unused2, unsigned mask);
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 091ee6d..87fcfd0 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -103,6 +103,10 @@
 extern int fchmodat(int dirfd, const char *path, mode_t mode, int flags);
 extern int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
 
+# define UTIME_NOW      ((1l << 30) - 1l)
+# define UTIME_OMIT     ((1l << 30) - 2l)
+extern int utimensat (int fd, const char *path, const struct timespec times[2], int flags);
+
 __END_DECLS
 
 #endif /* _SYS_STAT_H_ */
diff --git a/libc/include/sys/system_properties.h b/libc/include/sys/system_properties.h
index 4fdc944..85915b2 100644
--- a/libc/include/sys/system_properties.h
+++ b/libc/include/sys/system_properties.h
@@ -46,6 +46,10 @@
 */
 int __system_property_get(const char *name, char *value);
 
+/* Set a system property by name.
+**/
+int __system_property_set(const char *key, const char *value);
+
 /* Return a pointer to the system property named name, if it
 ** exists, or NULL if there is no such property.  Use 
 ** __system_property_read() to obtain the string value from
diff --git a/libc/kernel/common/linux/usb/f_accessory.h b/libc/kernel/common/linux/usb/f_accessory.h
index 84a8917..7ee9b7f 100644
--- a/libc/kernel/common/linux/usb/f_accessory.h
+++ b/libc/kernel/common/linux/usb/f_accessory.h
@@ -24,15 +24,20 @@
 #define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01
 #define ACCESSORY_STRING_MANUFACTURER 0
 #define ACCESSORY_STRING_MODEL 1
-#define ACCESSORY_STRING_TYPE 2
+#define ACCESSORY_STRING_DESCRIPTION 2
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ACCESSORY_STRING_VERSION 3
+#define ACCESSORY_STRING_URI 4
+#define ACCESSORY_STRING_SERIAL 5
+#define ACCESSORY_GET_PROTOCOL 51
 #define ACCESSORY_SEND_STRING 52
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ACCESSORY_START 53
 #define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256])
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256])
-#define ACCESSORY_GET_STRING_TYPE _IOW('M', 3, char[256])
-#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256])
-#endif
+#define ACCESSORY_GET_STRING_DESCRIPTION _IOW('M', 3, char[256])
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256])
+#define ACCESSORY_GET_STRING_URI _IOW('M', 5, char[256])
+#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256])
+#endif
diff --git a/libc/netbsd/resolv/res_init.c b/libc/netbsd/resolv/res_init.c
index 2158f20..ffd4054 100644
--- a/libc/netbsd/resolv/res_init.c
+++ b/libc/netbsd/resolv/res_init.c
@@ -225,6 +225,9 @@
 	char dnsProperty[PROP_VALUE_MAX];
 #endif
 
+        if ((statp->options & RES_INIT) != 0U)
+                res_ndestroy(statp);
+
 	if (!preinit) {
 		statp->retrans = RES_TIMEOUT;
 		statp->retry = RES_DFLRETRY;
@@ -232,9 +235,6 @@
 		statp->id = res_randomid();
 	}
 
-	if ((statp->options & RES_INIT) != 0U)
-		res_ndestroy(statp);
-
 	memset(u, 0, sizeof(u));
 #ifdef USELOOPBACK
 	u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
diff --git a/libc/netbsd/resolv/res_state.c b/libc/netbsd/resolv/res_state.c
index 3209b6f..322ace9 100644
--- a/libc/netbsd/resolv/res_state.c
+++ b/libc/netbsd/resolv/res_state.c
@@ -38,21 +38,32 @@
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
+/* Set to 1 to enable debug traces */
+#define DEBUG 0
+
+#if DEBUG
+#  include <logd.h>
+#  include <unistd.h>  /* for gettid() */
+#  define D(...)  __libc_android_log_print(ANDROID_LOG_DEBUG,"libc", __VA_ARGS__)
+#else
+#  define D(...)  do{}while(0)
+#endif
+
 static pthread_key_t   _res_key;
 static pthread_once_t  _res_once;
 
 typedef struct {
-    int                    _h_errno;
-    struct __res_state     _nres[1];
-    unsigned               _serial;
-    struct prop_info*      _pi;
-    struct res_static      _rstatic[1];
+    int                  _h_errno;
+    struct __res_state  _nres[1];
+    unsigned             _serial;
+    struct prop_info*   _pi;
+    struct res_static   _rstatic[1];
 } _res_thread;
 
 static _res_thread*
 _res_thread_alloc(void)
 {
-    _res_thread*  rt = malloc(sizeof(*rt));
+    _res_thread*  rt = calloc(1, sizeof(*rt));
 
     if (rt) {
         rt->_h_errno = 0;
@@ -62,12 +73,7 @@
         if (rt->_pi) {
             rt->_serial = rt->_pi->serial;
         }
-        if ( res_ninit( rt->_nres ) < 0 ) {
-            free(rt);
-            rt = NULL;
-        } else {
-            memset(rt->_rstatic, 0, sizeof rt->_rstatic);
-        }
+        memset(rt->_rstatic, 0, sizeof rt->_rstatic);
     }
     return rt;
 }
@@ -91,6 +97,8 @@
 {
     _res_thread*  rt = _rt;
 
+    D("%s: rt=%p for thread=%d", __FUNCTION__, rt, gettid());
+
     _res_static_done(rt->_rstatic);
     res_ndestroy(rt->_nres);
     free(rt);
@@ -108,27 +116,59 @@
     _res_thread*  rt;
     pthread_once( &_res_once, _res_init_key );
     rt = pthread_getspecific( _res_key );
-    if (rt == NULL) {
-        if ((rt = _res_thread_alloc()) == NULL) {
-            return NULL;
+
+    if (rt != NULL) {
+        /* We already have one thread-specific DNS state object.
+         * Check the serial value for any changes to net.* properties */
+        D("%s: Called for tid=%d rt=%p rt->pi=%p rt->serial=%d",
+           __FUNCTION__, gettid(), rt, rt->_pi, rt->_serial);
+        if (rt->_pi == NULL) {
+            /* The property wasn't created when _res_thread_get() was
+             * called the last time. This should only happen very
+             * early during the boot sequence. First, let's try to see if it
+             * is here now. */
+            rt->_pi = (struct prop_info*) __system_property_find("net.change");
+            if (rt->_pi == NULL) {
+                /* Still nothing, return current state */
+                D("%s: exiting for tid=%d rt=%d since system property not found",
+                  __FUNCTION__, gettid(), rt);
+                return rt;
+            }
         }
-        rt->_h_errno = 0;
-        rt->_serial = 0;
-        pthread_setspecific( _res_key, rt );
+        if (rt->_serial == rt->_pi->serial) {
+            /* Nothing changed, so return the current state */
+            D("%s: tid=%d rt=%p nothing changed, returning",
+              __FUNCTION__, gettid(), rt);
+            return rt;
+        }
+        /* Update the recorded serial number, and go reset the state */
+        rt->_serial = rt->_pi->serial;
+        goto RESET_STATE;
     }
-    /* Check the serial value for any chanes to net.* properties. */
-    if (rt->_pi == NULL) {
-        rt->_pi = (struct prop_info*) __system_property_find("net.change");
+
+    /* It is the first time this function is called in this thread,
+     * we need to create a new thread-specific DNS resolver state. */
+    rt = _res_thread_alloc();
+    if (rt == NULL) {
+        return NULL;
     }
-    if (rt->_pi == NULL || rt->_serial == rt->_pi->serial) {
-        return rt;
-    }
-    rt->_serial = rt->_pi->serial;
-    /* Reload from system properties. */
+    pthread_setspecific( _res_key, rt );
+    D("%s: tid=%d Created new DNS state rt=%p",
+      __FUNCTION__, gettid(), rt);
+
+RESET_STATE:
+    /* Reset the state, note that res_ninit() can now properly reset
+     * an existing state without leaking memory.
+     */
+    D("%s: tid=%d, rt=%p, resetting DNS state (options RES_INIT=%d)",
+      __FUNCTION__, gettid(), rt, (rt->_nres->options & RES_INIT) != 0);
     if ( res_ninit( rt->_nres ) < 0 ) {
-        free(rt);
-        rt = NULL;
-        pthread_setspecific( _res_key, rt );
+        /* This should not happen */
+        D("%s: tid=%d rt=%p, woot, res_ninit() returned < 0",
+          __FUNCTION__, gettid(), rt);
+        _res_thread_free(rt);
+        pthread_setspecific( _res_key, NULL );
+        return NULL;
     }
     _resolv_cache_reset(rt->_serial);
     return rt;