Merge "Add MDNS service"
diff --git a/adb/adb.c b/adb/adb.c
index 001fae1..f4ee448 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -933,6 +933,8 @@
 #if !ADB_HOST
     int port;
     char value[PROPERTY_VALUE_MAX];
+
+    umask(000);
 #endif
 
     atexit(adb_cleanup);
diff --git a/adb/sockets.c b/adb/sockets.c
index ce3c65e..91db951 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -426,11 +426,14 @@
     s = create_local_socket(fd);
     D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
 
-    if (!strcmp(name, "root:") || !strcmp(name, "usb:") ||
-                                  !strcmp(name, "tcpip:")) {
+#if !ADB_HOST
+    if ((!strcmp(name, "root:") && getuid() != 0)
+        || !strcmp(name, "usb:")
+        || !strcmp(name, "tcpip:")) {
         D("LS(%d): enabling exit_on_close\n", s->id);
         s->exit_on_close = 1;
     }
+#endif
 
     return s;
 }
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 8c130ff..089b9bb 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -50,6 +50,12 @@
 
 LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz libext4_utils libz
 
+ifneq ($(HOST_OS),windows)
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_STATIC_LIBRARIES += libselinux
+endif # HAVE_SELINUX
+endif # HOST_OS != windows
+
 include $(BUILD_HOST_EXECUTABLE)
 $(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE))
 
diff --git a/fastboot/engine.c b/fastboot/engine.c
index 93d24bc..994eeae 100644
--- a/fastboot/engine.c
+++ b/fastboot/engine.c
@@ -257,7 +257,7 @@
 #endif
     reset_ext4fs_info();
     info.len = image->partition_size;
-    make_ext4fs_internal(fd, NULL, NULL, 0, 0, 1, 0, 0, 0);
+    make_ext4fs_internal(fd, NULL, NULL, NULL, 0, 1, 0, 0, 0, NULL);
 
     fstat(fd, &st);
     image->image_size = st.st_size;
diff --git a/include/cutils/uevent.h b/include/cutils/uevent.h
index 4ebc300..4cca7e5 100644
--- a/include/cutils/uevent.h
+++ b/include/cutils/uevent.h
@@ -26,6 +26,7 @@
 
 int uevent_open_socket(int buf_sz, bool passcred);
 ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length);
+ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid);
 
 #ifdef __cplusplus
 }
diff --git a/include/system/audio.h b/include/system/audio.h
index 0276231..4cadb67 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -290,6 +290,8 @@
     AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400,
     AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800,
     AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000,
+    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000,
+    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000,
     AUDIO_DEVICE_OUT_DEFAULT                   = 0x8000,
     AUDIO_DEVICE_OUT_ALL      = (AUDIO_DEVICE_OUT_EARPIECE |
                                  AUDIO_DEVICE_OUT_SPEAKER |
@@ -304,6 +306,8 @@
                                  AUDIO_DEVICE_OUT_AUX_DIGITAL |
                                  AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
                                  AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
+                                 AUDIO_DEVICE_OUT_USB_ACCESSORY |
+                                 AUDIO_DEVICE_OUT_USB_DEVICE |
                                  AUDIO_DEVICE_OUT_DEFAULT),
     AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
                                  AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -311,6 +315,8 @@
     AUDIO_DEVICE_OUT_ALL_SCO  = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
                                  AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
                                  AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
+    AUDIO_DEVICE_OUT_ALL_USB  = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
+                                 AUDIO_DEVICE_OUT_USB_DEVICE),
 
     /* input devices */
     AUDIO_DEVICE_IN_COMMUNICATION         = 0x10000,
@@ -368,6 +374,14 @@
         return false;
 }
 
