Merge "Teach the mount command in init to not consider a wiped partition to be encrypted."
diff --git a/include/cutils/config_utils.h b/include/cutils/config_utils.h
index f3fb370..2dea6f1 100644
--- a/include/cutils/config_utils.h
+++ b/include/cutils/config_utils.h
@@ -54,6 +54,9 @@
 /* add a named child to a config node (or modify it if it already exists) */
 void config_set(cnode *root, const char *name, const char *value);
 
+/* free a config node tree */
+void config_free(cnode *root);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index aa8682e..19cae0c 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 
 #ifdef HAVE_WINSOCK
 #include <winsock2.h>
@@ -92,7 +93,18 @@
         const char *name, int namespaceId, int type);
 extern int socket_local_client(const char *name, int namespaceId, int type);
 extern int socket_inaddr_any_server(int port, int type);
-    
+
+/*
+ * socket_peer_is_trusted - Takes a socket which is presumed to be a
+ * connected local socket (e.g. AF_LOCAL) and returns whether the peer
+ * (the userid that owns the process on the other end of that socket)
+ * is one of the two trusted userids, root or shell.
+ *
+ * Note: This only works as advertised on the Android OS and always
+ * just returns true when called on other operating systems.
+ */
+extern bool socket_peer_is_trusted(int fd);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/cutils/uevent.h b/include/cutils/uevent.h
index 587149c..5f5e6ca 100644
--- a/include/cutils/uevent.h
+++ b/include/cutils/uevent.h
@@ -23,7 +23,7 @@
 extern "C" {
 #endif
 
-ssize_t uevent_checked_recv(int socket, void *buffer, size_t length);
+ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length);
 
 #ifdef __cplusplus
 }
diff --git a/include/system/audio.h b/include/system/audio.h
index 8f2ac0c..3294500 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -88,8 +88,10 @@
 
 /* PCM sub formats */
 typedef enum {
-    AUDIO_FORMAT_PCM_SUB_16_BIT          = 0x1, /* DO NOT CHANGE */
-    AUDIO_FORMAT_PCM_SUB_8_BIT           = 0x2, /* DO NOT CHANGE */
+    AUDIO_FORMAT_PCM_SUB_16_BIT          = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
+    AUDIO_FORMAT_PCM_SUB_8_BIT           = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
+    AUDIO_FORMAT_PCM_SUB_32_BIT          = 0x3, /* PCM signed .31 fixed point */
+    AUDIO_FORMAT_PCM_SUB_8_24_BIT        = 0x4, /* PCM signed 7.24 fixed point */
 } audio_format_pcm_sub_fmt_t;
 
 /* MP3 sub format field definition : can use 11 LSBs in the same way as MP3
@@ -144,6 +146,10 @@
                                         AUDIO_FORMAT_PCM_SUB_16_BIT),
     AUDIO_FORMAT_PCM_8_BIT           = (AUDIO_FORMAT_PCM |
                                         AUDIO_FORMAT_PCM_SUB_8_BIT),
+    AUDIO_FORMAT_PCM_32_BIT          = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_32_BIT),
+    AUDIO_FORMAT_PCM_8_24_BIT        = (AUDIO_FORMAT_PCM |
+                                        AUDIO_FORMAT_PCM_SUB_8_24_BIT),
 } audio_format_t;
 
 /* Channel mask definitions must be kept in sync with JAVA values in
diff --git a/init/devices.c b/init/devices.c
index a200c95..60659ce 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -774,7 +774,7 @@
 {
     char msg[UEVENT_MSG_LEN+2];
     int n;
-    while ((n = uevent_checked_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
+    while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
         if(n >= UEVENT_MSG_LEN)   /* overflow -- discard */
             continue;
 
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 8ee4c9a..29864b2 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -35,6 +35,7 @@
 	socket_loopback_client.c \
 	socket_loopback_server.c \
 	socket_network_client.c \
+	sockets.c \
 	config_utils.c \
 	cpu_info.c \
 	load_file.c \
diff --git a/libcutils/config_utils.c b/libcutils/config_utils.c
index 75fa6c6..fc5ca78 100644
--- a/libcutils/config_utils.c
+++ b/libcutils/config_utils.c
@@ -315,3 +315,15 @@
     data = load_file(fn, 0);
     config_load(root, data);
 }
