Merge change 23911 into eclair

* changes:
  Add contacts aggregation event to the log.
diff --git a/adb/services.c b/adb/services.c
index 2864ac9..cd02b36 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -32,8 +32,7 @@
 #    include <netdb.h>
 #  endif
 #else
-#include <sys/poll.h>
-#include <sys/reboot.h>
+#  include <sys/reboot.h>
 #endif
 
 typedef struct stinfo stinfo;
@@ -253,9 +252,12 @@
     return s[0];
 }
 
-#if !ADB_HOST
 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
 {
+#ifdef HAVE_WIN32_PROC
+	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
+	return -1;
+#else /* !HAVE_WIN32_PROC */
     char *devname;
     int ptm;
     pid_t pid;
@@ -298,6 +300,7 @@
                 cmd, strerror(errno), errno);
         exit(-1);
     } else {
+#if !ADB_HOST
         // set child's OOM adjustment to zero
         char text[64];
         snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
@@ -308,11 +311,11 @@
         } else {
            D("adb: unable to open %s\n", text);
         }
-
+#endif
         return ptm;
     }
+#endif /* !HAVE_WIN32_PROC */
 }
-#endif /* !ADB_HOST */
 
 #if ADB_HOST
 #define SHELL_COMMAND "/bin/sh"
@@ -320,76 +323,6 @@
 #define SHELL_COMMAND "/system/bin/sh"
 #endif
 
