Code drop from //branches/cupcake/...@124589
diff --git a/init/README.BOOTCHART b/init/README.BOOTCHART
index 4899369..70cf2c3 100644
--- a/init/README.BOOTCHART
+++ b/init/README.BOOTCHART
@@ -1,32 +1,50 @@
-this version of init contains code to perform "bootcharting", i.e. generating log
+This version of init contains code to perform "bootcharting", i.e. generating log
 files that can be later processed by the tools provided by www.bootchart.org.
 
-to activate it, you need to define build 'init' with the INIT_BOOTCHART environment
-variable defined to 'true', then create a file on the /data partition with a command
-like the following:
+To activate it, you need to define build 'init' with the INIT_BOOTCHART environment
+variable defined to 'true', for example:
 
-  adb shell 'echo 1 > /data/bootchart'
+    touch system/init/init.c
+    m INIT_BOOTCHART=true
 
-if the '/data/bootchart' file doesn't exist, or doesn't contain a '1' in its first
-byte, init will proceed normally.
+On the emulator, use the new -bootchart <timeout> option to boot with bootcharting
+activated for <timeout> seconds.
 
-by default, the bootchart log stops after 2 minutes, but you can stop it earlier
-with the following command while the device is booting:
+Otherwise, flash your device, and start it. Then create a file on the /data partition
+with a command like the following:
+
+  adb shell 'echo $TIMEOUT > /data/bootchart-start'
+
+Where the value of $TIMEOUT corresponds to the wanted bootcharted period in seconds;
+for example, to bootchart for 2 minutes, do:
+
+  adb shell 'echo 120 > /data/bootchart-start'
+
+Reboot your device, bootcharting will begin and stop after the period you gave.
+You can also stop the bootcharting at any moment by doing the following:
 
   adb shell 'echo 1 > /data/bootchart-stop'
 
-note that /data/bootchart-stop is deleted automatically by init at the end of the
-bootcharting. this is not the case of /data/bootchart, so don't forget to delete it
+Note that /data/bootchart-stop is deleted automatically by init at the end of the
+bootcharting. This is not the case of /data/bootchart-start, so don't forget to delete it
 when you're done collecting data:
 
-  adb shell rm /data/bootchart
+  adb shell rm /data/bootchart-start
 
-the log files are placed in /tmp/bootchart/. you must run the script tools/grab-bootchart.sh
+The log files are placed in /data/bootchart/. you must run the script tools/grab-bootchart.sh
 which will use ADB to retrieve them and create a bootchart.tgz file that can be used with
 the bootchart parser/renderer, or even uploaded directly to the form located at:
 
   http://www.bootchart.org/download.html
 
+NOTE: the bootchart.org webform doesn't seem to work at the moment, you can generate an
+      image on your machine by doing the following:
+
+         1/ download the sources from www.bootchart.org
+         2/ unpack them
+         3/ in the source directory, type 'ant' to build the bootchart program
+         4/ type 'java -jar bootchart.jar /path/to/bootchart.tgz
+
 technical note:
 
 this implementation of bootcharting does use the 'bootchartd' script provided by