+static inline bool audio_is_usb_device(audio_devices_t device)
+{
+    if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_USB))
+        return true;
+    else
+        return false;
+}
+
 static inline bool audio_is_input_channel(uint32_t channel)
 {
     if ((channel & ~AUDIO_CHANNEL_IN_ALL) == 0)
diff --git a/include/system/window.h b/include/system/window.h
index 9602445..3595514 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -157,9 +157,10 @@
 
 
     /*
-     * Default width and height of the ANativeWindow, these are the dimensions
-     * of the window irrespective of the NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS
-     * call.
+     * Default width and height of ANativeWindow buffers, these are the
+     * dimensions of the window buffers irrespective of the
+     * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS call and match the native window
+     * size unless overriden by NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS.
      */
     NATIVE_WINDOW_DEFAULT_WIDTH = 6,
     NATIVE_WINDOW_DEFAULT_HEIGHT = 7,
@@ -231,6 +232,7 @@
     NATIVE_WINDOW_UNLOCK_AND_POST           = 12,   /* private */
     NATIVE_WINDOW_API_CONNECT               = 13,   /* private */
     NATIVE_WINDOW_API_DISCONNECT            = 14,   /* private */
+    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
 };
 
 /* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -417,6 +419,7 @@
      *     NATIVE_WINDOW_UNLOCK_AND_POST        (private)
      *     NATIVE_WINDOW_API_CONNECT            (private)
      *     NATIVE_WINDOW_API_DISCONNECT         (private)
+     *     NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS (private)
      *
      */
 
@@ -527,7 +530,7 @@
 /*
  * native_window_set_buffers_dimensions(..., int w, int h)
  * All buffers dequeued after this call will have the dimensions specified.
- * In particular, all buffers will have a fixed-size, independent form the
+ * In particular, all buffers will have a fixed-size, independent from the
  * native-window size. They will be scaled according to the scaling mode
  * (see native_window_set_scaling_mode) upon window composition.
  *
@@ -546,6 +549,31 @@
 }
 
 /*
+ * native_window_set_buffers_user_dimensions(..., int w, int h)
+ *
+ * Sets the user buffer size for the window, which overrides the
+ * window's size.  All buffers dequeued after this call will have the
+ * dimensions specified unless overridden by
+ * native_window_set_buffers_dimensions.  All buffers will have a
+ * fixed-size, independent from the native-window size. They will be
+ * scaled according to the scaling mode (see
+ * native_window_set_scaling_mode) upon window composition.
+ *
+ * If w and h are 0, the normal behavior is restored. That is, the
+ * default buffer size will match the windows's size.
+ *
+ * Calling this function will reset the window crop to a NULL value, which
+ * disables cropping of the buffers.
+ */
+static inline int native_window_set_buffers_user_dimensions(
+        struct ANativeWindow* window,
+        int w, int h)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS,
+            w, h);
+}
+
+/*
  * native_window_set_buffers_format(..., int format)
  * All buffers dequeued after this call will have the format specified.
  *
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index 25a56f7..3494a9c 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -34,6 +34,8 @@
     const static int NlActionChange;
     const static int NlActionLinkDown;
     const static int NlActionLinkUp;
+    const static int NlActionIfaceActive;
+    const static int NlActionIfaceIdle;
 
     NetlinkEvent();
     virtual ~NetlinkEvent();
diff --git a/init/init.c b/init/init.c
index 5458e34..483544a 100755
--- a/init/init.c
+++ b/init/init.c
@@ -240,6 +240,7 @@
         char tmp[32];
         int fd, sz;
 
+        umask(077);
         if (properties_inited()) {
             get_property_workspace(&fd, &sz);
             sprintf(tmp, "%d,%d", dup(fd), sz);
diff --git a/init/ueventd.c b/init/ueventd.c
index ecf3b9b..a89e067 100644
--- a/init/ueventd.c
+++ b/init/ueventd.c
@@ -53,11 +53,18 @@
     int nr;
     char tmp[32];
 
-        /* Prevent fire-and-forget children from becoming zombies.
-         * If we should need to wait() for some children in the future
-         * (as opposed to none right now), double-forking here instead
-         * of ignoring SIGCHLD may be the better solution.
-         */
+    /*
+     * init sets the umask to 077 for forked processes. We need to
+     * create files with exact permissions, without modification by
+     * the umask.
+     */
+    umask(000);
+
+    /* Prevent fire-and-forget children from becoming zombies.
+     * If we should need to wait() for some children in the future
+     * (as opposed to none right now), double-forking here instead
+     * of ignoring SIGCHLD may be the better solution.
+     */
     signal(SIGCHLD, SIG_IGN);
 
     open_devnull_stdio();
