am 0feae044: am 46adfa69: Merge "init: Add support "&&" operator in property triggers"

* commit '0feae044f077bd32ba49ef074eacac7d1e704b8f':
  init: Add support "&&" operator in property triggers
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 959d3ad..2dc8ced 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -295,9 +295,8 @@
             "                                           Can override the fs type and/or\n"
             "                                           size the bootloader reports.\n"
             "  getvar <variable>                        display a bootloader variable\n"
-            "  boot <kernel> [ <ramdisk> [ <second> ] ] download and boot kernel\n"
-            "  flash:raw boot <kernel> [ <ramdisk> [ <second> ] ] create bootimage and \n"
-            "                                           flash it\n"
+            "  boot <kernel> [ <ramdisk> ]              download and boot kernel\n"
+            "  flash:raw boot <kernel> [ <ramdisk> ]    create bootimage and flash it\n"
             "  devices                                  list all connected devices\n"
             "  continue                                 continue with autoboot\n"
             "  reboot                                   reboot device normally\n"
@@ -325,11 +324,10 @@
 }
 
 void *load_bootable_image(const char *kernel, const char *ramdisk,
-                          const char *secondstage, unsigned *sz,
-                          const char *cmdline)
+                          unsigned *sz, const char *cmdline)
 {
-    void *kdata = 0, *rdata = 0, *sdata = 0;
-    unsigned ksize = 0, rsize = 0, ssize = 0;
+    void *kdata = 0, *rdata = 0;
+    unsigned ksize = 0, rsize = 0;
     void *bdata;
     unsigned bsize;
 
@@ -365,18 +363,10 @@
         }
     }
 
-    if (secondstage) {
-        sdata = load_file(secondstage, &ssize);
-        if(sdata == 0) {
-            fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
-            return  0;
-        }
-    }
-
     fprintf(stderr,"creating boot image...\n");
     bdata = mkbootimg(kdata, ksize, kernel_offset,
                       rdata, rsize, ramdisk_offset,
-                      sdata, ssize, second_offset,
+                      0, 0, second_offset,
                       page_size, base_addr, tags_offset, &bsize);
     if(bdata == 0) {
         fprintf(stderr,"failed to create boot.img\n");
@@ -1162,7 +1152,6 @@
         } else if(!strcmp(*argv, "boot")) {
             char *kname = 0;
             char *rname = 0;
-            char *sname = 0;
             skip(1);
             if (argc > 0) {
                 kname = argv[0];
@@ -1172,11 +1161,7 @@
                 rname = argv[0];
                 skip(1);
             }
-            if (argc > 0) {
-                sname = argv[0];
-                skip(1);
-            }
-            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+            data = load_bootable_image(kname, rname, &sz, cmdline);
             if (data == 0) return 1;
             fb_queue_download("boot.img", data, sz);
             fb_queue_command("boot", "booting");
@@ -1200,18 +1185,14 @@
             char *pname = argv[1];
             char *kname = argv[2];
             char *rname = 0;
-            char *sname = 0;
             require(3);
-            skip(3);
-            if (argc > 0) {
-                rname = argv[0];
-                skip(1);
+            if(argc > 3) {
+                rname = argv[3];
+                skip(4);
+            } else {
+                skip(3);
             }
-            if (argc > 0) {
-                sname = argv[0];
-                skip(1);
-            }
-            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+            data = load_bootable_image(kname, rname, &sz, cmdline);
             if (data == 0) die("cannot load bootable image");
             fb_queue_flash(pname, data, sz);
         } else if(!strcmp(*argv, "flashall")) {
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 1fee855..b0002cc 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -53,6 +53,7 @@
     .batteryCurrentAvgPath = String8(String8::kEmptyString),
     .batteryChargeCounterPath = String8(String8::kEmptyString),
     .energyCounter = NULL,
+    .boot_min_cap = 0,
     .screen_on = NULL,
 };
 
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 4704f0b..84b6d76 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -67,6 +67,7 @@
     android::String8 batteryChargeCounterPath;
 
     int (*energyCounter)(int64_t *);
+    int boot_min_cap;
     bool (*screen_on)(android::BatteryProperties *props);
 };
 
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 9ed5944..8931983 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -116,6 +116,7 @@
 
     struct animation *batt_anim;
     gr_surface surf_unknown;