+
+void config_free(cnode *root)
+{
+    cnode *cur = root->first_child;
+
+    while (cur) {
+        cnode *prev = cur;
+        config_free(cur);
+        cur = cur->next;
+        free(prev);
+    }
+}
diff --git a/libcutils/sockets.c b/libcutils/sockets.c
new file mode 100644
index 0000000..101a382
--- /dev/null
+++ b/libcutils/sockets.c
@@ -0,0 +1,44 @@
+/*
+ * 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 <cutils/log.h>
+#include <cutils/sockets.h>
+
+#ifdef HAVE_ANDROID_OS
+/* For the socket trust (credentials) check */
+#include <private/android_filesystem_config.h>
+#endif
+
+bool socket_peer_is_trusted(int fd)
+{
+#ifdef HAVE_ANDROID_OS
+    struct ucred cr;
+    socklen_t len = sizeof(cr);
+    int n = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
+
+    if (n != 0) {
+        LOGE("could not get socket credentials: %s\n", strerror(errno));
+        return false;
+    }
+
+    if ((cr.uid != AID_ROOT) && (cr.uid != AID_SHELL)) {
+        LOGE("untrusted userid on other end of socket: userid %d\n", cr.uid);
+        return false;
+    }
+#endif
+
+    return true;
+}
diff --git a/libcutils/uevent.c b/libcutils/uevent.c
index 3533c00..320f8d1 100644
--- a/libcutils/uevent.c
+++ b/libcutils/uevent.c
@@ -24,7 +24,7 @@
 /**
  * Like recv(), but checks that messages actually originate from the kernel.
  */
-ssize_t uevent_checked_recv(int socket, void *buffer, size_t length) {
+ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) {
     struct iovec iov = { buffer, length };
     struct sockaddr_nl addr;
     char control[CMSG_SPACE(sizeof(struct ucred))];
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 2e3df00..208402c 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -51,6 +51,8 @@
 static int ifc_ctl_sock6 = -1;
 void printerr(char *fmt, ...);
 
+#define DBG 0
+
 in_addr_t prefixLengthToIpv4Netmask(int prefix_length)
 {
     in_addr_t mask = 0;
@@ -88,13 +90,17 @@
 
 int ifc_init(void)
 {
+    int ret;
     if (ifc_ctl_sock == -1) {
-        ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);    
+        ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
         if (ifc_ctl_sock < 0) {
             printerr("socket() failed: %s\n", strerror(errno));
         }
     }
-    return ifc_ctl_sock < 0 ? -1 : 0;
+
+    ret = ifc_ctl_sock < 0 ? -1 : 0;
+    if (DBG) printerr("ifc_init_returning %d", ret);
+    return ret;
 }
 
 int ifc_init6(void)
@@ -110,6 +116,7 @@
 
 void ifc_close(void)
 {
+    if (DBG) printerr("ifc_close");
     if (ifc_ctl_sock != -1) {
         (void)close(ifc_ctl_sock);
         ifc_ctl_sock = -1;
@@ -141,7 +148,7 @@
     if(r < 0) return -1;
 
     memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
-    return 0;    
+    return 0;
 }
 
 int ifc_get_ifindex(const char *name, int *if_indexp)
@@ -169,12 +176,16 @@
 
 int ifc_up(const char *name)
 {
-    return ifc_set_flags(name, IFF_UP, 0);
+    int ret = ifc_set_flags(name, IFF_UP, 0);
+    if (DBG) printerr("ifc_up(%s) = %d", name, ret);
+    return ret;
 }
 
 int ifc_down(const char *name)
 {
-    return ifc_set_flags(name, 0, IFF_UP);
+    int ret = ifc_set_flags(name, 0, IFF_UP);
+    if (DBG) printerr("ifc_down(%s) = %d", name, ret);
+    return ret;
 }
 
 static void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr)
@@ -188,11 +199,14 @@
 int ifc_set_addr(const char *name, in_addr_t addr)
 {
     struct ifreq ifr;
+    int ret;
 
     ifc_init_ifr(name, &ifr);
     init_sockaddr_in(&ifr.ifr_addr, addr);
 
-    return ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
+    ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
+    if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret);
+    return ret;
 }
 
 int ifc_set_hwaddr(const char *name, const void *ptr)
@@ -209,11 +223,14 @@
 int ifc_set_mask(const char *name, in_addr_t mask)
 {
     struct ifreq ifr;
+    int ret;
 
     ifc_init_ifr(name, &ifr);
     init_sockaddr_in(&ifr.ifr_addr, mask);
 
-    return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
+    ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
+    if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret);
+    return ret;
 }
 
 int ifc_set_prefixLength(const char *name, int prefixLength)
@@ -323,6 +340,7 @@
     return result;
 }
 