diff --git a/libcutils/uevent.c b/libcutils/uevent.c
index 4add29c..97a81e3 100644
--- a/libcutils/uevent.c
+++ b/libcutils/uevent.c
@@ -29,7 +29,24 @@
 /**
  * Like recv(), but checks that messages actually originate from the kernel.
  */
-ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) {
+ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length)
+{
+    uid_t user = -1;
+    return uevent_kernel_multicast_uid_recv(socket, buffer, length, &user);
+}
+
+/**
+ * Like the above, but passes a uid_t in by reference. In the event that this
+ * fails due to a bad uid check, the uid_t will be set to the uid of the
+ * socket's peer.
+ *
+ * If this method rejects a netlink message from outside the kernel, it
+ * returns -1, sets errno to EIO, and sets "user" to the UID associated with the
+ * message. If the peer UID cannot be determined, "user" is set to -1."
+ */
+ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer,
+                                         size_t length, uid_t *user)
+{
     struct iovec iov = { buffer, length };
     struct sockaddr_nl addr;
     char control[CMSG_SPACE(sizeof(struct ucred))];
@@ -43,16 +60,12 @@
         0,
     };
 
+    *user = -1;
     ssize_t n = recvmsg(socket, &hdr, 0);
     if (n <= 0) {
         return n;
     }
 
-    if (addr.nl_groups == 0 || addr.nl_pid != 0) {
-        /* ignoring non-kernel or unicast netlink message */
-        goto out;
-    }
-
     struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
     if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
         /* ignoring netlink message with no sender credentials */
@@ -60,11 +73,17 @@
     }
 
     struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg);
+    *user = cred->uid;
     if (cred->uid != 0) {
         /* ignoring netlink message from non-root user */
         goto out;
     }
 
+    if (addr.nl_groups == 0 || addr.nl_pid != 0) {
+        /* ignoring non-kernel or unicast netlink message */
+        goto out;
+    }
+
     return n;
 
 out:
diff --git a/libsysutils/EventLogTags.logtags b/libsysutils/EventLogTags.logtags
index 27785f0..7aa5cad 100644
--- a/libsysutils/EventLogTags.logtags
+++ b/libsysutils/EventLogTags.logtags
@@ -2,3 +2,4 @@
 
 # FrameworkListener dispatchCommand overflow
 78001 dispatchCommand_overflow
+65537 netlink_failure (uid|1)
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 4beebb7..6439711 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -25,6 +25,7 @@
 #include <sys/socket.h>
 #include <linux/if.h>
 #include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/xt_IDLETIMER.h>
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
 /* From kernel's net/netfilter/xt_quota2.c */
 const int QLOG_NL_EVENT  = 112;
@@ -38,6 +39,8 @@
 const int NetlinkEvent::NlActionChange = 3;
 const int NetlinkEvent::NlActionLinkUp = 4;
 const int NetlinkEvent::NlActionLinkDown = 5;