+    int boot_min_cap;
 };
 
 static struct frame batt_anim_frames[] = {
@@ -520,19 +521,29 @@
                     LOGW("[%" PRId64 "] booting from charger mode\n", now);
                     property_set("sys.boot_from_charger_mode", "1");
                 } else {
-                    LOGW("[%" PRId64 "] rebooting\n", now);
-                    android_reboot(ANDROID_RB_RESTART, 0, 0);
+                    if (charger->batt_anim->capacity >= charger->boot_min_cap) {
+                        LOGW("[%" PRId64 "] rebooting\n", now);
+                        android_reboot(ANDROID_RB_RESTART, 0, 0);
+                    } else {
+                        LOGV("[%lld] ignore power-button press, battery level "
+                            "less than minimum\n", now);
+                    }
                 }
             } else {
                 /* if the key is pressed but timeout hasn't expired,
                  * make sure we wake up at the right-ish time to check
                  */
                 set_next_key_check(charger, key, POWER_ON_KEY_TIME);
+
+               /* Turn on the display and kick animation on power-key press
+                * rather than on key release
+                */
+                kick_animation(charger->batt_anim);
+                request_suspend(false);
             }
         } else {
             /* if the power key got released, force screen state cycle */
             if (key->pending) {
-                request_suspend(false);
                 kick_animation(charger->batt_anim);
             }
         }
@@ -555,6 +566,11 @@
         return;
 
     if (!charger->charger_connected) {
+
+        /* Last cycle would have stopped at the extreme top of battery-icon
+         * Need to show the correct level corresponding to capacity.
+         */
+        kick_animation(charger->batt_anim);
         request_suspend(false);
         if (charger->next_pwr_check == -1) {
             charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
@@ -705,4 +721,5 @@
     charger->next_key_check = -1;
     charger->next_pwr_check = -1;
     healthd_config = config;
+    charger->boot_min_cap = config->boot_min_cap;
 }
diff --git a/include/system/camera.h b/include/system/camera.h
index 7a4dd53..09c915d 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -194,7 +194,12 @@
     /** The facing of the camera is opposite to that of the screen. */
     CAMERA_FACING_BACK = 0,
     /** The facing of the camera is the same as that of the screen. */
-    CAMERA_FACING_FRONT = 1
+    CAMERA_FACING_FRONT = 1,
+    /**
+     * The facing of the camera is not fixed relative to the screen.
+     * The cameras with this facing are external cameras, e.g. USB cameras.
+     */
+    CAMERA_FACING_EXTERNAL = 2
 };
 
 enum {
diff --git a/init/builtins.c b/init/builtins.c
index b9b5029..303a8ca 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -205,6 +205,68 @@
     return -1;
 }
 
+int do_execonce(int nargs, char **args)
+{
+    pid_t child;
+    int child_status = 0;
+    static int already_done;
+
+    if (already_done) {
+      return -1;
+    }
+    already_done = 1;
+    if (!(child = fork())) {
+        /*
+         * Child process.
+         */
+        zap_stdio();
+        char *exec_args[100];
+        int i;
+        int num_process_args = nargs;
+
+        memset(exec_args, 0, sizeof(exec_args));
+        if (num_process_args > ARRAY_SIZE(exec_args) - 1) {
+            ERROR("exec called with %d args, limit is %d", num_process_args,
+                  ARRAY_SIZE(exec_args) - 1);
+            _exit(1);
+        }
+        for (i = 1; i < num_process_args; i++)
+            exec_args[i - 1] = args[i];
+
+        if (execv(exec_args[0], exec_args) == -1) {
+            ERROR("Failed to execv '%s' (%s)", exec_args[0], strerror(errno));
+            _exit(1);
+        }
+        ERROR("Returned from execv()!");
+        _exit(1);
+    }
+
+    /*
+     * Parent process.
+     */
+    if (child == -1) {
+        ERROR("Fork failed\n");
+        return -1;
+    }
+
+    if (TEMP_FAILURE_RETRY(waitpid(child, &child_status, 0)) == -1) {
+        ERROR("waitpid(): failed (%s)\n", strerror(errno));
+        return -1;
+    }
+
+    if (WIFSIGNALED(child_status)) {
+        INFO("Child exited due to signal %d\n", WTERMSIG(child_status));
+        return -1;
+    } else if (WIFEXITED(child_status)) {
+        INFO("Child exited normally (exit code %d)\n", WEXITSTATUS(child_status));
+        return WEXITSTATUS(child_status);
+    }
+
+    ERROR("Abnormal child process exit\n");
+
+    return -1;
+}
+
 int do_export(int nargs, char **args)
 {
     return add_environment(args[1], args[2]);
diff --git a/init/init.c b/init/init.c
index d3dd019..096d898 100644
--- a/init/init.c
+++ b/init/init.c
@@ -126,7 +126,7 @@
     return -1;
 }
 
