Merge "Fix a race in system properties."
diff --git a/adb/services.c b/adb/services.c
index c22ce17..7eab17a 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -32,7 +32,7 @@
 #    include <netdb.h>
 #  endif
 #else
-#  include <sys/reboot.h>
+#  include <cutils/android_reboot.h>
 #endif
 
 typedef struct stinfo stinfo;
@@ -193,8 +193,7 @@
         waitpid(pid, &ret, 0);
     }
 
-    ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
-                    LINUX_REBOOT_CMD_RESTART2, (char *)arg);
+    ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
     if (ret < 0) {
         snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
         writex(fd, buf, strlen(buf));
diff --git a/include/arch/darwin-x86/AndroidConfig.h b/include/arch/darwin-x86/AndroidConfig.h
index d99072a..c8ccc7e 100644
--- a/include/arch/darwin-x86/AndroidConfig.h
+++ b/include/arch/darwin-x86/AndroidConfig.h
@@ -305,12 +305,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h
index 9703c76..d828bd5 100644
--- a/include/arch/freebsd-x86/AndroidConfig.h
+++ b/include/arch/freebsd-x86/AndroidConfig.h
@@ -363,12 +363,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h
index 5138d90..83891cd 100644
--- a/include/arch/linux-arm/AndroidConfig.h
+++ b/include/arch/linux-arm/AndroidConfig.h
@@ -361,12 +361,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/include/arch/linux-ppc/AndroidConfig.h b/include/arch/linux-ppc/AndroidConfig.h
index 60bddd6..00706dc 100644
--- a/include/arch/linux-ppc/AndroidConfig.h
+++ b/include/arch/linux-ppc/AndroidConfig.h
@@ -323,12 +323,4 @@
  */
 #define HAVE_PREAD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/linux-sh/AndroidConfig.h b/include/arch/linux-sh/AndroidConfig.h
index 9303bb6..5562eae 100644
--- a/include/arch/linux-sh/AndroidConfig.h
+++ b/include/arch/linux-sh/AndroidConfig.h
@@ -366,12 +366,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/include/arch/linux-x86/AndroidConfig.h b/include/arch/linux-x86/AndroidConfig.h
index 6fd26ea..7dcaa98 100644
--- a/include/arch/linux-x86/AndroidConfig.h
+++ b/include/arch/linux-x86/AndroidConfig.h
@@ -333,12 +333,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h
index a6f7090..05dd220 100644
--- a/include/arch/target_linux-x86/AndroidConfig.h
+++ b/include/arch/target_linux-x86/AndroidConfig.h
@@ -350,12 +350,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/include/arch/windows/AndroidConfig.h b/include/arch/windows/AndroidConfig.h
index 8a7e062..ad890b4 100644
--- a/include/arch/windows/AndroidConfig.h
+++ b/include/arch/windows/AndroidConfig.h
@@ -338,10 +338,4 @@
  */
 /* #define HAVE_PRINTF_ZD 1 */
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * We don't define it on Windows since it is part of the io headers.
- */
-/* #define O_BINARY 0 */
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/cutils/android_reboot.h b/include/cutils/android_reboot.h
new file mode 100644
index 0000000..0c79be7
--- /dev/null
+++ b/include/cutils/android_reboot.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef __CUTILS_ANDROID_REBOOT_H__
+#define __CUTILS_ANDROID_REBOOT_H__
+
+__BEGIN_DECLS
+
+/* Commands */
+#define ANDROID_RB_RESTART  0xDEAD0001
+#define ANDROID_RB_POWEROFF 0xDEAD0002
+#define ANDROID_RB_RESTART2 0xDEAD0003
+
+/* Flags */
+#define ANDROID_RB_FLAG_NO_SYNC       0x1
+#define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2
+
+int android_reboot(int cmd, int flags, char *arg);
+
+__END_DECLS
+
+#endif /* __CUTILS_ANDROID_REBOOT_H__ */
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
new file mode 100644
index 0000000..1b3b762
--- /dev/null
+++ b/include/cutils/bitops.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef __CUTILS_BITOPS_H
+#define __CUTILS_BITOPS_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+static inline int popcount(unsigned int x)
+{
+    return __builtin_popcount(x);
+}
+
+static inline int popcountl(unsigned long x)
+{
+    return __builtin_popcountl(x);
+}
+
+static inline int popcountll(unsigned long long x)
+{
+    return __builtin_popcountll(x);
+}
+
+__END_DECLS
+
+#endif /* __CUTILS_BITOPS_H */
diff --git a/init/builtins.c b/init/builtins.c
index d9a9634..f2f76b7 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -286,7 +286,6 @@
     unsigned flags = 0;
     int n, i;
     int wait = 0;
-    char *prop;
 
     for (n = 4; n < nargs; n++) {
         for (i = 0; mount_flags[i].name; i++) {
@@ -416,6 +415,8 @@
      * unencrypted, and also trigger the action for a nonencrypted system.
      */
     if (!strcmp(target, DATA_MNT_POINT)) {
+        const char *prop;
+
         prop = property_get("ro.crypto.state");
         if (! prop) {
             prop = "notset";
@@ -631,6 +632,14 @@
     return -1;
 }
 
+int do_load_persist_props(int nargs, char **args) {
+    if (nargs == 1) {
+        load_persist_props();
+        return 0;
+    }
+    return -1;
+}
+
 int do_wait(int nargs, char **args)
 {
     if (nargs == 2) {
diff --git a/init/init_parser.c b/init/init_parser.c
index 0898ae8..e8e65ac 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -113,6 +113,7 @@
         break;
     case 'l':
         if (!strcmp(s, "oglevel")) return K_loglevel;
+        if (!strcmp(s, "oad_persist_props")) return K_load_persist_props;
         break;
     case 'm':
         if (!strcmp(s, "kdir")) return K_mkdir;
diff --git a/init/keywords.h b/init/keywords.h
index c977fd7..95acd01 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -30,6 +30,7 @@
 int do_chown(int nargs, char **args);
 int do_chmod(int nargs, char **args);
 int do_loglevel(int nargs, char **args);
+int do_load_persist_props(int nargs, char **args);
 int do_wait(int nargs, char **args);
 #define __MAKE_KEYWORD_ENUM__
 #define KEYWORD(symbol, flags, nargs, func) K_##symbol,
@@ -81,6 +82,7 @@
     KEYWORD(chown,       COMMAND, 2, do_chown)
     KEYWORD(chmod,       COMMAND, 2, do_chmod)
     KEYWORD(loglevel,    COMMAND, 1, do_loglevel)
+    KEYWORD(load_persist_props,    COMMAND, 0, do_load_persist_props)
     KEYWORD(ioprio,      OPTION,  0, 0)
 #ifdef __MAKE_KEYWORD_ENUM__
     KEYWORD_COUNT,
diff --git a/init/property_service.c b/init/property_service.c
index fdfec43..be56a19 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -515,6 +515,18 @@
     return property_area_inited;
 }
 
+/* When booting an encrypted system, /data is not mounted when the
+ * property service is started, so any properties stored there are
+ * not loaded.  Vold triggers init to load these properties once it
+ * has mounted /data.
+ */
+void load_persist_props(void)
+{
+    load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);
+    /* Read persistent properties after all default values have been loaded. */
+    load_persistent_properties();
+}
+
 void start_property_service(void)
 {
     int fd;
diff --git a/init/property_service.h b/init/property_service.h
index 045d20a..bc97cc4 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -19,6 +19,7 @@
 
 extern void handle_property_set_fd(void);
 extern void property_init(void);
+extern void load_persist_props(void);
 extern void start_property_service(void);
 void get_property_workspace(int *fd, int *sz);
 extern const char* property_get(const char *name);
diff --git a/init/signal_handler.c b/init/signal_handler.c
index 833e59d..f89d058 100644
--- a/init/signal_handler.c
+++ b/init/signal_handler.c
@@ -23,7 +23,7 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <cutils/sockets.h>
-#include <sys/reboot.h>
+#include <cutils/android_reboot.h>
 
 #include "init.h"
 #include "list.h"
@@ -96,9 +96,7 @@
                 ERROR("critical process '%s' exited %d times in %d minutes; "
                       "rebooting into recovery mode\n", svc->name,
                       CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
-                sync();
-                __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
-                         LINUX_REBOOT_CMD_RESTART2, "recovery");
+                android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
                 return 0;
             }
         } else {
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 3dc3d69..b6c5382 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -109,7 +109,7 @@
 # ========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := libcutils
-LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c
+LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c android_reboot.c
 
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_SRC_FILES += arch-arm/memset32.S
diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c
new file mode 100644
index 0000000..33a7358
--- /dev/null
+++ b/libcutils/android_reboot.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 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 <unistd.h>
+#include <sys/reboot.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <cutils/android_reboot.h>
+
+/* Check to see if /proc/mounts contains any writeable filesystems
+ * backed by a block device.
+ * Return true if none found, else return false.
+ */
+static int remount_ro_done(void)
+{
+    FILE *f;
+    char mount_dev[256];
+    char mount_dir[256];
+    char mount_type[256];
+    char mount_opts[256];
+    int mount_freq;
+    int mount_passno;
+    int match;
+    int found_rw_fs = 0;
+
+    f = fopen("/proc/mounts", "r");
+    if (! f) {
+        /* If we can't read /proc/mounts, just give up */
+        return 1;
+    }
+
+    do {
+        match = fscanf(f, "%255s %255s %255s %255s %d %d\n",
+                       mount_dev, mount_dir, mount_type,
+                       mount_opts, &mount_freq, &mount_passno);
+        mount_dev[255] = 0;
+        mount_dir[255] = 0;
+        mount_type[255] = 0;
+        mount_opts[255] = 0;
+        if ((match == 6) && !strncmp(mount_dev, "/dev/block", 10) && strstr(mount_opts, "rw")) {
+            found_rw_fs = 1;
+            break;
+        }
+    } while (match != EOF);
+
+    fclose(f);
+
+    return !found_rw_fs;
+}
+
+/* Remounting filesystems read-only is difficult when there are files
+ * opened for writing or pending deletes on the filesystem.  There is
+ * no way to force the remount with the mount(2) syscall.  The magic sysrq
+ * 'u' command does an emergency remount read-only on all writable filesystems
+ * that have a block device (i.e. not tmpfs filesystems) by calling
+ * emergency_remount(), which knows how to force the remount to read-only.
+ * Unfortunately, that is asynchronous, and just schedules the work and
+ * returns.  The best way to determine if it is done is to read /proc/mounts
+ * repeatedly until there are no more writable filesystems mounted on
+ * block devices.
+ */
+static void remount_ro(void)
+{
+    int fd, cnt = 0;
+
+    /* Trigger the remount of the filesystems as read-only,
+     * which also marks them clean.
+     */
+    fd = open("/proc/sysrq-trigger", O_WRONLY);
+    if (fd < 0) {
+        return;
+    }
+    write(fd, "u", 1);
+    close(fd);
+
+
+    /* Now poll /proc/mounts till it's done */
+    while (!remount_ro_done() && (cnt < 50)) {
+        usleep(100000);
+        cnt++;
+    }
+
+    return;
+}
+
+
+int android_reboot(int cmd, int flags, char *arg)
+{
+    int ret;
+
+    if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
+        sync();
+
+    if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
+        remount_ro();
+
+    switch (cmd) {
+        case ANDROID_RB_RESTART:
+            ret = reboot(RB_AUTOBOOT);
+            break;
+
+        case ANDROID_RB_POWEROFF:
+            ret = reboot(RB_POWER_OFF);
+            break;
+
+        case ANDROID_RB_RESTART2:
+            ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                           LINUX_REBOOT_CMD_RESTART2, arg);
+            break;
+
+        default:
+            ret = -1;
+    }
+
+    return ret;
+}
+
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index f5a7c3f..b1c967d 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -53,6 +53,9 @@
 #define USB_FS_ID_SCANNER   "/dev/bus/usb/%d/%d"
 #define USB_FS_ID_FORMAT    "/dev/bus/usb/%03d/%03d"
 
+// From drivers/usb/core/devio.c
+// I don't know why this isn't in a kernel header
+#define MAX_USBFS_BUFFER_SIZE   16384
 
 struct usb_host_context {
     int fd;
@@ -477,6 +480,10 @@
 {
     struct usbdevfs_bulktransfer  ctrl;
 
+    // need to limit request size to avoid EINVAL
+    if (length > MAX_USBFS_BUFFER_SIZE)
+        length = MAX_USBFS_BUFFER_SIZE;
+
     memset(&ctrl, 0, sizeof(ctrl));
     ctrl.ep = endpoint;
     ctrl.len = length;
@@ -531,7 +538,11 @@
 
     urb->status = -1;
     urb->buffer = req->buffer;
-    urb->buffer_length = req->buffer_length;
+    // need to limit request size to avoid EINVAL
+    if (req->buffer_length > MAX_USBFS_BUFFER_SIZE)
+        urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
+    else
+        urb->buffer_length = req->buffer_length;
 
     do {
         res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb);
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 046ab3d..7f5a38f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -295,6 +295,9 @@
     setprop net.tcp.buffersize.edge    4093,26280,35040,4096,16384,35040
     setprop net.tcp.buffersize.gprs    4092,8760,11680,4096,8760,11680
 
+# Set this property so surfaceflinger is not started by system_init
+    setprop system_init.startsurfaceflinger 0
+
     class_start core
     class_start main
 
@@ -304,6 +307,9 @@
 on property:vold.decrypt=trigger_reset_main
     class_reset main
 
+on property:vold.decrypt=trigger_load_persist_props
+    load_persist_props
+
 on property:vold.decrypt=trigger_post_fs_data
     trigger post-fs-data
 
@@ -377,18 +383,25 @@
     user root
     group radio cache inet misc audio sdcard_rw
 
+service surfaceflinger /system/bin/surfaceflinger
+    class main
+    user system
+    group graphics
+    onrestart restart zygote
+
 service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
     class main
     socket zygote stream 666
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
+    onrestart restart surfaceflinger
     onrestart restart media
     onrestart restart netd
 
 service drm /system/bin/drmserver
     class main
     user drm
-    group inet
+    group inet system
 
 service media /system/bin/mediaserver
     class main
diff --git a/toolbox/reboot.c b/toolbox/reboot.c
index aebe185..f8546de 100644
--- a/toolbox/reboot.c
+++ b/toolbox/reboot.c
@@ -1,7 +1,7 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/reboot.h>
+#include <cutils/android_reboot.h>
 #include <unistd.h>
 
 int reboot_main(int argc, char *argv[])
@@ -9,6 +9,7 @@
     int ret;
     int nosync = 0;
     int poweroff = 0;
+    int flags = 0;
 
     opterr = 0;
     do {
@@ -38,15 +39,16 @@
         exit(EXIT_FAILURE);
     }
 
-    if(!nosync)
-        sync();
+    if(nosync)
+        /* also set NO_REMOUNT_RO as remount ro includes an implicit sync */
+        flags = ANDROID_RB_FLAG_NO_SYNC | ANDROID_RB_FLAG_NO_REMOUNT_RO;
 
     if(poweroff)
-        ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL);
+        ret = android_reboot(ANDROID_RB_POWEROFF, flags, 0);
     else if(argc > optind)
-        ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, argv[optind]);
+        ret = android_reboot(ANDROID_RB_RESTART2, flags, argv[optind]);
     else
-        ret = reboot(RB_AUTOBOOT);
+        ret = android_reboot(ANDROID_RB_RESTART, flags, 0);
     if(ret < 0) {
         perror("reboot");
         exit(EXIT_FAILURE);
diff --git a/toolbox/wipe.c b/toolbox/wipe.c
index 7e263fd..650a0d6 100644
--- a/toolbox/wipe.c
+++ b/toolbox/wipe.c
@@ -5,7 +5,7 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/reboot.h>
+#include <cutils/android_reboot.h>
 #include <sys/stat.h>
 
 #ifndef PATH_MAX
@@ -63,7 +63,7 @@
 		wipe ("/system");
         wipe ("/data");
 		fprintf(stdout, "Device nuked! Rebooting...\n");
-		ret = reboot(RB_AUTOBOOT);
+		ret = android_reboot(ANDROID_RB_RESTART, 0, 0);
 	    if (ret < 0) {
 	        fprintf(stderr, "Reboot failed, %s\n", strerror(errno));
 	        return 1;