+const int NetlinkEvent::NlActionIfaceActive = 6;
+const int NetlinkEvent::NlActionIfaceIdle = 7;
 
 NetlinkEvent::NetlinkEvent() {
     mAction = NlActionUnknown;
@@ -70,7 +73,8 @@
 }
 
 /*
- * Parse an binary message from a NETLINK_ROUTE netlink socket.
+ * Parse an binary message from a NETLINK_ROUTE netlink socket
+ * and IDLETIMER netlink socket.
  */
 bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) {
     size_t sz = size;
@@ -127,6 +131,14 @@
             mSubsystem = strdup("qlog");
             mAction = NlActionChange;
 
+        } else if (nh->nlmsg_type == NL_EVENT_TYPE_ACTIVE
+                   || nh->nlmsg_type == NL_EVENT_TYPE_INACTIVE) {
+            char *ifacename;
+            ifacename = (char *)NLMSG_DATA(nh);
+            asprintf(&mParams[0], "INTERFACE=%s", ifacename);
+            mSubsystem = strdup("idletimer");
+            mAction = (nh->nlmsg_type == NL_EVENT_TYPE_ACTIVE) ?
+              NlActionIfaceActive : NlActionIfaceIdle;
         } else {
                 SLOGD("Unexpected netlink message. type=0x%x\n", nh->nlmsg_type);
         }
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
index e67b5c6..9c447ca 100644
--- a/libsysutils/src/NetlinkListener.cpp
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -45,9 +45,13 @@
 {
     int socket = cli->getSocket();
     ssize_t count;
+    uid_t uid = -1;
 
-    count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_recv(socket, mBuffer, sizeof(mBuffer)));
+    count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv(
+                                       socket, mBuffer, sizeof(mBuffer), &uid));
     if (count < 0) {
+        if (uid > 0)
+            LOG_EVENT_INT(65537, uid);
         SLOGE("recvmsg failed (%s)", strerror(errno));
         return false;
     }
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a0e4d19..90739c0 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -242,6 +242,20 @@
     chmod 0660 /sys/power/state
     chmod 0660 /sys/power/wake_lock
     chmod 0660 /sys/power/wake_unlock
+
+    chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate
+    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate
+    chown system system /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
+    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
+    chown system system /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
+    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
+    chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
+    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
+
+    # Assume SMP uses shared cpufreq policy for all CPUs
+    chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
+    chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
+
     chown system system /sys/class/timed_output/vibrator/enable
     chown system system /sys/class/leds/keyboard-backlight/brightness
     chown system system /sys/class/leds/lcd-backlight/brightness
@@ -370,6 +384,10 @@
 on property:ro.debuggable=1
     start console
 
+# Allow writing to the kernel trace log.  Enabling tracing still requires root.
+on property:ro.debuggable=1
+    chmod 0222 /sys/kernel/debug/tracing/trace_marker
+
 # adbd is controlled via property triggers in init.<platform>.usb.rc
 service adbd /sbin/adbd
     class core
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 689cd2a..dba5a4e 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -43,7 +43,7 @@
  * usage:  sdcard <path> <uid> <gid>
  *
  * It must be run as root, but will change to uid/gid as soon as it
- * mounts a filesystem on /mnt/sdcard.  It will refuse to run if uid or
+ * mounts a filesystem on /storage/sdcard.  It will refuse to run if uid or
  * gid are zero.
  *
  *
@@ -70,7 +70,7 @@
 
 #define FUSE_UNKNOWN_INO 0xffffffff
 
