1 #! /bin/bash 2 # 3 # Bootstat boot reason tests 4 # 5 # throughout testing: 6 # - manual tests can only run on eng/userdebug builds 7 # - watch adb logcat -b all -d -s bootstat 8 # - watch adb logcat -b all -d | audit2allow 9 # - wait until screen is up, boot has completed, can mean wait for 10 # sys.boot_completed=1 and sys.logbootcomplete=1 to be true 11 # 12 # All test frames, and nothing else, must be function names prefixed and 13 # specifiged with the pattern 'test_<test>() {' as this is also how the 14 # script discovers the full list of tests by inspecting its own code. 15 # 16 17 # Helper variables 18 19 SPACE=" " 20 ESCAPE="" 21 TAB=" " 22 GREEN="${ESCAPE}[38;5;40m" 23 RED="${ESCAPE}[38;5;196m" 24 NORMAL="${ESCAPE}[0m" 25 # Best guess to an average device's reboot time, refined as tests return 26 DURATION_DEFAULT=45 27 28 # Helper functions 29 30 [ "USAGE: inFastboot 31 32 Returns: true if device is in fastboot mode" ] 33 inFastboot() { 34 fastboot devices | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null 35 } 36 37 [ "USAGE: inAdb 38 39 Returns: true if device is in adb mode" ] 40 inAdb() { 41 adb devices | grep -v 'List of devices attached' | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null 42 } 43 44 [ "USAGE: hasPstore 45 46 Returns: true if device (likely) has pstore data" ] 47 hasPstore() { 48 if inAdb && [ 0 -eq `adb shell su root ls /sys/fs/pstore | wc -l` ]; then 49 false 50 fi 51 } 52 53 [ "USAGE: isDebuggable 54 55 Returns: true if device is (likely) a debug build" ] 56 isDebuggable() { 57 if inAdb && [ 1 -ne `adb shell getprop ro.debuggable` ]; then 58 false 59 fi 60 } 61 62 [ "USAGE: checkDebugBuild [--noerror] 63 64 Returns: true if device is a userdebug or eng release" ] 65 checkDebugBuild() { 66 if isDebuggable; then 67 echo "INFO: '${TEST}' test requires userdebug build" 68 elif [ -n "${1}" ]; then 69 echo "WARNING: '${TEST}' test requires userdebug build" 70 false 71 else 72 echo "ERROR: '${TEST}' test requires userdebug build, skipping FAILURE" 73 duration_prefix="~" 74 duration_estimate=1 75 false 76 fi >&2 77 } 78 79 [ "USAGE: setBootloaderBootReason [value] 80 81 Returns: true if device supports and set boot reason injection" ] 82 setBootloaderBootReason() { 83 inAdb || ( echo "ERROR: device not in adb mode." >&2 ; false ) || return 1 84 if [ -z "`adb shell ls /etc/init/bootstat-debug.rc 2>/dev/null`" ]; then 85 echo "ERROR: '${TEST}' test requires /etc/init/bootstat-debug.rc" >&2 86 return 1 87 fi 88 checkDebugBuild || return 1 89 if adb shell su root "cat /proc/cmdline | tr '\\0 ' '\\n\\n'" | 90 grep '^androidboot[.]bootreason=[^ ]' >/dev/null; then 91 echo "ERROR: '${TEST}' test requires a device with a bootloader that" >&2 92 echo " does not set androidboot.bootreason kernel parameter." >&2 93 return 1 94 fi 95 adb shell su root setprop persist.test.boot.reason "'${1}'" 2>/dev/null 96 test_reason="`adb shell getprop persist.test.boot.reason 2>/dev/null`" 97 if [ X"${test_reason}" != X"${1}" ]; then 98 echo "ERROR: can not set persist.test.boot.reason to '${1}'." >&2 99 return 1 100 fi 101 } 102 103 [ "USAGE: enterPstore 104 105 Prints a warning string requiring functional pstore 106 107 Returns: pstore_ok variable set to true or false" ] 108 enterPstore() { 109 if hasPstore; then 110 echo "INFO: '${TEST}' test requires functional and reliable pstore" 111 pstore_ok=true 112 else 113 echo "WARNING: '${TEST}' test requires functional pstore" 114 pstore_ok=false 115 fi >&2 116 ${pstore_ok} 117 } 118 119 [ "USAGE: exitPstore 120 121 Prints an error string requiring functional pstore 122 123 Returns: clears error if pstore dysfunctional" ] 124 exitPstore() { 125 save_ret=${?} 126 if [ ${save_ret} != 0 ]; then 127 if hasPstore; then 128 return ${save_ret} 129 fi 130 if [ true = ${pstore_ok} ]; then 131 echo "WARNING: '${TEST}' test requires functional pstore" 132 return ${save_ret} 133 fi 134 echo "ERROR: '${TEST}' test requires functional pstore, skipping FAILURE" 135 duration_prefix="~" 136 duration_estimate=1 137 fi >&2 138 } 139 140 [ "USAGE: format_duration <seconds> 141 142 human readable output whole seconds, whole minutes or mm:ss" ] 143 format_duration() { 144 if [ -z "${1}" ]; then 145 echo unknown 146 return 147 fi 148 seconds=`expr ${1} % 60` 149 minutes=`expr ${1} / 60` 150 if [ 0 -eq ${minutes} ]; then 151 if [ 1 -eq ${1} ]; then 152 echo 1 second 153 return 154 fi 155 echo ${1} seconds 156 return 157 elif [ 60 -eq ${1} ]; then 158 echo 1 minute 159 return 160 elif [ 0 -eq ${seconds} ]; then 161 echo ${minutes} minutes 162 return 163 fi 164 echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10` 165 } 166 167 wait_for_screen_timeout=900 168 [ "USAGE: wait_for_screen [-n] [TIMEOUT] 169 170 -n - echo newline at exit 171 TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ] 172 wait_for_screen() { 173 exit_function=true 174 if [ X"-n" = X"${1}" ]; then 175 exit_function=echo 176 shift 177 fi 178 timeout=${wait_for_screen_timeout} 179 if [ ${#} -gt 0 ]; then 180 timeout=${1} 181 shift 182 fi 183 counter=0 184 while true; do 185 if inFastboot; then 186 fastboot reboot 187 elif inAdb; then 188 if [ 0 != ${counter} ]; then 189 adb wait-for-device </dev/null >/dev/null 2>/dev/null 190 fi 191 if [ -n "`adb shell getprop sys.boot.reason </dev/null 2>/dev/null`" ] 192 then 193 vals=`adb shell getprop </dev/null 2>/dev/null | 194 sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'` 195 if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ] 196 then 197 sleep 1 198 break 199 fi 200 if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ] 201 then 202 sleep 1 203 break 204 fi 205 fi 206 fi 207 counter=`expr ${counter} + 1` 208 if [ ${counter} -gt ${timeout} ]; then 209 ${exit_function} 210 echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2 211 return 1 212 fi 213 sleep 1 214 done 215 ${exit_function} 216 } 217 218 [ "USAGE: EXPECT_EQ <lval> <rval> [message] 219 220 Returns true if (regex) lval matches rval" ] 221 EXPECT_EQ() { 222 lval="${1}" 223 rval="${2}" 224 shift 2 225 if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then 226 echo "ERROR: expected \"${lval}\" got \"${rval}\"" >&2 227 if [ -n "${*}" ] ; then 228 echo " ${*}" >&2 229 fi 230 return 1 231 fi 232 if [ -n "${*}" ] ; then 233 if [ X"${lval}" != X"${rval}" ]; then 234 echo "INFO: ok \"${lval}\"(=\"${rval}\") ${*}" >&2 235 else 236 echo "INFO: ok \"${lval}\" ${*}" >&2 237 fi 238 fi 239 return 0 240 } 241 242 [ "USAGE: EXPECT_PROPERTY <prop> <value> [--allow_failure] 243 244 Returns true (0) if current return (regex) value is true and the result matches 245 and the incoming return value is true as well (wired-or)" ] 246 EXPECT_PROPERTY() { 247 save_ret=${?} 248 property="${1}" 249 value="${2}" 250 shift 2 251 val=`adb shell getprop ${property} 2>&1` 252 EXPECT_EQ "${value}" "${val}" for Android property ${property} || 253 [ -n "${1}" ] || 254 save_ret=${?} 255 return ${save_ret} 256 } 257 258 [ "USAGE: report_bootstat_logs <expected> ... 259 260 if not prefixed with a minus (-), <expected> will become a series of expected 261 matches: 262 263 bootstat: Canonical boot reason: <expected_property_value> 264 265 If prefixed with a minus, <expected> will look for an exact match after 266 removing the minux prefix. All expected content is _dropped_ from the output 267 and in essence forms a known blacklist, unexpected content will show. 268 269 Report any logs, minus a known blacklist, preserve the current exit status" ] 270 report_bootstat_logs() { 271 save_ret=${?} 272 match= 273 for i in "${@}"; do 274 if [ X"${i}" != X"${i#-}" ] ; then 275 match="${match} 276 ${i#-}" 277 else 278 match="${match} 279 bootstat: Canonical boot reason: ${i}" 280 fi 281 done 282 adb logcat -b all -d | 283 grep bootstat[^e] | 284 grep -v -F "bootstat: Service started: /system/bin/bootstat --record_boot_complete${match} 285 bootstat: Failed to read /data/misc/bootstat/post_decrypt_time_elapsed: No such file or directory 286 bootstat: Failed to parse boot time record: /data/misc/bootstat/post_decrypt_time_elapsed 287 bootstat: Service started: /system/bin/bootstat --record_boot_reason 288 bootstat: Service started: /system/bin/bootstat --record_time_since_factory_reset 289 bootstat: Service started: /system/bin/bootstat -l 290 bootstat: Battery level at shutdown 100% 291 bootstat: Battery level at startup 100% 292 init : Parsing file /system/etc/init/bootstat.rc... 293 init : Parsing file /system/etc/init/bootstat-debug.rc... 294 init : processing action (persist.test.boot.reason=*) from (/system/etc/init/bootstat-debug.rc: 295 init : Command 'setprop ro.boot.bootreason \${persist.test.boot.reason}' action=persist.test.boot.reason=* (/system/etc/init/bootstat-debug.rc: 296 init : processing action (post-fs-data) from (/system/etc/init/bootstat.rc 297 init : processing action (boot) from (/system/etc/init/bootstat.rc 298 init : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc 299 init : processing action (sys.boot_completed=1 && sys.logbootcomplete=1) from (/system/etc/init/bootstat.rc 300 (/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)' 301 (/system/bin/bootstat -r post_decrypt_time_elapsed)' 302 init : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc: 303 init : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc: 304 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: 305 (/system/bin/bootstat --record_boot_complete)'... 306 (/system/bin/bootstat --record_boot_complete)' (pid${SPACE} 307 (/system/bin/bootstat --record_boot_reason)'... 308 (/system/bin/bootstat --record_boot_reason)' (pid${SPACE} 309 (/system/bin/bootstat --record_time_since_factory_reset)'... 310 (/system/bin/bootstat --record_time_since_factory_reset)' (pid${SPACE} 311 (/system/bin/bootstat -l)'... 312 (/system/bin/bootstat -l)' (pid " | 313 grep -v 'bootstat: Unknown boot reason: $' # Hikey Special 314 return ${save_ret} 315 } 316 317 [ "USAGE: start_test [message] 318 319 Record start of test, preserve exit status" ] 320 start_test() { 321 save_ret=${?} 322 duration_prefix="~" 323 duration_estimate=1 324 START=`date +%s` 325 echo "${GREEN}[ RUN ]${NORMAL} ${TEST} ${*}" 326 return ${save_ret} 327 } 328 329 duration_sum_diff=0 330 duration_num=0 331 [ "USAGE: duration_test [[prefix]seconds] 332 333 Report the adjusted and expected test duration" ] 334 duration_test() { 335 duration_prefix=${1%%[0123456789]*} 336 if [ -z "${duration_prefix}" ]; then 337 duration_prefix="~" 338 fi 339 duration_estimate="${1#${duration_prefix}}" 340 if [ -z "${duration_estimate}" ]; then 341 duration_estimate="${DURATION_DEFAULT}" 342 fi 343 duration_new_estimate="${duration_estimate}" 344 if [ 0 -ne ${duration_num} ]; then 345 duration_new_estimate=`expr ${duration_new_estimate} + \ 346 \( ${duration_num} / 2 + ${duration_sum_diff} \) / ${duration_num}` 347 # guard against catastrophe 348 if [ -z "${duration_new_estimate}" ]; then 349 duration_new_estimate=${duration_estimate} 350 fi 351 fi 352 # negative values are so undignified 353 if [ 0 -ge ${duration_new_estimate} ]; then 354 duration_new_estimate=1 355 fi 356 echo "INFO: expected duration of '${TEST}' test" \ 357 "${duration_prefix}`format_duration ${duration_new_estimate}`" >&2 358 } 359 360 [ "USAGE: end_test [message] 361 362 Document duration and success of test, preserve exit status" ] 363 end_test() { 364 save_ret=${?} 365 END=`date +%s` 366 duration=`expr ${END} - ${START} 2>/dev/null` 367 [ 0 -ge ${duration} ] || 368 echo "INFO: '${TEST}' test duration `format_duration ${duration}`" >&2 369 if [ ${save_ret} = 0 ]; then 370 if [ 0 -lt ${duration} -a 0 -lt ${duration_estimate} -a \( \ 371 X"~" = X"${duration_prefix}" -o \ 372 ${duration_estimate} -gt ${duration} \) ]; then 373 duration_sum_diff=`expr ${duration_sum_diff} + \ 374 ${duration} - ${duration_estimate}` 375 duration_num=`expr ${duration_num} + 1` 376 fi 377 echo "${GREEN}[ OK ]${NORMAL} ${TEST} ${*}" 378 else 379 echo "${RED}[ FAILED ]${NORMAL} ${TEST} ${*}" 380 fi 381 return ${save_ret} 382 } 383 384 [ "USAGE: wrap_test <test> [message] 385 386 All tests below are wrapped with this helper" ] 387 wrap_test() { 388 if [ -z "${1}" -o X"nothing" = X"${1}" ]; then 389 return 390 fi 391 TEST=${1} 392 shift 393 start_test ${1} 394 eval test_${TEST} 395 end_test ${2} 396 } 397 398 [ "USAGE: validate_reason <value> 399 400 Check property for CTS compliance with our expectations. Return a cleansed 401 string representing what is acceptable. 402 403 NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ] 404 validate_reason() { 405 var=`echo -n ${*} | 406 tr '[A-Z]' '[a-z]' | 407 tr ' \f\t\r\n' '_____'` 408 case ${var} in 409 watchdog | watchdog,?* ) ;; 410 kernel_panic | kernel_panic,?*) ;; 411 recovery | recovery,?*) ;; 412 bootloader | bootloader,?*) ;; 413 cold | cold,?*) ;; 414 hard | hard,?*) ;; 415 warm | warm,?*) ;; 416 shutdown | shutdown,?*) ;; 417 reboot,reboot | reboot,reboot,* ) var=${var#reboot,} ; var=${var%,} ;; 418 reboot,cold | reboot,cold,* ) var=${var#reboot,} ; var=${var%,} ;; 419 reboot,hard | reboot,hard,* ) var=${var#reboot,} ; var=${var%,} ;; 420 reboot,warm | reboot,warm,* ) var=${var#reboot,} ; var=${var%,} ;; 421 reboot,recovery | reboot,recovery,* ) var=${var#reboot,} ; var=${var%,} ;; 422 reboot,bootloader | reboot,bootloader,* ) var=${var#reboot,} ; var=${var%,} ;; 423 reboot | reboot,?*) ;; 424 # Aliases and Heuristics 425 *wdog* | *watchdog* ) var="watchdog" ;; 426 *powerkey* ) var="cold,powerkey" ;; 427 *panic* | *kernel_panic*) var="kernel_panic" ;; 428 *thermal*) var="shutdown,thermal" ;; 429 *s3_wakeup*) var="warm,s3_wakeup" ;; 430 *hw_reset*) var="hard,hw_reset" ;; 431 *bootloader*) var="bootloader" ;; 432 *) var="reboot" ;; 433 esac 434 echo ${var} 435 } 436 437 [ "USAGE: validate_property <property> 438 439 Check property for CTS compliance with our expectations. Return a cleansed 440 string representing what is acceptable. 441 442 NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ] 443 validate_property() { 444 val="`adb shell getprop ${1} 2>&1`" 445 ret=`validate_reason "${val}"` 446 if [ "reboot" = "${ret}" ]; then 447 ret=`validate_reason "reboot,${val}"` 448 fi 449 echo ${ret} 450 } 451 452 # 453 # Actual test frames 454 # 455 456 [ "USAGE: test_properties 457 458 properties test 459 - (wait until screen is up, boot has completed) 460 - adb shell getprop ro.boot.bootreason (bootloader reason) 461 - adb shell getprop persist.sys.boot.reason (last reason) 462 - adb shell getprop sys.boot.reason (system reason) 463 - NB: all should have a value that is compliant with our known set." ] 464 test_properties() { 465 duration_test 1 466 wait_for_screen 467 retval=0 468 check_set="ro.boot.bootreason persist.sys.boot.reason sys.boot.reason" 469 bootloader="" 470 # NB: this test could fail if performed _after_ optional_factory_reset test 471 # and will report 472 # ERROR: expected "reboot" got "" 473 # for Android property persist.sys.boot.reason 474 # following is mitigation for the persist.sys.boot.reason, skip it 475 if [ "reboot,factory_reset" = "`validate_property ro.boot_bootreason`" ]; then 476 check_set="ro.boot.bootreason sys.boot.reason" 477 bootloader="bootloader" 478 fi 479 for prop in ${check_set}; do 480 reason=`validate_property ${prop}` 481 EXPECT_PROPERTY ${prop} ${reason} || retval=${?} 482 done 483 # sys.boot.reason is last for a reason 484 report_bootstat_logs ${reason} ${bootloader} 485 return ${retval} 486 } 487 488 [ "USAGE: test_ota 489 490 ota test 491 - rm out/.kati_stamp-* out/build_date.txt out/build_number.txt 492 - rm out/target/product/*/*/*.prop 493 - rm -r out/target/product/*/obj/ETC/system_build_prop_intermediates 494 - m 495 - NB: ro.build.date.utc should update 496 - fastboot flashall 497 - (wait until screen is up, boot has completed) 498 - adb shell getprop sys.boot.reason 499 - NB: should report ota 500 501 Decision to change the build itself rather than trick bootstat by 502 rummaging through its data files was made." ] 503 test_ota() { 504 duration_test ">300" 505 echo " extended by build and flashing times" >&2 506 if [ -z "${TARGET_PRODUCT}" -o \ 507 -z "${ANDROID_PRODUCT_OUT}" -o \ 508 -z "${ANDROID_BUILD_TOP}" -o \ 509 -z "${TARGET_BUILD_VARIANT}" ]; then 510 echo "ERROR: Missing envsetup.sh and lunch" >&2 511 return 1 512 fi 513 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/.kati_stamp-* || 514 true 515 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_date.txt || 516 true 517 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_number.txt || 518 true 519 rm ${ANDROID_PRODUCT_OUT}/*/*.prop || 520 true 521 rm -r ${ANDROID_PRODUCT_OUT}/obj/ETC/system_build_prop_intermediates || 522 true 523 pushd ${ANDROID_BUILD_TOP} >&2 524 make -j50 >&2 525 if [ ${?} != 0 ]; then 526 popd >&2 527 return 1 528 fi 529 if ! inFastboot; then 530 adb reboot-bootloader >&2 531 fi 532 fastboot flashall >&2 533 popd >&2 534 wait_for_screen 535 EXPECT_PROPERTY sys.boot.reason "\(reboot,ota\|bootloader\)" 536 EXPECT_PROPERTY persist.sys.boot.reason bootloader 537 report_bootstat_logs reboot,ota bootloader 538 } 539 540 [ "USAGE: test_optional_ota 541 542 fast and fake (touch build_date on device to make it different)" ] 543 test_optional_ota() { 544 checkDebugBuild || return 545 duration_test 546 adb shell su root touch /data/misc/bootstat/build_date >&2 547 adb reboot ota 548 wait_for_screen 549 EXPECT_PROPERTY sys.boot.reason reboot,ota 550 EXPECT_PROPERTY persist.sys.boot.reason reboot,ota 551 report_bootstat_logs reboot,ota 552 } 553 554 [ "USAGE: [TEST=<test>] blind_reboot_test 555 556 Simple tests helper 557 - adb reboot <test> 558 - (wait until screen is up, boot has completed) 559 - adb shell getprop sys.boot.reason 560 - NB: should report <test>, or reboot,<test> depending on canonical rules 561 562 We interleave the simple reboot tests between the hard/complex ones 563 as a means of checking sanity and any persistent side effect of the 564 other tests." ] 565 blind_reboot_test() { 566 duration_test 567 case ${TEST} in 568 bootloader | recovery | cold | hard | warm ) reason=${TEST} ;; 569 *) reason=reboot,${TEST} ;; 570 esac 571 adb reboot ${TEST} 572 wait_for_screen 573 bootloader_reason=`validate_property ro.boot.bootreason` 574 EXPECT_PROPERTY ro.boot.bootreason ${bootloader_reason} 575 EXPECT_PROPERTY sys.boot.reason ${reason} 576 EXPECT_PROPERTY persist.sys.boot.reason ${reason} 577 report_bootstat_logs ${reason} 578 } 579 580 [ "USAGE: test_cold 581 582 cold test 583 - adb reboot cold 584 - (wait until screen is up, boot has completed) 585 - adb shell getprop sys.boot.reason 586 - NB: should report cold" ] 587 test_cold() { 588 blind_reboot_test 589 } 590 591 [ "USAGE: test_factory_reset 592 593 factory_reset test 594 - adb shell su root rm /data/misc/bootstat/build_date 595 - adb reboot 596 - (wait until screen is up, boot has completed) 597 - adb shell getprop sys.boot.reason 598 - NB: should report factory_reset 599 600 Decision to rummage through bootstat data files was made as 601 a _real_ factory_reset is too destructive to the device." ] 602 test_factory_reset() { 603 checkDebugBuild || return 604 duration_test 605 adb shell su root rm /data/misc/bootstat/build_date >&2 606 adb reboot >&2 607 wait_for_screen 608 EXPECT_PROPERTY sys.boot.reason reboot,factory_reset 609 EXPECT_PROPERTY persist.sys.boot.reason "reboot,.*" 610 report_bootstat_logs reboot,factory_reset reboot, reboot,adb \ 611 "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \ 612 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date" 613 } 614 615 [ "USAGE: test_optional_factory_reset 616 617 factory_reset test 618 - adb reboot-bootloader 619 - fastboot format userdata 620 - fastboot reboot 621 - (wait until screen is up, boot has completed) 622 - adb shell getprop sys.boot.reason 623 - NB: should report factory_reset 624 625 For realz, and disruptive" ] 626 test_optional_factory_reset() { 627 duration_test 60 628 if ! inFastboot; then 629 adb reboot-bootloader 630 fi 631 fastboot format userdata >&2 632 save_ret=${?} 633 if [ 0 != ${save_ret} ]; then 634 echo "ERROR: fastboot can not format userdata" >&2 635 fi 636 fastboot reboot >&2 637 wait_for_screen 638 ( exit ${save_ret} ) # because one can not just do ?=${save_ret} 639 EXPECT_PROPERTY sys.boot.reason reboot,factory_reset 640 EXPECT_PROPERTY persist.sys.boot.reason "" 641 report_bootstat_logs reboot,factory_reset bootloader \ 642 "-bootstat: Failed to read /data/misc/bootstat/last_boot_time_utc: No such file or directory" \ 643 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/last_boot_time_utc" \ 644 "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \ 645 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date" \ 646 "-bootstat: Failed to read /data/misc/bootstat/factory_reset: No such file or directory" \ 647 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/factory_reset" 648 } 649 650 [ "USAGE: test_hard 651 652 hard test: 653 - adb reboot hard 654 - (wait until screen is up, boot has completed) 655 - adb shell getprop sys.boot.reason 656 - NB: should report hard" ] 657 test_hard() { 658 blind_reboot_test 659 } 660 661 [ "USAGE: test_battery 662 663 battery test (trick): 664 - echo healthd: battery l=2<space> | adb shell su root tee /dev/kmsg 665 - adb reboot cold 666 - (wait until screen is up, boot has completed) 667 - adb shell getprop sys.boot.reason 668 - NB: should report reboot,battery, unless healthd managed to log 669 before reboot in above trick. 670 671 - Bonus points (manual extras) 672 - Make sure the following is added to the /init.rc file in post-fs 673 section before logd is started: 674 + setprop logd.kernel false 675 + rm /sys/fs/pstore/console-ramoops 676 + rm /sys/fs/pstore/console-ramoops-0 677 + write /dev/kmsg \"healthd: battery l=2${SPACE} 678 +\" 679 - adb reboot fs 680 - (wait until screen is up, boot has completed) 681 - adb shell getprop sys.boot.reason 682 - NB: should report reboot,battery 683 - (replace set logd.kernel true to the above, and retry test)" ] 684 test_battery() { 685 checkDebugBuild || return 686 duration_test 120 687 enterPstore 688 # Send it _many_ times to combat devices with flakey pstore 689 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 690 echo 'healthd: battery l=2 ' | adb shell su root tee /dev/kmsg >/dev/null 691 done 692 adb reboot cold >&2 693 adb wait-for-device 694 wait_for_screen 695 adb shell su root \ 696 cat /proc/fs/pstore/console-ramoops \ 697 /proc/fs/pstore/console-ramoops-0 2>/dev/null | 698 grep 'healthd: battery l=' | 699 tail -1 | 700 grep 'healthd: battery l=2 ' >/dev/null || ( 701 if ! EXPECT_PROPERTY sys.boot.reason reboot,battery >/dev/null 2>/dev/null; then 702 # retry 703 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 704 echo 'healthd: battery l=2 ' | adb shell su root tee /dev/kmsg >/dev/null 705 done 706 adb reboot cold >&2 707 adb wait-for-device 708 wait_for_screen 709 fi 710 ) 711 712 EXPECT_PROPERTY sys.boot.reason shutdown,battery 713 EXPECT_PROPERTY persist.sys.boot.reason cold 714 report_bootstat_logs shutdown,battery "-bootstat: Battery level at shutdown 2%" 715 exitPstore 716 } 717 718 [ "USAGE: test_optional_battery 719 720 battery shutdown test: 721 - adb shell setprop sys.powerctl shutdown,battery 722 - (power up the device) 723 - (wait until screen is up, boot has completed) 724 - adb shell getprop sys.boot.reason 725 - NB: should report shutdown,battery" ] 726 test_optional_battery() { 727 duration_test ">60" 728 echo " power on request" >&2 729 adb shell setprop sys.powerctl shutdown,battery 730 sleep 5 731 echo -n "WARNING: Please power device back up, waiting ... " >&2 732 wait_for_screen -n >&2 733 EXPECT_PROPERTY sys.boot.reason shutdown,battery 734 EXPECT_PROPERTY persist.sys.boot.reason shutdown,battery 735 report_bootstat_logs shutdown,battery 736 } 737 738 [ "USAGE: test_optional_battery_thermal 739 740 battery thermal shutdown test: 741 - adb shell setprop sys.powerctl shutdown,thermal,battery 742 - (power up the device) 743 - (wait until screen is up, boot has completed) 744 - adb shell getprop sys.boot.reason 745 - NB: should report shutdown,thermal,battery" ] 746 test_optional_battery_thermal() { 747 duration_test ">60" 748 echo " power on request" >&2 749 adb shell setprop sys.powerctl shutdown,thermal,battery 750 sleep 5 751 echo -n "WARNING: Please power device back up, waiting ... " >&2 752 wait_for_screen -n >&2 753 EXPECT_PROPERTY sys.boot.reason shutdown,thermal,battery 754 EXPECT_PROPERTY persist.sys.boot.reason shutdown,thermal,battery 755 report_bootstat_logs shutdown,thermal,battery 756 } 757 758 [ "USAGE: test_unknown 759 760 unknown test 761 - adb reboot unknown 762 - (wait until screen is up, boot has completed) 763 - adb shell getprop sys.boot.reason 764 - NB: should report reboot,unknown 765 - NB: expect log \"... I bootstat: Unknown boot reason: reboot,unknown\"" ] 766 test_unknown() { 767 blind_reboot_test 768 } 769 770 [ "USAGE: test_kernel_panic 771 772 kernel_panic test: 773 - echo c | adb shell su root tee /proc/sysrq-trigger 774 - (wait until screen is up, boot has completed) 775 - adb shell getprop sys.boot.reason 776 - NB: should report kernel_panic,sysrq" ] 777 test_kernel_panic() { 778 checkDebugBuild || return 779 duration_test ">90" 780 panic_msg="kernel_panic,sysrq" 781 enterPstore 782 if [ ${?} != 0 ]; then 783 echo " or functional bootloader" >&2 784 panic_msg="\(kernel_panic,sysrq\|kernel_panic\)" 785 pstore_ok=true 786 fi 787 echo c | adb shell su root tee /proc/sysrq-trigger >/dev/null 788 wait_for_screen 789 EXPECT_PROPERTY sys.boot.reason ${panic_msg} 790 EXPECT_PROPERTY persist.sys.boot.reason ${panic_msg} 791 report_bootstat_logs kernel_panic,sysrq 792 exitPstore 793 } 794 795 [ "USAGE: test_warm 796 797 warm test 798 - adb reboot warm 799 - (wait until screen is up, boot has completed) 800 - adb shell getprop sys.boot.reason 801 - NB: should report warm" ] 802 test_warm() { 803 blind_reboot_test 804 } 805 806 [ "USAGE: test_thermal_shutdown 807 808 thermal shutdown test: 809 - adb shell setprop sys.powerctl shutdown,thermal 810 - (power up the device) 811 - (wait until screen is up, boot has completed) 812 - adb shell getprop sys.boot.reason 813 - NB: should report shutdown,thermal" ] 814 test_thermal_shutdown() { 815 duration_test ">60" 816 echo " power on request" >&2 817 adb shell setprop sys.powerctl shutdown,thermal 818 sleep 5 819 echo -n "WARNING: Please power device back up, waiting ... " >&2 820 wait_for_screen -n >&2 821 EXPECT_PROPERTY sys.boot.reason shutdown,thermal 822 EXPECT_PROPERTY persist.sys.boot.reason shutdown,thermal 823 report_bootstat_logs shutdown,thermal 824 } 825 826 [ "USAGE: test_userrequested_shutdown 827 828 userrequested shutdown test: 829 - adb shell setprop sys.powerctl shutdown,userrequested 830 - (power up the device) 831 - (wait until screen is up, boot has completed) 832 - adb shell getprop sys.boot.reason 833 - NB: should report shutdown,userrequested" ] 834 test_userrequested_shutdown() { 835 duration_test ">60" 836 echo " power on request" >&2 837 adb shell setprop sys.powerctl shutdown,userrequested 838 sleep 5 839 echo -n "WARNING: Please power device back up, waiting ... " >&2 840 wait_for_screen -n >&2 841 EXPECT_PROPERTY sys.boot.reason shutdown,userrequested 842 EXPECT_PROPERTY persist.sys.boot.reason shutdown,userrequested 843 report_bootstat_logs shutdown,userrequested 844 } 845 846 [ "USAGE: test_shell_reboot 847 848 shell reboot test: 849 - adb shell reboot 850 - (wait until screen is up, boot has completed) 851 - adb shell getprop sys.boot.reason 852 - NB: should report reboot,shell" ] 853 test_shell_reboot() { 854 duration_test 855 adb shell reboot 856 wait_for_screen 857 EXPECT_PROPERTY sys.boot.reason reboot,shell 858 EXPECT_PROPERTY persist.sys.boot.reason reboot,shell 859 report_bootstat_logs reboot,shell 860 } 861 862 [ "USAGE: test_adb_reboot 863 864 adb reboot test: 865 - adb reboot 866 - (wait until screen is up, boot has completed) 867 - adb shell getprop sys.boot.reason 868 - NB: should report reboot,adb" ] 869 test_adb_reboot() { 870 duration_test 871 adb reboot 872 wait_for_screen 873 EXPECT_PROPERTY sys.boot.reason reboot,adb 874 EXPECT_PROPERTY persist.sys.boot.reason reboot,adb 875 report_bootstat_logs reboot,adb 876 } 877 878 [ "USAGE: test_Its_Just_So_Hard_reboot 879 880 Its Just So Hard reboot test: 881 - adb shell reboot 'Its Just So Hard' 882 - (wait until screen is up, boot has completed) 883 - adb shell getprop sys.boot.reason 884 - NB: should report reboot,its_just_so_hard 885 - NB: expect log \"... I bootstat: Unknown boot reason: reboot,its_just_so_hard\"" ] 886 test_Its_Just_So_Hard_reboot() { 887 if isDebuggable; then # see below 888 duration_test 889 else 890 duration_test `expr ${DURATION_DEFAULT} + ${DURATION_DEFAULT}` 891 fi 892 adb shell 'reboot "Its Just So Hard"' 893 wait_for_screen 894 EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard 895 EXPECT_PROPERTY persist.sys.boot.reason "reboot,Its Just So Hard" 896 # Do not leave this test with an illegal value in persist.sys.boot.reason 897 save_ret=${?} # hold on to error code from above two lines 898 if isDebuggable; then # can do this easy, or we can do this hard. 899 adb shell su root setprop persist.sys.boot.reason reboot,its_just_so_hard 900 ( exit ${save_ret} ) # because one can not just do ?=${save_ret} 901 else 902 report_bootstat_logs reboot,its_just_so_hard # report what we have so far 903 # user build mitigation 904 adb shell reboot its_just_so_hard 905 wait_for_screen 906 ( exit ${save_ret} ) # because one can not just do ?=${save_ret} 907 EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard 908 fi 909 # Ensure persist.sys.boot.reason now valid, failure here acts as a signal 910 # that we could choke up following tests. For example test_properties. 911 EXPECT_PROPERTY persist.sys.boot.reason reboot,its_just_so_hard ${flag} 912 report_bootstat_logs reboot,its_just_so_hard 913 } 914 915 [ "USAGE: run_bootloader [value [expected]] 916 917 bootloader boot reason injection tests: 918 - setBootloaderBootReason value 919 - adb shell reboot 920 - (wait until screen is up, boot has completed) 921 - adb shell getprop sys.boot.reason 922 - NB: should report reboot,value" ] 923 run_bootloader() { 924 bootloader_expected="${1}" 925 if [ -z "${bootloader_expected}" ]; then 926 bootloader_expected="${TEST#bootloader_}" 927 fi 928 if ! setBootloaderBootReason ${bootloader_expected}; then 929 echo " Skipping FAILURE." 2>&1 930 return 931 fi 932 duration_test 933 if [ X"warm" = X"${bootloader_expected}" ]; then 934 last_expected=cold 935 else 936 last_expected=warm 937 fi 938 adb reboot ${last_expected} 939 wait_for_screen 940 # Reset so that other tests do not get unexpected injection 941 setBootloaderBootReason 942 # Determine the expected values 943 sys_expected="${2}" 944 if [ -z "${sys_expected}" ]; then 945 sys_expected="`validate_reason ${bootloader_expected}`" 946 if [ "reboot" = "${sys_expected}" ]; then 947 sys_expected="${last_expected}" 948 fi 949 else 950 sys_expected=`validate_reason ${sys_expected}` 951 fi 952 case ${sys_expected} in 953 kernel_panic | kernel_panic,* | watchdog | watchdog,* ) 954 last_expected=${sys_expected} 955 ;; 956 esac 957 # Check values 958 EXPECT_PROPERTY ro.boot.bootreason "${bootloader_expected}" 959 EXPECT_PROPERTY sys.boot.reason "${sys_expected}" 960 EXPECT_PROPERTY persist.sys.boot.reason "${last_expected}" 961 report_bootstat_logs "${sys_expected}" 962 } 963 964 [ "USAGE: test_bootloader_<type> 965 966 bootloader boot reasons test injection" ] 967 test_bootloader_normal() { 968 run_bootloader 969 } 970 971 test_bootloader_watchdog() { 972 run_bootloader 973 } 974 975 test_bootloader_kernel_panic() { 976 run_bootloader 977 } 978 979 test_bootloader_oem_powerkey() { 980 run_bootloader 981 } 982 983 test_bootloader_wdog_reset() { 984 run_bootloader 985 } 986 987 test_bootloader_cold() { 988 run_bootloader 989 } 990 991 test_bootloader_warm() { 992 run_bootloader 993 } 994 995 test_bootloader_hard() { 996 run_bootloader 997 } 998 999 test_bootloader_recovery() { 1000 run_bootloader 1001 } 1002 1003 [ "USAGE: ${0##*/} [-s SERIAL] [tests] 1004 1005 Mainline executive to run the above tests" ] 1006 1007 # Rudimentary argument parsing 1008 1009 if [ ${#} -ge 2 -a X"-s" = X"${1}" ]; then 1010 export ANDROID_SERIAL="${2}" 1011 shift 2 1012 fi 1013 1014 if [ X"--help" = X"${1}" -o X"-h" = X"${1}" -o X"-?" = X"${1}" ]; then 1015 echo "USAGE: ${0##*/} [-s SERIAL] [tests]" 1016 echo tests - `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null` 1017 exit 0 1018 fi 1019 1020 # Check if all conditions for the script are sane 1021 1022 if [ -z "${ANDROID_SERIAL}" ]; then 1023 ndev=`( 1024 adb devices | grep -v 'List of devices attached' 1025 fastboot devices 1026 ) | 1027 grep -v "^[${SPACE}${TAB}]*\$" | 1028 wc -l` 1029 if [ ${ndev} -gt 1 ]; then 1030 echo "ERROR: no target device specified, ${ndev} connected" >&2 1031 echo "${RED}[ FAILED ]${NORMAL}" 1032 exit 1 1033 fi 1034 echo "WARNING: no target device specified" >&2 1035 fi 1036 1037 ret=0 1038 1039 # Test Series 1040 if [ X"all" = X"${*}" ]; then 1041 # automagically pick up all test_<function>s. 1042 eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null` 1043 if [ X"nothing" = X"${1}" ]; then 1044 shift 1 1045 fi 1046 fi 1047 if [ -z "$*" ]; then 1048 # automagically pick up all test_<function>, except test_optional_<function>. 1049 eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null | 1050 grep -v '^optional_'` 1051 if [ -z "${2}" ]; then 1052 # Hard coded should shell fail to find them above (search/permission issues) 1053 eval set properties ota cold factory_reset hard battery unknown \ 1054 kernel_panic warm thermal_shutdown userrequested_shutdown \ 1055 shell_reboot adb_reboot Its_Just_So_Hard_reboot \ 1056 bootloader_normal bootloader_watchdog bootloader_kernel_panic \ 1057 bootloader_oem_powerkey bootloader_wdog_reset \ 1058 bootloader_wdog_reset bootloader_wdog_reset bootloader_hard \ 1059 bootloader_recovery 1060 fi 1061 if [ X"nothing" = X"${1}" ]; then 1062 shift 1 1063 fi 1064 fi 1065 echo "INFO: selected test(s): ${@}" >&2 1066 echo 1067 # Prepare device 1068 setBootloaderBootReason 2>/dev/null 1069 # Start pouring through the tests. 1070 failures= 1071 successes= 1072 for t in "${@}"; do 1073 wrap_test ${t} 1074 retval=${?} 1075 if [ 0 = ${retval} ]; then 1076 if [ -z "${successes}" ]; then 1077 successes=${t} 1078 else 1079 successes="${successes} ${t}" 1080 fi 1081 else 1082 ret=${retval} 1083 if [ -z "${failures}" ]; then 1084 failures=${t} 1085 else 1086 failures="${failures} ${t}" 1087 fi 1088 fi 1089 echo 1090 done 1091 1092 if [ -n "${successes}" ]; then 1093 echo "${GREEN}[ PASSED ]${NORMAL} ${successes}" 1094 fi 1095 if [ -n "${failures}" ]; then 1096 echo "${RED}[ FAILED ]${NORMAL} ${failures}" 1097 fi 1098 exit ${ret} 1099