-static void zap_stdio(void)
+void zap_stdio(void)
 {
     int fd;
     fd = open("/dev/null", O_RDWR);
diff --git a/init/init.h b/init/init.h
index e03bd53..654a80b 100644
--- a/init/init.h
+++ b/init/init.h
@@ -149,5 +149,6 @@
 extern struct selabel_handle *sehandle;
 extern struct selabel_handle *sehandle_prop;
 extern int selinux_reload_policy(void);
+void zap_stdio(void);
 
 #endif	/* _INIT_INIT_H */
diff --git a/init/init_parser.c b/init/init_parser.c
index a124fa2..02cbf3d 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -97,6 +97,7 @@
     case 'e':
         if (!strcmp(s, "nable")) return K_enable;
         if (!strcmp(s, "xec")) return K_exec;
+        if (!strcmp(s, "xeconce")) return K_execonce;
         if (!strcmp(s, "xport")) return K_export;
         break;
     case 'g':
diff --git a/init/keywords.h b/init/keywords.h
index 2d97e5b..7473586 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -8,6 +8,7 @@
 int do_domainname(int nargs, char **args);
 int do_enable(int nargs, char **args);
 int do_exec(int nargs, char **args);
+int do_execonce(int nargs, char **args);
 int do_export(int nargs, char **args);
 int do_hostname(int nargs, char **args);
 int do_ifup(int nargs, char **args);
@@ -59,6 +60,7 @@
     KEYWORD(domainname,  COMMAND, 1, do_domainname)
     KEYWORD(enable,      COMMAND, 1, do_enable)
     KEYWORD(exec,        COMMAND, 1, do_exec)
+    KEYWORD(execonce,    COMMAND, 1, do_execonce)
     KEYWORD(export,      COMMAND, 2, do_export)
     KEYWORD(group,       OPTION,  0, 0)
     KEYWORD(hostname,    COMMAND, 1, do_hostname)
diff --git a/init/readme.txt b/init/readme.txt
index 0b43fd5..132a869 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -136,10 +136,14 @@
 --------
 
 exec <path> [ <argument> ]*
+   This command is not implemented.
+
+execonce <path> [ <argument> ]*
    Fork and execute a program (<path>).  This will block until
-   the program completes execution.  It is best to avoid exec
-   as unlike the builtin commands, it runs the risk of getting
-   init "stuck". (??? maybe there should be a timeout?)
+   the program completes execution.  This command can be run at most
+   once during init's lifetime. Subsequent invocations are ignored.
+   It is best to avoid exec as unlike the builtin commands, it runs
+   the risk of getting init "stuck".
 
 export <name> <value>
    Set the environment variable <name> equal to <value> in the
diff --git a/libion/ion.c b/libion/ion.c
index 4908932..d1984bd 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -91,6 +91,7 @@
             int flags, off_t offset, unsigned char **ptr, int *map_fd)
 {
     int ret;
+    unsigned char *tmp_ptr;
     struct ion_fd_data data = {
         .handle = handle,
     };
@@ -103,16 +104,17 @@
     ret = ion_ioctl(fd, ION_IOC_MAP, &data);
     if (ret < 0)
         return ret;
-    *map_fd = data.fd;
-    if (*map_fd < 0) {
+    if (data.fd < 0) {
         ALOGE("map ioctl returned negative fd\n");
         return -EINVAL;
     }
-    *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
-    if (*ptr == MAP_FAILED) {
+    tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset);
+    if (tmp_ptr == MAP_FAILED) {
         ALOGE("mmap failed: %s\n", strerror(errno));
         return -errno;
     }
+    *map_fd = data.fd;
+    *ptr = tmp_ptr;
     return ret;
 }
 
@@ -129,11 +131,11 @@
     ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
     if (ret < 0)
         return ret;
-    *share_fd = data.fd;
-    if (*share_fd < 0) {
+    if (data.fd < 0) {
         ALOGE("share ioctl returned negative fd\n");
         return -EINVAL;
     }
+    *share_fd = data.fd;
     return ret;
 }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 32ca673..1b3518d 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -114,6 +114,10 @@
     # set fwmark on accepted sockets
     write /proc/sys/net/ipv4/tcp_fwmark_accept 1
 
+    # disable icmp redirects
+    write /proc/sys/net/ipv4/conf/all/accept_redirects 0
+    write /proc/sys/net/ipv6/conf/all/accept_redirects 0
+
     # Create cgroup mount points for process groups
     mkdir /dev/cpuctl
     mount cgroup none /dev/cpuctl cpu
@@ -523,6 +527,7 @@
     onrestart restart zygote
     onrestart restart media
     onrestart restart surfaceflinger
+    onrestart restart inputflinger
     onrestart restart drm
 
 service vold /system/bin/vold
@@ -556,6 +561,12 @@
     group graphics drmrpc
     onrestart restart zygote
 
+service inputflinger /system/bin/inputflinger
+    class main
+    user system
+    group input
+    onrestart restart zygote
+
 service drm /system/bin/drmserver
     class main
     user drm