Merge "init: use protobuf for serialization of persistent properties"
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index d789808..4314271 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -162,7 +162,7 @@
     fi
   done
   adb logcat -b all -d |
-  grep bootstat |
+  grep bootstat[^e] |
   grep -v -F "bootstat: Service started: /system/bin/bootstat --record_boot_complete${match}
 bootstat: Failed to read /data/misc/bootstat/post_decrypt_time_elapsed: No such file or directory
 bootstat: Failed to parse boot time record: /data/misc/bootstat/post_decrypt_time_elapsed
@@ -176,6 +176,8 @@
 init    : processing action (boot) from (/system/etc/init/bootstat.rc
 init    : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc
 init    : processing action (sys.boot_completed=1 && sys.logbootcomplete=1) from (/system/etc/init/bootstat.rc
+ (/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
+ (/system/bin/bootstat -r post_decrypt_time_elapsed)'
 init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
 init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
 init    : Command 'exec - system log -- /system/bin/bootstat --record_time_since_factory_reset' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
@@ -477,7 +479,7 @@
 [ "USAGE: test_battery
 
 battery test (trick):
-- echo healthd: battery l=2 | adb shell su root tee /dev/kmsg ; adb reboot warm
+- echo healthd: battery l=2 | adb shell su root tee /dev/kmsg ; adb reboot cold
 - (wait until screen is up, boot has completed)
 - adb shell getprop sys.boot.reason
 - NB: should report reboot,battery, unless healthd managed to log
@@ -498,8 +500,12 @@
 - (replace set logd.kernel true to the above, and retry test)" ]
 test_battery() {
   echo "INFO: expected duration of ${TEST} test roughly two minutes" >&2
-  echo healthd: battery l=2 | adb shell su root tee /dev/kmsg >/dev/null
-  adb reboot warm >&2
+  # Send it _many_ times to combat devices with flakey pstore
+  for i in a b c d e f g h i j k l m n o p q r s t u v w x y z; do
+    echo healthd: battery l=2 | adb shell su root tee /dev/kmsg >/dev/null
+  done
+  adb reboot cold >&2
+  adb wait-for-device
   wait_for_screen
   adb shell su root \
     cat /proc/fs/pstore/console-ramoops \
@@ -509,14 +515,17 @@
     grep 'healthd: battery l=2' >/dev/null || (
       if ! EXPECT_PROPERTY sys.boot.reason reboot,battery >/dev/null 2>/dev/null; then
         # retry
-        echo healthd: battery l=2 | adb shell su root tee /dev/kmsg >/dev/null
-        adb reboot warm >&2
+        for i in a b c d e f g h i j k l m n o p q r s t u v w x y z; do
+          echo healthd: battery l=2 | adb shell su root tee /dev/kmsg >/dev/null
+        done
+        adb reboot cold >&2
+        adb wait-for-device
         wait_for_screen
       fi
     )
 
   EXPECT_PROPERTY sys.boot.reason shutdown,battery
-  EXPECT_PROPERTY persist.sys.boot.reason reboot,warm
+  EXPECT_PROPERTY persist.sys.boot.reason reboot,cold
   report_bootstat_logs shutdown,battery "-bootstat: Battery level at shutdown 2%"
 }
 
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 3b8b707..e7f9c11 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -494,7 +494,8 @@
 
       // String is either "reboot,<reason>" or "shutdown,<reason>".
       // We will set if default reasons, only override with detail if thermal.
-      if (!isBluntRebootReason(content)) {
+      if ((android::base::StartsWith(content, ret.c_str()) && (content[ret.length()] == ',')) ||
+          !isBluntRebootReason(content)) {
         // Ok, we want it, let's squash it if secondReason is known.
         pos = content.find(',');
         if (pos != std::string::npos) {
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index 410b854..f06a38f 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -12,16 +12,16 @@
     chown system log /data/misc/bootstat/boot_complete
     chown system log /data/misc/bootstat/boot_complete_no_encryption
     chown system log /data/misc/bootstat/boot_reason
-    chown system log /data/misc/bootstat/bootime.bootloader.1BLE
-    chown system log /data/misc/bootstat/bootime.bootloader.1BLL
-    chown system log /data/misc/bootstat/bootime.bootloader.2BLE
-    chown system log /data/misc/bootstat/bootime.bootloader.2BLL
-    chown system log /data/misc/bootstat/bootime.bootloader.AVB
-    chown system log /data/misc/bootstat/bootime.bootloader.KD
-    chown system log /data/misc/bootstat/bootime.bootloader.KL
-    chown system log /data/misc/bootstat/bootime.bootloader.ODT
-    chown system log /data/misc/bootstat/bootime.bootloader.SW
-    chown system log /data/misc/bootstat/bootime.bootloader.total
+    chown system log /data/misc/bootstat/boottime.bootloader.1BLE
+    chown system log /data/misc/bootstat/boottime.bootloader.1BLL
+    chown system log /data/misc/bootstat/boottime.bootloader.2BLE
+    chown system log /data/misc/bootstat/boottime.bootloader.2BLL
+    chown system log /data/misc/bootstat/boottime.bootloader.AVB
+    chown system log /data/misc/bootstat/boottime.bootloader.KD
+    chown system log /data/misc/bootstat/boottime.bootloader.KL
+    chown system log /data/misc/bootstat/boottime.bootloader.ODT
+    chown system log /data/misc/bootstat/boottime.bootloader.SW
+    chown system log /data/misc/bootstat/boottime.bootloader.total
     chown system log /data/misc/bootstat/build_date
     chown system log /data/misc/bootstat/factory_reset
     chown system log /data/misc/bootstat/factory_reset_boot_complete
@@ -46,7 +46,7 @@
 # property:init.svc.bootanim=running: The boot animation is running
 # property:ro.crypto.type=block: FDE device
 on post-fs-data && property:init.svc.bootanim=running && property:ro.crypto.type=block
-    exec - system log -- /system/bin/bootstat -r post_decrypt_time_elapsed
+    exec_background - system log -- /system/bin/bootstat -r post_decrypt_time_elapsed
 
 # sys.logbootcomplete is a signal to enable the bootstat logging mechanism.
 # This signaling is necessary to prevent logging boot metrics after a runtime
@@ -69,13 +69,7 @@
 # Record boot complete metrics.
 on property:sys.boot_completed=1 && property:sys.logbootcomplete=1
     # Record boot_complete and related stats (decryption, etc).
-    exec - system log -- /system/bin/bootstat --record_boot_complete
-
     # Record the boot reason.
-    exec - system log -- /system/bin/bootstat --record_boot_reason
-
     # Record time since factory reset.
-    exec - system log -- /system/bin/bootstat --record_time_since_factory_reset
-
     # Log all boot events.
-    exec - system log -- /system/bin/bootstat -l
+    exec_background - system log -- /system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l
diff --git a/init/README.md b/init/README.md
index 7df37ff..d7edf21 100644
--- a/init/README.md
+++ b/init/README.md
@@ -381,6 +381,11 @@
   within _argument_.
   Init halts executing commands until the forked process exits.
 
+`exec_background [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]`
+> Fork and execute command with the given arguments. This is handled similarly
+  to the `exec` command. The difference is that init does not halt executing
+  commands until the process exits for `exec_background`.
+
 `exec_start <service>`
 > Start a given service and halt the processing of additional init commands
   until it returns.  The command functions similarly to the `exec` command,
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 5f359cf..be24573 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -148,6 +148,19 @@
     return Success();
 }
 
+static Result<Success> do_exec_background(const std::vector<std::string>& args) {
+    auto service = Service::MakeTemporaryOneshotService(args);
+    if (!service) {
+        return Error() << "Could not create exec background service";
+    }
+    if (auto result = service->Start(); !result) {
+        return Error() << "Could not start exec background service: " << result.error();
+    }
+
+    ServiceList::GetInstance().AddService(std::move(service));
+    return Success();
+}
+
 static Result<Success> do_exec_start(const std::vector<std::string>& args) {
     Service* service = ServiceList::GetInstance().FindService(args[1]);
     if (!service) {
@@ -959,6 +972,7 @@
         {"domainname",              {1,     1,    do_domainname}},
         {"enable",                  {1,     1,    do_enable}},
         {"exec",                    {1,     kMax, do_exec}},
+        {"exec_background",         {1,     kMax, do_exec_background}},
         {"exec_start",              {1,     1,    do_exec_start}},
         {"export",                  {2,     2,    do_export}},
         {"hostname",                {1,     1,    do_hostname}},