am b01c52aa: am d106305f: Merge "Lose getenforce and setenforce to toybox."

* commit 'b01c52aac2cc80a40e0b5e1c3b8f1a96eb064ecc':
  Lose getenforce and setenforce to toybox.
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/init/init.c b/init/init.c
index 7ddab80..d1845dd 100644
--- a/init/init.c
+++ b/init/init.c
@@ -540,17 +540,35 @@
     return (list_tail(&act->commands) == &cmd->clist);
 }
 
+
+void build_triggers_string(char *name_str, int length, struct action *cur_action) {
+    struct listnode *node;
+    struct trigger *cur_trigger;
+
+    list_for_each(node, &cur_action->triggers) {
+        cur_trigger = node_to_item(node, struct trigger, nlist);
+        if (node != cur_action->triggers.next) {
+            strlcat(name_str, " " , length);
+        }
+        strlcat(name_str, cur_trigger->name , length);
+    }
+}
+
 void execute_one_command(void)
 {
     int ret, i;
     char cmd_str[256] = "";
+    char name_str[256] = "";
 
     if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
         cur_action = action_remove_queue_head();
         cur_command = NULL;
         if (!cur_action)
             return;
-        INFO("processing action %p (%s)\n", cur_action, cur_action->name);
+
+        build_triggers_string(name_str, sizeof(name_str), cur_action);
+
+        INFO("processing action %p (%s)\n", cur_action, name_str);
         cur_command = get_first_command(cur_action);
     } else {
         cur_command = get_next_command(cur_action, cur_command);
@@ -568,7 +586,7 @@
             }
         }
         INFO("command '%s' action=%s status=%d (%s:%d)\n",
-             cmd_str, cur_action ? cur_action->name : "", ret, cur_command->filename,
+             cmd_str, cur_action ? name_str : "", ret, cur_command->filename,
              cur_command->line);
     }
 }
diff --git a/init/init.h b/init/init.h
index a7615a3..e03bd53 100644
--- a/init/init.h
+++ b/init/init.h
@@ -37,6 +37,11 @@
     char *args[1];
 };
 
+struct trigger {
+    struct listnode nlist;
+    const char *name;
+};
+
 struct action {
         /* node in list of all actions */
     struct listnode alist;
@@ -46,12 +51,15 @@
     struct listnode tlist;
 
     unsigned hash;
-    const char *name;
 
+        /* list of actions which triggers the commands*/
+    struct listnode triggers;
     struct listnode commands;
     struct command *current;
 };
 