diff --git a/init/bootchart.c b/init/bootchart.c
index 2afe98b..f72fcaa 100644
--- a/init/bootchart.c
+++ b/init/bootchart.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
 /* this code is used to generate a boot sequence profile that can be used
  * with the 'bootchart' graphics generation tool. see www.bootchart.org
  * note that unlike the original bootchartd, this is not a Bash script but
@@ -16,17 +32,18 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <sys/stat.h>
+#include "bootchart.h"
 
 #define VERSION         "0.8"
 #define SAMPLE_PERIOD   0.2
-#define LOG_ROOT        "/tmp/bootchart"
+#define LOG_ROOT        "/data/bootchart"
 #define LOG_STAT        LOG_ROOT"/proc_stat.log"
 #define LOG_PROCS       LOG_ROOT"/proc_ps.log"
 #define LOG_DISK        LOG_ROOT"/proc_diskstats.log"
 #define LOG_HEADER      LOG_ROOT"/header"
 #define LOG_ACCT        LOG_ROOT"/kernel_pacct"
 
-#define LOG_STARTFILE   "/data/bootchart"
+#define LOG_STARTFILE   "/data/bootchart-start"
 #define LOG_STOPFILE    "/data/bootchart-stop"
 
 static int
@@ -54,12 +71,11 @@
         len = unix_read(fd, buff, buffsize-1);
         close(fd);
     }
-    buff[len] = 0;
+    buff[len > 0 ? len : 0] = 0;
     return len;
 }
 
 #define FILE_BUFF_SIZE    65536
-#define FILE_BUFF_RESERVE (FILE_BUFF_SIZE - 4096)
 
 typedef struct {
     int   count;
@@ -81,7 +97,7 @@
         int  avail = sizeof(buff->data) - buff->count;
         if (avail > len)
             avail = len;
-        
+
         memcpy( buff->data + buff->count, src, avail );
         len -= avail;
         src  = (char*)src + avail;
@@ -115,7 +131,7 @@
     time_t     now_t = time(NULL);
     struct tm  now = *localtime(&now_t);
     strftime(date, sizeof(date), "%x %X", &now);
-    
+
     out = fopen( LOG_HEADER, "w" );
     if (out == NULL)
         return;
@@ -123,7 +139,7 @@
     proc_read("/proc/cmdline", cmdline, sizeof(cmdline));
     proc_read("/proc/version", uname, sizeof(uname));
     proc_read("/proc/cpuinfo", cpuinfo, sizeof(cpuinfo));
-   
+
     cpu = strchr( cpuinfo, ':' );
     if (cpu) {
         char*  p = strchr(cpu, '\n');
@@ -131,7 +147,7 @@
         if (p)
             *p = 0;
     }
-   
+
     fprintf(out, "version = %s\n", VERSION);
     fprintf(out, "title = Boot chart for Android ( %s )\n", date);
     fprintf(out, "system.uname = %s\n", uname);
@@ -174,7 +190,6 @@
     fd = open("/proc/uptime",O_RDONLY);
     if (fd >= 0) {
         int  ret;
-        close_on_exec(fd);
         ret = unix_read(fd, buff, 64);
         close(fd);
         buff[64] = 0;
@@ -212,7 +227,7 @@
             ret = unix_read(fd, buff, sizeof(buff));
             if (ret <= 0)
                 break;
-                
+
             file_buff_write(log, buff, ret);
             if (ret < (int)sizeof(buff))
                 break;
@@ -230,7 +245,7 @@
     struct dirent*  entry;
 
     do_log_uptime(log);
-    
+
     while ((entry = readdir(dir)) != NULL) {
         /* only match numeric values */
         char*  end;
@@ -241,7 +256,7 @@
             char  cmdline[1024];
             int   len;
             int   fd;
-            
+
             /* read command line and extract program name */
             snprintf(filename,sizeof(filename),"/proc/%d/cmdline",pid);
             proc_read(filename, cmdline, sizeof(cmdline));
@@ -285,11 +300,36 @@
 {
     int  ret;
     char buff[4];
-    
+    int  timeout = 0, count = 0;
+
     buff[0] = 0;
     proc_read( LOG_STARTFILE, buff, sizeof(buff) );
-    if (buff[0] != '1')
-        return -1;
+    if (buff[0] != 0) {
+        timeout = atoi(buff);
+    }
+    else {
+        /* when running with emulator, androidboot.bootchart=<timeout>
+         * might be passed by as kernel parameters to specify the bootchart
+         * timeout. this is useful when using -wipe-data since the /data
+         * partition is fresh
+         */
+        char  cmdline[1024];
+        char* s;
+#define  KERNEL_OPTION  "androidboot.bootchart="
+        proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) );
+        s = strstr(cmdline, KERNEL_OPTION);
+        if (s) {
+            s      += sizeof(KERNEL_OPTION)-1;
+            timeout = atoi(s);
+        }
+    }
+    if (timeout == 0)
+        return 0;
+
+    if (timeout > BOOTCHART_MAX_TIME_SEC)
+        timeout = BOOTCHART_MAX_TIME_SEC;
+
+    count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS;
 
     do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR);
 
@@ -307,7 +347,7 @@
     }
 
     log_header();
-    return 0;
+    return count;
 }
 
 /* called each time you want to perform a bootchart sampling op */
@@ -324,6 +364,7 @@
             return -1;
         }
     }
+
     return 0;
 }
 
diff --git a/init/bootchart.h b/init/bootchart.h
new file mode 100644
index 0000000..39d2d4f
--- /dev/null
+++ b/init/bootchart.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef _BOOTCHART_H
+#define _BOOTCHART_H
+
+#ifndef BOOTCHART
+# define  BOOTCHART  0
+#endif
+
+#if BOOTCHART
+
+extern int   bootchart_init(void);
+extern int   bootchart_step(void);
+extern void  bootchart_finish(void);
+
+# define BOOTCHART_POLLING_MS   200   /* polling period in ms */
+# define BOOTCHART_DEFAULT_TIME_SEC    (2*60)  /* default polling time in seconds */
+# define BOOTCHART_MAX_TIME_SEC        (10*60) /* max polling time in seconds */
+
+#endif /* BOOTCHART */
+
+#endif /* _BOOTCHART_H */
diff --git a/init/builtins.c b/init/builtins.c
index ba34410..95fb223 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -64,7 +64,7 @@
     }
 }
 