-#if !ADB_HOST
-static void shell_service(int s, void *command)
-{
-    char    buffer[MAX_PAYLOAD];
-    char    buffer2[MAX_PAYLOAD];
-    struct pollfd ufds[2];
-    int     fd, ret = 0;
-    unsigned count = 0;
-    char** args = (char **)command;
-    fd = create_subprocess(SHELL_COMMAND, args[0], args[1]);
-
-    while (1) {
-        while (count < sizeof(buffer)) {
-            ufds[0].fd = fd;
-            ufds[0].events = POLLIN | POLLHUP;
-            ufds[0].revents = 0;
-            ufds[1].fd = s;
-            ufds[1].events = POLLIN | POLLHUP;
-            ufds[1].revents = 0;
-            // use a 100ms timeout so we don't block indefinitely with our
-            // buffer partially filled.
-            ret = poll(ufds, 2, 100);
-            if (ret <= 0) {
-                D("poll returned %d\n", ret);
-                // file has closed or we timed out
-                // set ret to 1 so we don't exit the outer loop
-                ret = 1;
-                break;
-            }
-
-            if (ufds[0].revents & POLLIN) {
-                ret = adb_read(fd, buffer + count, sizeof(buffer) - count);
-                D("read fd ret: %d, count: %d\n", ret, count);
-                if (ret > 0)
-                    count += ret;
-                else
-                    break;
-            }
-            if (ufds[1].revents & POLLIN) {
-                ret = adb_read(s, buffer2, sizeof(buffer2));
-                D("read s ret: %d\n", ret);
-                if (ret > 0)
-                    adb_write(fd, buffer2, ret);
-                else
-                    break;
-            }
-
-            if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) {
-                // set flag to exit after flushing the buffer
-                ret = -1;
-                break;
-            }
-        }
-
-        D("writing: %d\n", count);
-        if (count > 0) {
-            adb_write(s, buffer, count);
-            count = 0;
-        }
-        if (ret <= 0)
-            break;
-    }
-
-    D("shell_service done\n");
-
-    adb_close(fd);
-    adb_close(s);
-}
-#endif // !ADB_HOST
-
 int service_to_fd(const char *name)
 {
     int ret = -1;
@@ -440,16 +373,14 @@
         ret = create_jdwp_connection_fd(atoi(name+5));
     } else if (!strncmp(name, "log:", 4)) {
         ret = create_service_thread(log_service, get_log_file_path(name + 4));
+#endif
     } else if(!HOST && !strncmp(name, "shell:", 6)) {
-        const char* args[2];
         if(name[6]) {
-            args[0] = "-c";
-            args[1] = name + 6;
+            ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
         } else {
-            args[0] = "-";
-            args[1] = 0;
+            ret = create_subprocess(SHELL_COMMAND, "-", 0);
         }
-        ret = create_service_thread(shell_service, (void *)args);
+#if !ADB_HOST
     } else if(!strncmp(name, "sync:", 5)) {
         ret = create_service_thread(file_sync_service, NULL);
     } else if(!strncmp(name, "remount:", 8)) {
diff --git a/init/property_service.c b/init/property_service.c
index 35929f0..7db7c2c 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -52,31 +52,32 @@
 struct {
     const char *prefix;
     unsigned int uid;
+    unsigned int gid;
 } property_perms[] = {
-    { "net.rmnet0.",      AID_RADIO },
-    { "net.gprs.",        AID_RADIO },
-    { "net.ppp",          AID_RADIO },
-    { "ril.",             AID_RADIO },
-    { "gsm.",             AID_RADIO },
-    { "persist.radio",    AID_RADIO },
-    { "net.dns",          AID_RADIO },
-    { "net.",             AID_SYSTEM },
-    { "dev.",             AID_SYSTEM },
-    { "runtime.",         AID_SYSTEM },
-    { "hw.",              AID_SYSTEM },
-    { "sys.",             AID_SYSTEM },
-    { "service.",         AID_SYSTEM },
-    { "wlan.",            AID_SYSTEM },
-    { "dhcp.",            AID_SYSTEM },
-    { "dhcp.",            AID_DHCP },
-    { "vpn.",             AID_SYSTEM },
-    { "vpn.",             AID_VPN },
-    { "debug.",           AID_SHELL },
-    { "log.",             AID_SHELL },
-    { "service.adb.root", AID_SHELL },
-    { "persist.sys.",     AID_SYSTEM },
-    { "persist.service.", AID_SYSTEM },
-    { NULL, 0 }
+    { "net.rmnet0.",      AID_RADIO,    0 },
+    { "net.gprs.",        AID_RADIO,    0 },
+    { "net.ppp",          AID_RADIO,    0 },
+    { "ril.",             AID_RADIO,    0 },
+    { "gsm.",             AID_RADIO,    0 },
+    { "persist.radio",    AID_RADIO,    0 },
+    { "net.dns",          AID_RADIO,    0 },
+    { "net.",             AID_SYSTEM,   0 },
+    { "dev.",             AID_SYSTEM,   0 },
+    { "runtime.",         AID_SYSTEM,   0 },
+    { "hw.",              AID_SYSTEM,   0 },
+    { "sys.",             AID_SYSTEM,   0 },
+    { "service.",         AID_SYSTEM,   0 },
+    { "wlan.",            AID_SYSTEM,   0 },
+    { "dhcp.",            AID_SYSTEM,   0 },
+    { "dhcp.",            AID_DHCP,     0 },
+    { "vpn.",             AID_SYSTEM,   0 },
+    { "vpn.",             AID_VPN,      0 },
+    { "debug.",           AID_SHELL,    0 },
+    { "log.",             AID_SHELL,    0 },
+    { "service.adb.root", AID_SHELL,    0 },
+    { "persist.sys.",     AID_SYSTEM,   0 },
+    { "persist.service.", AID_SYSTEM,   0 },
+    { NULL, 0, 0 }
 };
 
 /*
@@ -86,8 +87,10 @@
 struct {
     const char *service;
     unsigned int uid;
+    unsigned int gid;
 } control_perms[] = {
-     {NULL, 0 }
+    { "dumpstate",AID_SHELL, AID_LOG },
+     {NULL, 0, 0 }
 };
 
 typedef struct {
@@ -183,7 +186,7 @@
  *
  * Returns 1 if uid allowed, 0 otherwise.
  */
-static int check_control_perms(const char *name, int uid) {
+static int check_control_perms(const char *name, int uid, int gid) {
     int i;
     if (uid == AID_SYSTEM || uid == AID_ROOT)
         return 1;
@@ -191,8 +194,10 @@
     /* Search the ACL */
     for (i = 0; control_perms[i].service; i++) {
         if (strcmp(control_perms[i].service, name) == 0) {
-            if (control_perms[i].uid == uid)
+            if ((uid && control_perms[i].uid == uid) ||
+                (gid && control_perms[i].gid == gid)) {
                 return 1;
+            }
         }
     }
     return 0;
@@ -202,7 +207,7 @@
  * Checks permissions for setting system properties.
  * Returns 1 if uid allowed, 0 otherwise.
  */
-static int check_perms(const char *name, unsigned int uid)
+static int check_perms(const char *name, unsigned int uid, int gid)
 {
     int i;
     if (uid == 0)
@@ -215,7 +220,8 @@
         int tmp;
         if (strncmp(property_perms[i].prefix, name,
                     strlen(property_perms[i].prefix)) == 0) {
-            if (property_perms[i].uid == uid) {
+            if ((uid && property_perms[i].uid == uid) ||
+                (gid && property_perms[i].gid == gid)) {
                 return 1;
             }
         }
@@ -373,14 +379,14 @@
         msg.value[PROP_VALUE_MAX-1] = 0;
 
         if(memcmp(msg.name,"ctl.",4) == 0) {
-            if (check_control_perms(msg.value, cr.uid)) {
+            if (check_control_perms(msg.value, cr.uid, cr.gid)) {
                 handle_control_message((char*) msg.name + 4, (char*) msg.value);
             } else {
                 ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n",
                         msg.name + 4, msg.value, cr.uid, cr.pid);
             }
         } else {
-            if (check_perms(msg.name, cr.uid)) {
+            if (check_perms(msg.name, cr.uid, cr.gid)) {
                 property_set((char*) msg.name, (char*) msg.value);
             } else {
                 ERROR("sys_prop: permission denied uid:%d  name:%s\n",
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 03563c3..7d9869f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -352,3 +352,7 @@
     group keystore
     socket keystore stream 666
 
+service dumpstate /system/bin/dumpstate -s
+    socket dumpstate stream 0660 shell log
+    disabled
+    oneshot