+void build_triggers_string(char *name_str, int length, struct action *cur_action);
+
 struct socketinfo {
     struct socketinfo *next;
     const char *name;
diff --git a/init/init_parser.c b/init/init_parser.c
index 2b4db8e..a124fa2 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -499,77 +499,92 @@
 void action_for_each_trigger(const char *trigger,
                              void (*func)(struct action *act))
 {
-    struct listnode *node;
+    struct listnode *node, *node2;
     struct action *act;
+    struct trigger *cur_trigger;
+
     list_for_each(node, &action_list) {
         act = node_to_item(node, struct action, alist);
-        if (!strcmp(act->name, trigger)) {
-            func(act);
+        list_for_each(node2, &act->triggers) {
+            cur_trigger = node_to_item(node2, struct trigger, nlist);
+            if (!strcmp(cur_trigger->name, trigger)) {
+                func(act);
+            }
         }
     }
 }
 
+
 void queue_property_triggers(const char *name, const char *value)
 {
-    struct listnode *node;
+    struct listnode *node, *node2;
     struct action *act;
+    struct trigger *cur_trigger;
+    bool match;
+    int name_length;
+
     list_for_each(node, &action_list) {
         act = node_to_item(node, struct action, alist);
-        if (!strncmp(act->name, "property:", strlen("property:"))) {
-            const char *test = act->name + strlen("property:");
-            int name_length = strlen(name);
+            match = !name;
+        list_for_each(node2, &act->triggers) {
+            cur_trigger = node_to_item(node2, struct trigger, nlist);
+            if (!strncmp(cur_trigger->name, "property:", strlen("property:"))) {
+                const char *test = cur_trigger->name + strlen("property:");
+                if (!match) {
+                    name_length = strlen(name);
+                    if (!strncmp(name, test, name_length) &&
+                        test[name_length] == '=' &&
+                        (!strcmp(test + name_length + 1, value) ||
+                        !strcmp(test + name_length + 1, "*"))) {
+                        match = true;
+                        continue;
+                    }
+                } else {
+                     const char* equals = strchr(test, '=');
+                     if (equals) {
+                         char prop_name[PROP_NAME_MAX + 1];
+                         char value[PROP_VALUE_MAX];
+                         int length = equals - test;
+                         if (length <= PROP_NAME_MAX) {
+                             int ret;
+                             memcpy(prop_name, test, length);
+                             prop_name[length] = 0;
 
-            if (!strncmp(name, test, name_length) &&
-                    test[name_length] == '=' &&
-                    (!strcmp(test + name_length + 1, value) ||
-                     !strcmp(test + name_length + 1, "*"))) {
-                action_add_queue_tail(act);
-            }
+                             /* does the property exist, and match the trigger value? */
+                             ret = property_get(prop_name, value);
+                             if (ret > 0 && (!strcmp(equals + 1, value) ||
+                                !strcmp(equals + 1, "*"))) {
+                                 continue;
+                             }
+                         }
+                     }
+                 }
+             }
+             match = false;
+             break;
+        }
+        if (match) {
+            action_add_queue_tail(act);
         }
     }
 }
 
 void queue_all_property_triggers()
 {
-    struct listnode *node;
-    struct action *act;
-    list_for_each(node, &action_list) {
-        act = node_to_item(node, struct action, alist);
-        if (!strncmp(act->name, "property:", strlen("property:"))) {
-            /* parse property name and value
-               syntax is property:<name>=<value> */
-            const char* name = act->name + strlen("property:");
-            const char* equals = strchr(name, '=');
-            if (equals) {
-                char prop_name[PROP_NAME_MAX + 1];
-                char value[PROP_VALUE_MAX];
-                int length = equals - name;
-                if (length > PROP_NAME_MAX) {
-                    ERROR("property name too long in trigger %s", act->name);
-                } else {
-                    int ret;
-                    memcpy(prop_name, name, length);
-                    prop_name[length] = 0;
-
-                    /* does the property exist, and match the trigger value? */
-                    ret = property_get(prop_name, value);
-                    if (ret > 0 && (!strcmp(equals + 1, value) ||
-                                    !strcmp(equals + 1, "*"))) {
-                        action_add_queue_tail(act);
-                    }
-                }
-            }
-        }
-    }
+    queue_property_triggers(NULL, NULL);
 }
 
 void queue_builtin_action(int (*func)(int nargs, char **args), char *name)
 {
     struct action *act;
     struct command *cmd;
+    struct trigger *cur_trigger;
 
     act = calloc(1, sizeof(*act));
-    act->name = name;
+    cur_trigger = calloc(1, sizeof(*cur_trigger));
+    cur_trigger->name = name;
+    list_init(&act->triggers);
+    list_add_tail(&act->triggers, &cur_trigger->nlist);
     list_init(&act->commands);
     list_init(&act->qlist);
 
@@ -611,6 +626,7 @@
 static void *parse_service(struct parse_state *state, int nargs, char **args)
 {
     struct service *svc;
+    struct trigger *cur_trigger;
     if (nargs < 3) {
         parse_error(state, "services must have a name and a program\n");
         return 0;
@@ -635,9 +651,12 @@
     svc->name = args[1];
     svc->classname = "default";
     memcpy(svc->args, args + 2, sizeof(char*) * nargs);
+    cur_trigger = calloc(1, sizeof(*cur_trigger));
     svc->args[nargs] = 0;
     svc->nargs = nargs;
-    svc->onrestart.name = "onrestart";
+    list_init(&svc->onrestart.triggers);
+    cur_trigger->name = "onrestart";
+    list_add_tail(&svc->onrestart.triggers, &cur_trigger->nlist);
     list_init(&svc->onrestart.commands);
     list_add_tail(&service_list, &svc->slist);
     return svc;
@@ -821,16 +840,29 @@
 static void *parse_action(struct parse_state *state, int nargs, char **args)
 {
     struct action *act;
+    struct trigger *cur_trigger;
+    int i;
     if (nargs < 2) {
         parse_error(state, "actions must have a trigger\n");
         return 0;
     }
-    if (nargs > 2) {
-        parse_error(state, "actions may not have extra parameters\n");
-        return 0;
-    }
+
     act = calloc(1, sizeof(*act));
-    act->name = args[1];
+    list_init(&act->triggers);
+
+    for (i = 1; i < nargs; i++) {
+        if (!(i % 2)) {
+            if (strcmp(args[i], "&&")) {
+                parse_error(state, "& is the only symbol allowed to concatenate actions\n");
+                return 0;
+            } else
+                continue;
+        }
+        cur_trigger = calloc(1, sizeof(*cur_trigger));
+        cur_trigger->name = args[i];
+        list_add_tail(&act->triggers, &cur_trigger->nlist);
+    }
+
     list_init(&act->commands);
     list_init(&act->qlist);
     list_add_tail(&action_list, &act->alist);
diff --git a/init/parser.c b/init/parser.c
index 48e7aec..80bfb09 100644
--- a/init/parser.c
+++ b/init/parser.c
@@ -15,9 +15,10 @@
     struct command *cmd;
     struct listnode *node;
     struct listnode *node2;
+    char name_str[256] = "";
     struct socketinfo *si;
     int n;
-    
+
     list_for_each(node, &service_list) {
         svc = node_to_item(node, struct service, slist);
         RAW("service %s\n", svc->name);
@@ -34,7 +35,11 @@
 
     list_for_each(node, &action_list) {
         act = node_to_item(node, struct action, alist);
-        RAW("on %s\n", act->name);
+        RAW("on ");
+        build_triggers_string(name_str, sizeof(name_str), act);
+        RAW("%s", name_str);
+        RAW("\n");
+
         list_for_each(node2, &act->commands) {
             cmd = node_to_item(node2, struct command, clist);
             RAW("  %p", cmd->func);
diff --git a/init/readme.txt b/init/readme.txt
index 750d953..0b43fd5 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -123,6 +123,15 @@
    Triggers of this form occur when the property <name> is set
    to the specific value <value>.
 
+   One can also test Mutliple properties to execute a group
+   of commands. For example:
+
+   on property:test.a=1 && property:test.b=1
+       setprop test.c 1
+
+   The above stub sets test.c to 1 only when
+   both test.a=1 and test.b=1
+
 Commands
 --------
 
diff --git a/libion/ion.c b/libion/ion.c
index a79525d..27ec47a 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -90,6 +90,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,
     };
@@ -102,16 +103,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;
 }
 
@@ -128,11 +130,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 cbcb842..c0efeb1 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
@@ -520,6 +524,7 @@
     onrestart restart zygote
     onrestart restart media
     onrestart restart surfaceflinger
+    onrestart restart inputflinger
     onrestart restart drm
 
 service vold /system/bin/vold
@@ -553,6 +558,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