-static int insmod(const char *filename)
+static int insmod(const char *filename, char *options)
 {
     void *module;
     unsigned size;
@@ -74,7 +74,7 @@
     if (!module)
         return -1;
 
-    ret = init_module(module, size, "");
+    ret = init_module(module, size, options);
 
     free(module);
 
@@ -172,9 +172,35 @@
     return __ifupdown(args[1], 1);
 }
 
+
+static int do_insmod_inner(int nargs, char **args, int opt_len)
+{
+    char options[opt_len + 1];
+    int i;
+
+    options[0] = '\0';
+    if (nargs > 2) {
+        strcpy(options, args[2]);
+        for (i = 3; i < nargs; ++i) {
+            strcat(options, " ");
+            strcat(options, args[i]);
+        }
+    }
+
+    return insmod(args[1], options);
+}
+
 int do_insmod(int nargs, char **args)
 {
-    return insmod(args[1]);
+    int i;
+    int size = 0;
+
+    if (nargs > 2) {
+        for (i = 2; i < nargs; ++i)
+            size += strlen(args[i]) + 1;
+    }
+
+    return do_insmod_inner(nargs, args, size);
 }
 
 int do_import(int nargs, char **args)
@@ -326,6 +352,20 @@
     return symlink(args[1], args[2]);
 }
 
+int do_sysclktz(int nargs, char **args)
+{
+    struct timezone tz;
+
+    if (nargs != 2)
+        return -1;
+
+    memset(&tz, 0, sizeof(tz));
+    tz.tz_minuteswest = atoi(args[1]);   
+    if (settimeofday(NULL, &tz))
+        return -1;
+    return 0;
+}
+
 int do_write(int nargs, char **args)
 {
     return write_file(args[1], args[2]);
diff --git a/init/devices.c b/init/devices.c
index 7aea246..f86eab9 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -98,9 +98,12 @@
         /* these should not be world writable */
     { "/dev/android_adb",   0660,   AID_ADB,        AID_ADB,        0 },
     { "/dev/android_adb_enable",   0660,   AID_ADB,        AID_ADB,        0 },
-    { "/dev/ttyMSM0",       0660,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
+    /* TODO: remove legacy ttyMSM0 */
+    { "/dev/ttyMSM0",       0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
+    { "/dev/ttyHS0",        0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
+    { "/dev/uinput",        0600,   AID_BLUETOOTH,  AID_BLUETOOTH,  0 },
     { "/dev/alarm",         0664,   AID_SYSTEM,     AID_RADIO,      0 },
-    { "/dev/tty0",          0666,   AID_ROOT,       AID_SYSTEM,     0 },
+    { "/dev/tty0",          0660,   AID_ROOT,       AID_SYSTEM,     0 },
     { "/dev/graphics/",     0660,   AID_ROOT,       AID_GRAPHICS,   1 },
     { "/dev/hw3d",          0660,   AID_SYSTEM,     AID_GRAPHICS,   0 },
     { "/dev/input/",        0660,   AID_ROOT,       AID_INPUT,      1 },
@@ -360,29 +363,29 @@
         return;
 
         /* are we block or char? where should we live? */
-    if(!strncmp(uevent->path, "/block", 6)) {
+    if(!strncmp(uevent->subsystem, "block", 5)) {
         block = 1;
         base = "/dev/block/";
         mkdir(base, 0755);
     } else {
         block = 0;
             /* this should probably be configurable somehow */
-        if(!strncmp(uevent->path, "/class/graphics/", 16)) {
+        if(!strncmp(uevent->subsystem, "graphics", 8)) {
             base = "/dev/graphics/";
             mkdir(base, 0755);
-        } else if (!strncmp(uevent->path, "/class/oncrpc/", 14)) {
+        } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
             base = "/dev/oncrpc/";
             mkdir(base, 0755);
-        } else if (!strncmp(uevent->path, "/class/adsp/", 12)) {
+        } else if (!strncmp(uevent->subsystem, "adsp", 4)) {
             base = "/dev/adsp/";
             mkdir(base, 0755);
-      } else if(!strncmp(uevent->path, "/class/input/", 13)) {
+      } else if(!strncmp(uevent->subsystem, "input", 5)) {
             base = "/dev/input/";
             mkdir(base, 0755);
-        } else if(!strncmp(uevent->path, "/class/mtd/", 11)) {
+        } else if(!strncmp(uevent->subsystem, "mtd", 3)) {
             base = "/dev/mtd/";
             mkdir(base, 0755);
-        } else if(!strncmp(uevent->path, "/class/misc/", 12) &&
+        } else if(!strncmp(uevent->subsystem, "misc", 4) &&
                     !strncmp(name, "log_", 4)) {
             base = "/dev/log/";
             mkdir(base, 0755);
diff --git a/init/grab-bootchart.sh b/init/grab-bootchart.sh
index 57c9556..7fe8904 100755
--- a/init/grab-bootchart.sh
+++ b/init/grab-bootchart.sh
@@ -9,13 +9,13 @@
 rm -rf $TMPDIR
 mkdir -p $TMPDIR
 
-LOGROOT=/tmp/bootchart
+LOGROOT=/data/bootchart
 TARBALL=bootchart.tgz
 
 FILES="header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct"
 
 for f in $FILES; do
-    adb pull $LOGROOT/$f $TMPDIR/$f &> /dev/null
+    adb pull $LOGROOT/$f $TMPDIR/$f 2>&1 > /dev/null
 done
 (cd $TMPDIR && tar -czf $TARBALL $FILES)
 cp -f $TMPDIR/$TARBALL ./$TARBALL
diff --git a/init/init.c b/init/init.c
index f6e9b39..3616840 100644
--- a/init/init.c
+++ b/init/init.c
@@ -43,21 +43,12 @@
 #include "devices.h"
 #include "init.h"
 #include "property_service.h"
-
-#ifndef BOOTCHART
-# define  BOOTCHART  0
-#endif
+#include "bootchart.h"
 
 static int property_triggers_enabled = 0;
 
 #if BOOTCHART
 static int   bootchart_count;
-extern int   bootchart_init(void);
-extern int   bootchart_step(void);
-extern void  bootchart_finish(void);
-# define BOOTCHART_POLLING_MS   200 /* polling period in ms */
-# define BOOTCHART_MAX_TIME_MS  (2*60*1000) /* max polling time from boot */
-# define BOOTCHART_MAX_COUNT    (BOOTCHART_MAX_TIME_MS/BOOTCHART_POLLING_MS)
 #endif
 
 static char console[32];
@@ -834,11 +825,13 @@
     ufds[2].events = POLLIN;
 
 #if BOOTCHART
-    if (bootchart_init() < 0)
+    bootchart_count = bootchart_init();
+    if (bootchart_count < 0) {
         ERROR("bootcharting init failure\n");
-    else {
-        NOTICE("bootcharting started\n");
-        bootchart_count = BOOTCHART_MAX_COUNT;
+    } else if (bootchart_count > 0) {
+        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
+    } else {
+        NOTICE("bootcharting ignored\n");
     }
 #endif
 
diff --git a/init/keywords.h b/init/keywords.h
index f09bad2..058996e 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -19,6 +19,7 @@
 int do_stop(int nargs, char **args);
 int do_trigger(int nargs, char **args);
 int do_symlink(int nargs, char **args);
+int do_sysclktz(int nargs, char **args);
 int do_write(int nargs, char **args);
 int do_chown(int nargs, char **args);
 int do_chmod(int nargs, char **args);
@@ -60,6 +61,7 @@
     KEYWORD(stop,        COMMAND, 1, do_stop)
     KEYWORD(trigger,     COMMAND, 1, do_trigger)
     KEYWORD(symlink,     COMMAND, 1, do_symlink)
+    KEYWORD(sysclktz,    COMMAND, 1, do_sysclktz)
     KEYWORD(user,        OPTION,  0, 0)
     KEYWORD(write,       COMMAND, 2, do_write)
     KEYWORD(chown,       COMMAND, 2, do_chown)
diff --git a/init/parser.c b/init/parser.c
index 95bf017..a51691b 100644
--- a/init/parser.c
+++ b/init/parser.c
@@ -183,6 +183,7 @@
         if (!strcmp(s, "tart")) return K_start;
         if (!strcmp(s, "top")) return K_stop;
         if (!strcmp(s, "ymlink")) return K_symlink;
+	if (!strcmp(s, "ysclktz")) return K_sysclktz;
         break;
     case 't':
         if (!strcmp(s, "rigger")) return K_trigger;
diff --git a/init/property_service.c b/init/property_service.c
index 0bc403f..7a6416b 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -343,7 +343,7 @@
     socklen_t addr_size = sizeof(addr);
     socklen_t cr_size = sizeof(cr);
 
-    if ((s = accept(fd, &addr, &addr_size)) < 0) {
+    if ((s = accept(fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
         return;
     }
 
diff --git a/init/readme.txt b/init/readme.txt
index 360a1b7..665090b 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -194,6 +194,9 @@
 symlink <target> <path>
    Create a symbolic link at <path> with the value <target>
 
+sysclktz <mins_west_of_gmt>
+   Set the system clock base (0 if system clock ticks in GMT)
+
 trigger <event>
    Trigger an event.  Used to queue an action from another
    action.