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.