-#define MOUNT_POINT "/mnt/sdcard"
+#define MOUNT_POINT "/storage/sdcard0"
 
 struct handle {
     struct node *node;
diff --git a/toolbox/kill.c b/toolbox/kill.c
index 4d0e479..b79805f 100644
--- a/toolbox/kill.c
+++ b/toolbox/kill.c
@@ -5,16 +5,127 @@
 #include <sys/types.h>
 #include <signal.h>
 
+static struct {
+    unsigned int number;
+    char *name;
+} signals[] = {
+#define _SIG(name) {SIG##name, #name}
+    /* Single Unix Specification signals */
+    _SIG(ABRT),
+    _SIG(ALRM),
+    _SIG(FPE),
+    _SIG(HUP),
+    _SIG(ILL),
+    _SIG(INT),
+    _SIG(KILL),
+    _SIG(PIPE),
+    _SIG(QUIT),
+    _SIG(SEGV),
+    _SIG(TERM),
+    _SIG(USR1),
+    _SIG(USR2),
+    _SIG(CHLD),
+    _SIG(CONT),
+    _SIG(STOP),
+    _SIG(TSTP),
+    _SIG(TTIN),
+    _SIG(TTOU),
+    _SIG(BUS),
+    _SIG(POLL),
+    _SIG(PROF),
+    _SIG(SYS),
+    _SIG(TRAP),
+    _SIG(URG),
+    _SIG(VTALRM),
+    _SIG(XCPU),
+    _SIG(XFSZ),
+    /* non-SUS signals */
+    _SIG(IO),
+    _SIG(PWR),
+    _SIG(STKFLT),
+    _SIG(WINCH),
+#undef _SIG
+};
+
+/* To indicate a matching signal was not found */
+static const unsigned int SENTINEL = (unsigned int) -1;
+
+void list_signals()
+{
+    unsigned int sorted_signals[_NSIG];
+    unsigned int i;
+    unsigned int num;
+
+    memset(sorted_signals, SENTINEL, sizeof(sorted_signals));
+
+    // Sort the signals
+    for (i = 0; i < sizeof(signals)/sizeof(signals[0]); i++) {
+        sorted_signals[signals[i].number] = i;
+    }
+
+    num = 0;
+    for (i = 1; i < _NSIG; i++) {
+        unsigned int index = sorted_signals[i];
+        if (index == SENTINEL) {
+            continue;
+        }
+
+        fprintf(stderr, "%2d) SIG%-9s ", i, signals[index].name);
+
+        if ((num++ % 4) == 3) {
+            fprintf(stderr, "\n");
+        }
+    }
+
+    if ((num % 4) == 3) {
+        fprintf(stderr, "\n");
+    }
+}
+
+unsigned int name_to_signal(const char* name)
+{
+    unsigned int i;
+
+    for (i = 1; i < sizeof(signals) / sizeof(signals[0]); i++) {
+        if (!strcasecmp(name, signals[i].name)) {
+            return signals[i].number;
+        }
+    }
+
+    return SENTINEL;
+}
+
 int kill_main(int argc, char **argv)
 {
-    int sig = SIGTERM;
+    unsigned int sig = SIGTERM;
     int result = 0;
-    
+
     argc--;
     argv++;
 
-    if(argc >= 2 && argv[0][0] == '-'){
-        sig = atoi(argv[0] + 1);
+    if (argc >= 1 && argv[0][0] == '-') {
+        char *endptr;
+        size_t arg_len = strlen(argv[0]);
+        if (arg_len < 2) {
+            fprintf(stderr, "invalid argument: -\n");
+            return -1;
+        }
+
+        char* arg = argv[0] + 1;
+        if (arg_len == 2 && *arg == 'l') {
+            list_signals();
+            return 0;
+        }
+
+        sig = strtol(arg, &endptr, 10);
+        if (*endptr != '\0') {
+            sig = name_to_signal(arg);
+            if (sig == SENTINEL) {
+                fprintf(stderr, "invalid signal name: %s\n", arg);
+                return -1;
+            }
+        }
+
         argc--;
         argv++;
     }
@@ -26,10 +137,10 @@
             result = err;
             fprintf(stderr, "could not kill pid %d: %s\n", pid, strerror(errno));
         }
-            
+
         argc--;
         argv++;
     }
-    
+
     return result;
 }
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index ff9e844..6d78eb6 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -431,7 +431,8 @@
 		bpb.spc = 8;
 	    else if (bpb.bsec <= (1<<19)) /* 256M -> 8k */
 		bpb.spc = 16;
-	    else if (bpb.bsec <= (1<<21)) /* 1G -> 16k */
+	    else if (bpb.bsec <= (1<<22)) /* 2G -> 16k, some versions of windows
+					     require a minimum of 65527 clusters */
 		bpb.spc = 32;
 	    else
 		bpb.spc = 64;		/* otherwise 32k */