Loading bootstat/boot_reason_test.sh +170 −43 Original line number Original line Diff line number Diff line Loading @@ -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" ] Loading Loading @@ -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} } } Loading Loading @@ -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#-}" Loading Loading @@ -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 Loading Loading @@ -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 \ Loading Loading @@ -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 } } Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading bootstat/bootstat.cpp +4 −19 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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? Loading Loading @@ -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; Loading init/reboot.cpp +12 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading
bootstat/boot_reason_test.sh +170 −43 Original line number Original line Diff line number Diff line Loading @@ -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" ] Loading Loading @@ -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} } } Loading Loading @@ -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#-}" Loading Loading @@ -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 Loading Loading @@ -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 \ Loading Loading @@ -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 } } Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading
bootstat/bootstat.cpp +4 −19 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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? Loading Loading @@ -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; Loading
init/reboot.cpp +12 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading