Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6290982e authored by Mark Salyzyn's avatar Mark Salyzyn
Browse files

init+bootstat: reduce last reboot reason to canonical alias

To make parsing easier for last reboot reason.  This also ensures that
last boot reason matches the content that is typically returned by the
bootloader or in turn landed in the canonical system boot reason.

Simplify parsing in bootstat.  Adjust and fix boot_reason_test.sh for
new reality.  Allow boot reason tests battery and kernel_panic to pass
if device does not support pstore (empty before and after the test).
If device somehow landed in fastboot mode while waiting for the
display, issue a fastboot reboot to move the test along.  Some cleanup
and standardization changes to the test script.

Test: system/core/bootstat/boot_reason_test.sh
Bug: 63736262
Change-Id: I97d5467c0b4a6d65df3525f1a2d0051db813d5ad
parent be729702
Loading
Loading
Loading
Loading
+170 −43
Original line number Original line Diff line number Diff line
@@ -32,6 +32,78 @@ inFastboot() {
  fastboot devices | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
  fastboot devices | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
}
}


[ "USAGE: inAdb

Returns: true if device is in adb mode" ]
inAdb() {
  adb devices | grep -v 'List of devices attached' | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
}

[ "USAGE: hasPstore

Returns: true if device (likely) has pstore data" ]
hasPstore() {
  if inAdb && [ 0 -eq `adb shell su root ls /sys/fs/pstore | wc -l` ]; then
    false
  fi
}

[ "USAGE: isDebuggable

Returns: true if device is (likely) a debug build" ]
isDebuggable() {
  if inAdb && [ 1 -ne `adb shell getprop ro.debuggable` ]; then
    false
  fi
}

[ "USAGE: checkDebugBuild

Returns: true if device is a userdebug or eng release" ]
checkDebugBuild() {
  if isDebuggable; then
    echo "INFO: '${TEST}' test requires userdebug build"
  else
    echo "ERROR: '${TEST}' test requires userdebug build, skipping FAILURE"
    false
  fi >&2
}

[ "USAGE: enterPstore

Prints a warning string requiring functional pstore

Returns: pstore_ok variable set to true or false" ]
enterPstore() {
  if hasPstore; then
    echo "INFO: '${TEST}' test requires functional and reliable pstore"
    pstore_ok=true
  else
    echo "WARNING: '${TEST}' test requires functional pstore"
    pstore_ok=false
  fi >&2
  ${pstore_ok}
}

[ "USAGE: exitPstore

Prints an error string requiring functional pstore

Returns: clears error if pstore dysfunctional" ]
exitPstore() {
  save_ret=${?}
  if [ ${save_ret} != 0 ]; then
    if hasPstore; then
      return ${save_ret}
    fi
    if [ true = ${pstore_ok} ]; then
      echo "WARNING: '${TEST}' test requires functional pstore"
      return ${save_ret}
    fi
    echo "ERROR: '${TEST}' test requires functional pstore, skipping FAILURE"
  fi >&2
}

[ "USAGE: format_duration <seconds>
[ "USAGE: format_duration <seconds>


human readable output whole seconds, whole minutes or mm:ss" ]
human readable output whole seconds, whole minutes or mm:ss" ]
@@ -77,24 +149,33 @@ wait_for_screen() {
  fi
  fi
  counter=0
  counter=0
  while true; do
  while true; do
    [ 0 = ${counter} ] ||
    if inFastboot; then
      fastboot reboot
    elif inAdb; then
      if [ 0 != ${counter} ]; then
        adb wait-for-device </dev/null >/dev/null 2>/dev/null
        adb wait-for-device </dev/null >/dev/null 2>/dev/null
      fi
      if [ -n "`adb shell getprop sys.boot.reason </dev/null 2>/dev/null`" ]
      then
        vals=`adb shell getprop </dev/null 2>/dev/null |
        vals=`adb shell getprop </dev/null 2>/dev/null |
              sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
              sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
    [ 0 = ${counter} ] ||
        if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ]
      sleep 1
        then
    if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ]; then
          break
          break
        fi
        fi
    if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ]; then
        if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ]
        then
          break
          break
        fi
        fi
      fi
    fi
    counter=`expr ${counter} + 1`
    counter=`expr ${counter} + 1`
    if [ ${counter} -gt ${timeout} ]; then
    if [ ${counter} -gt ${timeout} ]; then
      ${exit_function}
      ${exit_function}
      echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2
      echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2
      return 1
      return 1
    fi
    fi
    sleep 1
  done
  done
  ${exit_function}
  ${exit_function}
}
}
@@ -152,7 +233,7 @@ Report any logs, minus a known blacklist, preserve the current exit status" ]
report_bootstat_logs() {
report_bootstat_logs() {
  save_ret=${?}
  save_ret=${?}
  match=
  match=
  for i in ${*}; do
  for i in "${@}"; do
    if [ X"${i}" != X"${i#-}" ] ; then
    if [ X"${i}" != X"${i#-}" ] ; then
      match="${match}
      match="${match}
${i#-}"
${i#-}"
@@ -211,7 +292,7 @@ end_test() {
  END=`date +%s`
  END=`date +%s`
  duration=`expr ${END} - ${START} 2>/dev/null`
  duration=`expr ${END} - ${START} 2>/dev/null`
  [ 0 = ${duration} ] ||
  [ 0 = ${duration} ] ||
    echo INFO: ${TEST} test duration `format_duration ${duration}` >&2
    echo "INFO: '${TEST}' test duration `format_duration ${duration}`" >&2
  if [ ${save_ret} = 0 ]; then
  if [ ${save_ret} = 0 ]; then
    echo "${GREEN}[       OK ]${NORMAL} ${TEST} ${*}"
    echo "${GREEN}[       OK ]${NORMAL} ${TEST} ${*}"
  else
  else
@@ -329,7 +410,7 @@ ota test
Decision to change the build itself rather than trick bootstat by
Decision to change the build itself rather than trick bootstat by
rummaging through its data files was made." ]
rummaging through its data files was made." ]
test_ota() {
test_ota() {
  echo "INFO: expected duration of ${TEST} test about 5 minutes or more" >&2
  echo "INFO: expected duration of '${TEST}' test >`format_duration 300`" >&2
  echo "      extended by build and flashing times" >&2
  echo "      extended by build and flashing times" >&2
  if [ -z "${TARGET_PRODUCT}" -o \
  if [ -z "${TARGET_PRODUCT}" -o \
       -z "${ANDROID_PRODUCT_OUT}" -o \
       -z "${ANDROID_PRODUCT_OUT}" -o \
@@ -361,7 +442,7 @@ test_ota() {
  popd >&2
  popd >&2
  wait_for_screen
  wait_for_screen
  EXPECT_PROPERTY sys.boot.reason "\(reboot,ota\|bootloader\)"
  EXPECT_PROPERTY sys.boot.reason "\(reboot,ota\|bootloader\)"
  EXPECT_PROPERTY persist.sys.boot.reason reboot,bootloader
  EXPECT_PROPERTY persist.sys.boot.reason bootloader
  report_bootstat_logs reboot,ota bootloader
  report_bootstat_logs reboot,ota bootloader
}
}


@@ -369,8 +450,8 @@ test_ota() {


fast and fake (touch build_date on device to make it different)" ]
fast and fake (touch build_date on device to make it different)" ]
test_optional_ota() {
test_optional_ota() {
  echo "INFO: expected duration of ${TEST} test about 45 seconds" >&2
  checkDebugBuild || return
  echo "WARNING: ${TEST} requires userdebug build" >&2
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 45`" >&2
  adb shell su root touch /data/misc/bootstat/build_date >&2
  adb shell su root touch /data/misc/bootstat/build_date >&2
  adb reboot ota
  adb reboot ota
  wait_for_screen
  wait_for_screen
@@ -379,27 +460,28 @@ test_optional_ota() {
  report_bootstat_logs reboot,ota
  report_bootstat_logs reboot,ota
}
}


[ "USAGE: [TEST=<test>] blind_reboot_test [<match>]
[ "USAGE: [TEST=<test>] blind_reboot_test


Simple tests helper
Simple tests helper
- adb reboot <test>
- adb reboot <test>
- (wait until screen is up, boot has completed)
- (wait until screen is up, boot has completed)
- adb shell getprop sys.boot.reason
- adb shell getprop sys.boot.reason
- NB: should report <test>, or overriden <match>
- NB: should report <test>, or reboot,<test> depending on canonical rules


We interleave the simple reboot tests between the hard/complex ones
We interleave the simple reboot tests between the hard/complex ones
as a means of checking sanity and any persistent side effect of the
as a means of checking sanity and any persistent side effect of the
other tests." ]
other tests." ]
blind_reboot_test() {
blind_reboot_test() {
  if [ -z "${1}" ]; then
  case ${TEST} in
    set ${TEST}
    bootloader | recovery | cold | hard | warm ) reason=${TEST} ;;
  fi
    *)                                           reason=reboot,${TEST} ;;
  echo "INFO: expected duration of ${TEST} test roughly 45 seconds" >&2
  esac
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 45`" >&2
  adb reboot ${TEST}
  adb reboot ${TEST}
  wait_for_screen
  wait_for_screen
  EXPECT_PROPERTY sys.boot.reason ${1}
  EXPECT_PROPERTY sys.boot.reason ${reason}
  EXPECT_PROPERTY persist.sys.boot.reason reboot,${TEST}
  EXPECT_PROPERTY persist.sys.boot.reason ${reason}
  report_bootstat_logs ${1}
  report_bootstat_logs ${reason}
}
}


[ "USAGE: test_cold
[ "USAGE: test_cold
@@ -425,8 +507,8 @@ factory_reset test
Decision to rummage through bootstat data files was made as
Decision to rummage through bootstat data files was made as
a _real_ factory_reset is too destructive to the device." ]
a _real_ factory_reset is too destructive to the device." ]
test_factory_reset() {
test_factory_reset() {
  echo "INFO: expected duration of ${TEST} test roughly 45 seconds" >&2
  checkDebugBuild || return
  echo "WARNING: ${TEST} requires userdebug build" >&2
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 45`" >&2
  adb shell su root rm /data/misc/bootstat/build_date >&2
  adb shell su root rm /data/misc/bootstat/build_date >&2
  adb reboot >&2
  adb reboot >&2
  wait_for_screen
  wait_for_screen
@@ -449,7 +531,7 @@ factory_reset test


For realz, and disruptive" ]
For realz, and disruptive" ]
test_optional_factory_reset() {
test_optional_factory_reset() {
  echo "INFO: expected duration of ${TEST} test roughly a minute" >&2
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 60`" >&2
  if ! inFastboot; then
  if ! inFastboot; then
    adb reboot-bootloader
    adb reboot-bootloader
  fi
  fi
@@ -502,8 +584,9 @@ battery test (trick):
- NB: should report reboot,battery
- NB: should report reboot,battery
- (replace set logd.kernel true to the above, and retry test)" ]
- (replace set logd.kernel true to the above, and retry test)" ]
test_battery() {
test_battery() {
  echo "INFO: expected duration of ${TEST} test roughly two minutes" >&2
  checkDebugBuild || return
  echo "WARNING: ${TEST} requires userdebug build" >&2
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 120`" >&2
  enterPstore
  # Send it _many_ times to combat devices with flakey pstore
  # 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
  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
    echo 'healthd: battery l=2 ' | adb shell su root tee /dev/kmsg >/dev/null
@@ -529,8 +612,49 @@ test_battery() {
    )
    )


  EXPECT_PROPERTY sys.boot.reason shutdown,battery
  EXPECT_PROPERTY sys.boot.reason shutdown,battery
  EXPECT_PROPERTY persist.sys.boot.reason reboot,cold
  EXPECT_PROPERTY persist.sys.boot.reason cold
  report_bootstat_logs shutdown,battery "-bootstat: Battery level at shutdown 2%"
  report_bootstat_logs shutdown,battery "-bootstat: Battery level at shutdown 2%"
  exitPstore
}

[ "USAGE: test_optional_battery

battery shutdown test:
- adb shell setprop sys.powerctl shutdown,battery
- (power up the device)
- (wait until screen is up, boot has completed)
- adb shell getprop sys.boot.reason
- NB: should report shutdown,battery" ]
test_optional_battery() {
  echo "INFO: expected duration of '${TEST}' test >`format_duration 60`" >&2
  echo "      power on request" >&2
  adb shell setprop sys.powerctl shutdown,battery
  sleep 5
  echo -n "WARNING: Please power device back up, waiting ... " >&2
  wait_for_screen -n >&2
  EXPECT_PROPERTY sys.boot.reason shutdown,battery
  EXPECT_PROPERTY persist.sys.boot.reason shutdown,battery
  report_bootstat_logs shutdown,battery
}

[ "USAGE: test_optional_battery_thermal

battery thermal shutdown test:
- adb shell setprop sys.powerctl shutdown,thermal,battery
- (power up the device)
- (wait until screen is up, boot has completed)
- adb shell getprop sys.boot.reason
- NB: should report shutdown,thermal,battery" ]
test_optional_battery_thermal() {
  echo "INFO: expected duration of '${TEST}' test >`format_duration 60`" >&2
  echo "      power on request" >&2
  adb shell setprop sys.powerctl shutdown,thermal,battery
  sleep 5
  echo -n "WARNING: Please power device back up, waiting ... " >&2
  wait_for_screen -n >&2
  EXPECT_PROPERTY sys.boot.reason shutdown,thermal,battery
  EXPECT_PROPERTY persist.sys.boot.reason shutdown,thermal,battery
  report_bootstat_logs shutdown,thermal,battery
}
}


[ "USAGE: test_unknown
[ "USAGE: test_unknown
@@ -542,7 +666,7 @@ unknown test
- NB: should report reboot,unknown
- NB: should report reboot,unknown
- NB: expect log \"... I bootstat: Unknown boot reason: reboot,unknown\"" ]
- NB: expect log \"... I bootstat: Unknown boot reason: reboot,unknown\"" ]
test_unknown() {
test_unknown() {
  blind_reboot_test reboot,unknown
  blind_reboot_test
}
}


[ "USAGE: test_kernel_panic
[ "USAGE: test_kernel_panic
@@ -553,13 +677,16 @@ kernel_panic test:
- adb shell getprop sys.boot.reason
- adb shell getprop sys.boot.reason
- NB: should report kernel_panic,sysrq" ]
- NB: should report kernel_panic,sysrq" ]
test_kernel_panic() {
test_kernel_panic() {
  echo "INFO: expected duration of ${TEST} test > 2 minutes" >&2
  checkDebugBuild || return
  echo "WARNING: ${TEST} requires userdebug build" >&2
  echo "INFO: expected duration of '${TEST}' test >`format_duration 120`" >&2
  panic_msg="kernel_panic,sysrq"
  enterPstore || panic_msg="\(kernel_panic,sysrq\|kernel_panic\)"
  echo c | adb shell su root tee /proc/sysrq-trigger >/dev/null
  echo c | adb shell su root tee /proc/sysrq-trigger >/dev/null
  wait_for_screen
  wait_for_screen
  EXPECT_PROPERTY sys.boot.reason kernel_panic,sysrq
  EXPECT_PROPERTY sys.boot.reason ${panic_msg}
  EXPECT_PROPERTY persist.sys.boot.reason kernel_panic,sysrq
  EXPECT_PROPERTY persist.sys.boot.reason ${panic_msg}
  report_bootstat_logs kernel_panic,sysrq
  report_bootstat_logs kernel_panic,sysrq
  exitPstore
}
}


[ "USAGE: test_warm
[ "USAGE: test_warm
@@ -582,7 +709,7 @@ thermal shutdown test:
- adb shell getprop sys.boot.reason
- adb shell getprop sys.boot.reason
- NB: should report shutdown,thermal" ]
- NB: should report shutdown,thermal" ]
test_thermal_shutdown() {
test_thermal_shutdown() {
  echo "INFO: expected duration of ${TEST} test roughly a minute plus" >&2
  echo "INFO: expected duration of '${TEST}' test >`format_duration 60`" >&2
  echo "      power on request" >&2
  echo "      power on request" >&2
  adb shell setprop sys.powerctl shutdown,thermal
  adb shell setprop sys.powerctl shutdown,thermal
  sleep 5
  sleep 5
@@ -602,7 +729,7 @@ userrequested shutdown test:
- adb shell getprop sys.boot.reason
- adb shell getprop sys.boot.reason
- NB: should report shutdown,userrequested" ]
- NB: should report shutdown,userrequested" ]
test_userrequested_shutdown() {
test_userrequested_shutdown() {
  echo "INFO: expected duration of ${TEST} test roughly a minute plus" >&2
  echo "INFO: expected duration of '${TEST}' test >`format_duration 60`" >&2
  echo "      power on request" >&2
  echo "      power on request" >&2
  adb shell setprop sys.powerctl shutdown,userrequested
  adb shell setprop sys.powerctl shutdown,userrequested
  sleep 5
  sleep 5
@@ -621,7 +748,7 @@ shell reboot test:
- adb shell getprop sys.boot.reason
- adb shell getprop sys.boot.reason
- NB: should report reboot,shell" ]
- NB: should report reboot,shell" ]
test_shell_reboot() {
test_shell_reboot() {
  echo "INFO: expected duration of ${TEST} test roughly 45 seconds" >&2
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 45`" >&2
  adb shell reboot
  adb shell reboot
  wait_for_screen
  wait_for_screen
  EXPECT_PROPERTY sys.boot.reason reboot,shell
  EXPECT_PROPERTY sys.boot.reason reboot,shell
@@ -637,7 +764,7 @@ adb reboot test:
- adb shell getprop sys.boot.reason
- adb shell getprop sys.boot.reason
- NB: should report reboot,adb" ]
- NB: should report reboot,adb" ]
test_adb_reboot() {
test_adb_reboot() {
  echo "INFO: expected duration of ${TEST} test roughly 45 seconds" >&2
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 45`" >&2
  adb reboot
  adb reboot
  wait_for_screen
  wait_for_screen
  EXPECT_PROPERTY sys.boot.reason reboot,adb
  EXPECT_PROPERTY sys.boot.reason reboot,adb
@@ -654,8 +781,8 @@ Its Just So Hard reboot test:
- NB: should report reboot,its_just_so_hard
- NB: should report reboot,its_just_so_hard
- NB: expect log \"... I bootstat: Unknown boot reason: reboot,its_just_so_hard\"" ]
- NB: expect log \"... I bootstat: Unknown boot reason: reboot,its_just_so_hard\"" ]
test_Its_Just_So_Hard_reboot() {
test_Its_Just_So_Hard_reboot() {
  echo "INFO: expected duration of ${TEST} test roughly 45 seconds" >&2
  checkDebugBuild || return
  echo "INFO: ${TEST} cleanup requires userdebug build" >&2
  echo "INFO: expected duration of '${TEST}' test ~`format_duration 45`" >&2
  adb shell 'reboot "Its Just So Hard"'
  adb shell 'reboot "Its Just So Hard"'
  wait_for_screen
  wait_for_screen
  EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard
  EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard
+4 −19
Original line number Original line Diff line number Diff line
@@ -233,6 +233,7 @@ const std::vector<const std::string> knownReasons = {
    "cold",
    "cold",
    "hard",
    "hard",
    "warm",
    "warm",
    // super blunt
    "shutdown",    // Can not happen from ro.boot.bootreason
    "shutdown",    // Can not happen from ro.boot.bootreason
    "reboot",      // Default catch-all for anything unknown
    "reboot",      // Default catch-all for anything unknown
    // clang-format on
    // clang-format on
@@ -543,21 +544,11 @@ std::string BootReasonStrToReason(const std::string& boot_reason) {
      std::transform(content.begin(), content.end(), content.begin(), tounderline);
      std::transform(content.begin(), content.end(), content.begin(), tounderline);
      std::transform(content.begin(), content.end(), content.begin(), toprintable);
      std::transform(content.begin(), content.end(), content.begin(), toprintable);


      // String is either "reboot,<reason>" or "shutdown,<reason>".
      // Anything in last is better than 'super-blunt' reboot or shutdown.
      // We will set if default reasons, only override with detail if thermal.
      if ((ret == "") || (ret == "reboot") || (ret == "shutdown") || !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.
        size_t pos = content.find(',');
        if (pos != std::string::npos) {
          ++pos;
          std::string secondReason(content.substr(pos));
          ret = isKnownRebootReason(secondReason) ? secondReason : content;
        } else {
        ret = content;
        ret = content;
      }
      }
    }
    }
    }


    // Other System Health HAL reasons?
    // Other System Health HAL reasons?


@@ -611,17 +602,11 @@ std::string CalculateBootCompletePrefix() {
    boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date);
    boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date);
    LOG(INFO) << "Canonical boot reason: reboot,factory_reset";
    LOG(INFO) << "Canonical boot reason: reboot,factory_reset";
    SetProperty(system_reboot_reason_property, "reboot,factory_reset");
    SetProperty(system_reboot_reason_property, "reboot,factory_reset");
    if (GetProperty(bootloader_reboot_reason_property) == "") {
      SetProperty(bootloader_reboot_reason_property, "reboot,factory_reset");
    }
  } else if (build_date != record.second) {
  } else if (build_date != record.second) {
    boot_complete_prefix = "ota_" + boot_complete_prefix;
    boot_complete_prefix = "ota_" + boot_complete_prefix;
    boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date);
    boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date);
    LOG(INFO) << "Canonical boot reason: reboot,ota";
    LOG(INFO) << "Canonical boot reason: reboot,ota";
    SetProperty(system_reboot_reason_property, "reboot,ota");
    SetProperty(system_reboot_reason_property, "reboot,ota");
    if (GetProperty(bootloader_reboot_reason_property) == "") {
      SetProperty(bootloader_reboot_reason_property, "reboot,ota");
    }
  }
  }


  return boot_complete_prefix;
  return boot_complete_prefix;
+12 −2
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@
#include "service.h"
#include "service.h"
#include "sigchld_handler.h"
#include "sigchld_handler.h"


using android::base::Split;
using android::base::StringPrintf;
using android::base::StringPrintf;
using android::base::Timer;
using android::base::Timer;


@@ -346,7 +347,16 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
    Timer t;
    Timer t;
    LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
    LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;


    property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str());
    // Ensure last reboot reason is reduced to canonical
    // alias reported in bootloader or system boot reason.
    size_t skip = 0;
    std::vector<std::string> reasons = Split(reason, ",");
    if (reasons.size() >= 2 && reasons[0] == "reboot" &&
        (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
         reasons[1] == "hard" || reasons[1] == "warm")) {
        skip = strlen("reboot,");
    }
    property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
    sync();
    sync();


    bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
    bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
@@ -469,7 +479,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re


bool HandlePowerctlMessage(const std::string& command) {
bool HandlePowerctlMessage(const std::string& command) {
    unsigned int cmd = 0;
    unsigned int cmd = 0;
    std::vector<std::string> cmd_params = android::base::Split(command, ",");
    std::vector<std::string> cmd_params = Split(command, ",");
    std::string reboot_target = "";
    std::string reboot_target = "";
    bool run_fsck = false;
    bool run_fsck = false;
    bool command_invalid = false;
    bool command_invalid = false;