+/* deprecated - v4 only */
 int ifc_create_default_route(const char *name, in_addr_t gw)
 {
     struct in_addr in_dst, in_gw;
@@ -330,7 +348,20 @@
     in_dst.s_addr = 0;
     in_gw.s_addr = gw;
 
-    return ifc_act_on_route(SIOCADDRT, name, in_dst, 0, in_gw);
+    int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw);
+    if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret);
+    return ret;
+}
+
+/* deprecated v4-only */
+int ifc_add_host_route(const char *name, in_addr_t dst)
+{
+    struct in_addr in_dst, in_gw;
+
+    in_dst.s_addr = dst;
+    in_gw.s_addr = 0;
+
+    return ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 32, in_gw);
 }
 
 int ifc_enable(const char *ifname)
@@ -449,6 +480,70 @@
 }
 
 /*
+ * Return the address of the default gateway
+ *
+ * TODO: factor out common code from this and remove_host_routes()
+ * so that we only scan /proc/net/route in one place.
+ *
+ * DEPRECATED
+ */
+int ifc_get_default_route(const char *ifname)
+{
+    char name[64];
+    in_addr_t dest, gway, mask;
+    int flags, refcnt, use, metric, mtu, win, irtt;
+    int result;
+    FILE *fp;
+
+    fp = fopen("/proc/net/route", "r");
+    if (fp == NULL)
+        return 0;
+    /* Skip the header line */
+    if (fscanf(fp, "%*[^\n]\n") < 0) {
+        fclose(fp);
+        return 0;
+    }
+    ifc_init();
+    result = 0;
+    for (;;) {
+        int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n",
+                           name, &dest, &gway, &flags, &refcnt, &use, &metric, &mask,
+                           &mtu, &win, &irtt);
+        if (nread != 11) {
+            break;
+        }
+        if ((flags & (RTF_UP|RTF_GATEWAY)) == (RTF_UP|RTF_GATEWAY)
+                && dest == 0
+                && strcmp(ifname, name) == 0) {
+            result = gway;
+            break;
+        }
+    }
+    fclose(fp);
+    ifc_close();
+    return result;
+}
+
+/*
+ * Sets the specified gateway as the default route for the named interface.
+ * DEPRECATED
+ */
+int ifc_set_default_route(const char *ifname, in_addr_t gateway)
+{
+    struct in_addr addr;
+    int result;
+
+    ifc_init();
+    addr.s_addr = gateway;
+    if ((result = ifc_create_default_route(ifname, gateway)) < 0) {
+        LOGD("failed to add %s as default route for %s: %s",
+             inet_ntoa(addr), ifname, strerror(errno));
+    }
+    ifc_close();
+    return result;
+}
+
+/*
  * Removes the default route for the named interface.
  */
 int ifc_remove_default_route(const char *ifname)
@@ -627,9 +722,31 @@
     return ret;
 }
 
+/*
+ * DEPRECATED
+ */
+int ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length,
+      struct in_addr gw)
+{
+    int i =ifc_act_on_ipv4_route(SIOCADDRT, ifname, dst, prefix_length, gw);
+    printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i);
+    return i;
+}
+
+/*
+ * DEPRECATED
+ */
+int ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_length,
+      struct in6_addr gw)
+{
+    return ifc_act_on_ipv6_route(SIOCADDRT, ifname, dst, prefix_length, gw);
+}
+
 int ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw)
 {
-    return ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw);
+    int i = ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw);
+    printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i);
+    return i;
 }
 
 int ifc_remove_route(const char *ifname, const char*dst, int prefix_length, const char *gw)
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
index b24a45e..adea077 100644
--- a/libsysutils/src/NetlinkListener.cpp
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -36,7 +36,7 @@
     int socket = cli->getSocket();
     ssize_t count;
 
-    count = TEMP_FAILURE_RETRY(uevent_checked_recv(socket, mBuffer, sizeof(mBuffer)));
+    count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_recv(socket, mBuffer, sizeof(mBuffer)));
     if (count < 0) {
         SLOGE("recvmsg failed (%s)", strerror(errno));
         return false;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 54873e0..a2c6beb 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -19,7 +19,7 @@
     export ANDROID_DATA /data
     export ASEC_MOUNTPOINT /mnt/asec
     export LOOP_MOUNTPOINT /mnt/obb
-    export BOOTCLASSPATH /system/framework/core.jar:/system/framework/apache-xml.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/core-junit.jar
+    export BOOTCLASSPATH /system/framework/core.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar
 
 # Backward compatibility
     symlink /system/etc /etc