Merge "zip_archive: Remove unused ziparchive-host"
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index 7ed5b2b..121197c 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -51,6 +51,14 @@
   ASSERT_EQ("bar", parts[2]);
 }
 
+TEST(strings, split_with_trailing_empty_part) {
+  std::vector<std::string> parts = android::base::Split("foo,bar,", ",");
+  ASSERT_EQ(3U, parts.size());
+  ASSERT_EQ("foo", parts[0]);
+  ASSERT_EQ("bar", parts[1]);
+  ASSERT_EQ("", parts[2]);
+}
+
 TEST(strings, split_null_char) {
   std::vector<std::string> parts =
       android::base::Split(std::string("foo\0bar", 7), std::string("\0", 1));
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index 209e81b..e69db12 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -194,10 +194,12 @@
               sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
         if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ]
         then
+          sleep 1
           break
         fi
         if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ]
         then
+          sleep 1
           break
         fi
       fi
@@ -287,6 +289,7 @@
 bootstat: Battery level at shutdown 100%
 bootstat: Battery level at startup 100%
 init    : Parsing file /system/etc/init/bootstat.rc...
+init    : Parsing file /system/etc/init/bootstat-debug.rc...
 init    : processing action (persist.test.boot.reason=*) from (/system/etc/init/bootstat-debug.rc:
 init    : Command 'setprop ro.boot.bootreason \${persist.test.boot.reason}' action=persist.test.boot.reason=* (/system/etc/init/bootstat-debug.rc:
 init    : processing action (post-fs-data) from (/system/etc/init/bootstat.rc
@@ -566,6 +569,8 @@
   esac
   adb reboot ${TEST}
   wait_for_screen
+  bootloader_reason=`validate_property ro.boot.bootreason`
+  EXPECT_PROPERTY ro.boot.bootreason ${bootloader_reason}
   EXPECT_PROPERTY sys.boot.reason ${reason}
   EXPECT_PROPERTY persist.sys.boot.reason ${reason}
   report_bootstat_logs ${reason}
@@ -868,17 +873,30 @@
 - NB: should report reboot,its_just_so_hard
 - NB: expect log \"... I bootstat: Unknown boot reason: reboot,its_just_so_hard\"" ]
 test_Its_Just_So_Hard_reboot() {
-  duration_test
+  if isDebuggable; then       # see below
+    duration_test
+  else
+    duration_test `expr ${DURATION_DEFAULT} + ${DURATION_DEFAULT}`
+  fi
   adb shell 'reboot "Its Just So Hard"'
   wait_for_screen
   EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard
   EXPECT_PROPERTY persist.sys.boot.reason "reboot,Its Just So Hard"
-  adb shell su root setprop persist.sys.boot.reason reboot,its_just_so_hard
-  if checkDebugBuild; then
-    flag=""
+  # Do not leave this test with an illegal value in persist.sys.boot.reason
+  save_ret=${?}           # hold on to error code from above two lines
+  if isDebuggable; then   # can do this easy, or we can do this hard.
+    adb shell su root setprop persist.sys.boot.reason reboot,its_just_so_hard
+    ( exit ${save_ret} )  # because one can not just do ?=${save_ret}
   else
-    flag="--allow_failure"
+    report_bootstat_logs reboot,its_just_so_hard  # report what we have so far
+    # user build mitigation
+    adb shell reboot its_just_so_hard
+    wait_for_screen
+    ( exit ${save_ret} )  # because one can not just do ?=${save_ret}
+    EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard
   fi
+  # Ensure persist.sys.boot.reason now valid, failure here acts as a signal
+  # that we could choke up following tests.  For example test_properties.
   EXPECT_PROPERTY persist.sys.boot.reason reboot,its_just_so_hard ${flag}
   report_bootstat_logs reboot,its_just_so_hard
 }
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 2270133..07d410c 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -223,6 +223,10 @@
     {"2sec_reboot", 83},
     {"reboot,by_key", 84},
     {"reboot,longkey", 85},
+    {"reboot,2sec", 86},
+    {"shutdown,thermal,battery", 87},
+    {"reboot,its_just_so_hard", 88},  // produced by boot_reason_test
+    {"reboot,Its Just So Hard", 89},  // produced by boot_reason_test
 };
 
 // Converts a string value representing the reason the system booted to an
@@ -349,10 +353,18 @@
 char tounderline(char c) {
   return ::isblank(c) ? '_' : c;
 }
+
 char toprintable(char c) {
   return ::isprint(c) ? c : '?';
 }
 
+// Cleanup boot_reason regarding acceptable character set
+void transformReason(std::string& reason) {
+  std::transform(reason.begin(), reason.end(), reason.begin(), ::tolower);
+  std::transform(reason.begin(), reason.end(), reason.begin(), tounderline);
+  std::transform(reason.begin(), reason.end(), reason.begin(), toprintable);
+}
+
 const char system_reboot_reason_property[] = "sys.boot.reason";
 const char last_reboot_reason_property[] = LAST_REBOOT_REASON_PROPERTY;
 const char bootloader_reboot_reason_property[] = "ro.boot.bootreason";
@@ -366,10 +378,7 @@
   // If sys.boot.reason == ro.boot.bootreason, let's re-evaluate
   if (reason == ret) ret = "";
 
-  // Cleanup boot_reason regarding acceptable character set
-  std::transform(reason.begin(), reason.end(), reason.begin(), ::tolower);
-  std::transform(reason.begin(), reason.end(), reason.begin(), tounderline);
-  std::transform(reason.begin(), reason.end(), reason.begin(), toprintable);
+  transformReason(reason);
 
   // Is the current system boot reason sys.boot.reason valid?
   if (!isKnownRebootReason(ret)) ret = "";
@@ -406,6 +415,7 @@
         {"shutdown,thermal", "thermal"},
         {"warm,s3_wakeup", "s3_wakeup"},
         {"hard,hw_reset", "hw_reset"},
+        {"reboot,2sec", "2sec_reboot"},
         {"bootloader", ""},
     };
 
@@ -457,18 +467,20 @@
         pos += strlen(cmd);
         std::string subReason(content.substr(pos, max_reason_length));
         for (pos = 0; pos < subReason.length(); ++pos) {
-          char c = tounderline(subReason[pos]);
+          char c = subReason[pos];
           if (!::isprint(c) || (c == '\'')) {
             subReason.erase(pos);
             break;
           }
-          subReason[pos] = ::tolower(c);
         }
+        transformReason(subReason);
         if (subReason != "") {  // Will not land "reboot" as that is too blunt.
           if (isKernelRebootReason(subReason)) {
             ret = "reboot," + subReason;  // User space can't talk kernel reasons.
-          } else {
+          } else if (isKnownRebootReason(subReason)) {
             ret = subReason;
+          } else {
+            ret = "reboot," + subReason;  // legitimize unknown reasons
           }
         }
       }
@@ -560,10 +572,7 @@
       // Content buffer no longer will have console data. Beware if more
       // checks added below, that depend on parsing console content.
       content = GetProperty(last_reboot_reason_property);
-      // Cleanup last_boot_reason regarding acceptable character set
-      std::transform(content.begin(), content.end(), content.begin(), ::tolower);
-      std::transform(content.begin(), content.end(), content.begin(), tounderline);
-      std::transform(content.begin(), content.end(), content.begin(), toprintable);
+      transformReason(content);
 
       // Anything in last is better than 'super-blunt' reboot or shutdown.
       if ((ret == "") || (ret == "reboot") || (ret == "shutdown") || !isBluntRebootReason(content)) {
diff --git a/init/service.cpp b/init/service.cpp
index 765b61e..45e3f06 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -101,8 +101,22 @@
 
     // It's OK to LOG(FATAL) in this function since it's running in the first
     // child process.
-    if (mount("", "/proc", "proc", kSafeFlags | MS_REMOUNT, "") == -1) {
-        PLOG(FATAL) << "couldn't remount(/proc) for " << service_name;
+
+    // Recursively remount / as slave like zygote does so unmounting and mounting /proc
+    // doesn't interfere with the parent namespace's /proc mount. This will also
+    // prevent any other mounts/unmounts initiated by the service from interfering
+    // with the parent namespace but will still allow mount events from the parent
+    // namespace to propagate to the child.
+    if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
+        PLOG(FATAL) << "couldn't remount(/) recursively as slave for " << service_name;
+    }
+    // umount() then mount() /proc.
+    // Note that it is not sufficient to mount with MS_REMOUNT.
+    if (umount("/proc") == -1) {
+        PLOG(FATAL) << "couldn't umount(/proc) for " << service_name;
+    }
+    if (mount("", "/proc", "proc", kSafeFlags, "") == -1) {
+        PLOG(FATAL) << "couldn't mount(/proc) for " << service_name;
     }
 
     if (prctl(PR_SET_NAME, service_name.c_str()) == -1) {
@@ -706,14 +720,20 @@
 }
 
 Result<Success> Service::Start() {
+    bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET));
     // Starting a service removes it from the disabled or reset state and
     // immediately takes it out of the restarting state if it was in there.
     flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
 
     // Running processes require no additional work --- if they're in the
     // process of exiting, we've ensured that they will immediately restart
-    // on exit, unless they are ONESHOT.
+    // on exit, unless they are ONESHOT. For ONESHOT service, if it's in
+    // stopping status, we just set SVC_RESTART flag so it will get restarted
+    // in Reap().
     if (flags_ & SVC_RUNNING) {
+        if ((flags_ & SVC_ONESHOT) && disabled) {
+            flags_ |= SVC_RESTART;
+        }
         // It is not an error to try to start a service that is already running.
         return Success();
     }
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index c3f08c8..62e453f 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -64,7 +64,7 @@
     auto frame = &unwinder_frames[i];
     backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
 
-    back_frame->num = frame->num;
+    back_frame->num = frame->num - num_ignore_frames;
 
     back_frame->rel_pc = frame->rel_pc;
     back_frame->pc = frame->pc;
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index e5eb9e3..c3e5da0 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -1844,6 +1844,22 @@
   UnwindThroughSignal(true, Backtrace::CreateNew, BacktraceMap::CreateNew);
 }
 
+static void TestFrameSkipNumbering(create_func_t create_func, map_create_func_t map_create_func) {
+  std::unique_ptr<BacktraceMap> map(map_create_func(getpid(), false));
+  std::unique_ptr<Backtrace> backtrace(create_func(getpid(), gettid(), map.get()));
+  backtrace->Unwind(1);
+  ASSERT_NE(0U, backtrace->NumFrames());
+  ASSERT_EQ(0U, backtrace->GetFrame(0)->num);
+}
+
+TEST(libbacktrace, unwind_frame_skip_numbering) {
+  TestFrameSkipNumbering(Backtrace::Create, BacktraceMap::Create);
+}
+
+TEST(libbacktrace, unwind_frame_skip_numbering_new) {
+  TestFrameSkipNumbering(Backtrace::CreateNew, BacktraceMap::CreateNew);
+}
+
 #if defined(ENABLE_PSS_TESTS)
 #include "GetPss.h"