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.bootstat.first_boot_completed=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
19SPACE=" "
20ESCAPE=""
21TAB="	"
22GREEN="${ESCAPE}[38;5;40m"
23RED="${ESCAPE}[38;5;196m"
24NORMAL="${ESCAPE}[0m"
25# Best guess to an average device's reboot time, refined as tests return
26DURATION_DEFAULT=45
27STOP_ON_FAILURE=false
28progname="${0##*/}"
29progpath="${0%${progname}}"
30
31# Helper functions
32
33[ "USAGE: inFastboot
34
35Returns: true if device is in fastboot mode" ]
36inFastboot() {
37  fastboot devices | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
38}
39
40[ "USAGE: inAdb
41
42Returns: true if device is in adb mode" ]
43inAdb() {
44  adb devices | grep -v 'List of devices attached' | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
45}
46
47[ "USAGE: adb_sh <commands> </dev/stdin >/dev/stdout 2>/dev/stderr
48
49Returns: true if the command succeeded" ]
50adb_sh() {
51  local args=
52  for i in "${@}"; do
53    [ -z "${args}" ] || args="${args} "
54    if [ X"${i}" != X"${i#\'}" ]; then
55      args="${args}${i}"
56    elif [ X"${i}" != X"${i#*\\}" ]; then
57      args="${args}`echo ${i} | sed 's/\\\\/\\\\\\\\/g'`"
58    elif [ X"${i}" != X"${i#* }" ]; then
59      args="${args}'${i}'"
60    elif [ X"${i}" != X"${i#*${TAB}}" ]; then
61      args="${args}'${i}'"
62    else
63      args="${args}${i}"
64    fi
65  done
66  adb shell "${args}"
67}
68
69[ "USAGE: adb_su <commands> </dev/stdin >/dev/stdout 2>/dev/stderr
70
71Returns: true if the command running as root succeeded" ]
72adb_su() {
73  adb_sh su root "${@}"
74}
75
76[ "USAGE: hasPstore
77
78Returns: true if device (likely) has pstore data" ]
79hasPstore() {
80  if inAdb && [ 0 -eq `adb_su ls /sys/fs/pstore </dev/null | wc -l` ]; then
81    false
82  fi
83}
84
85[ "USAGE: get_property <prop>
86
87Returns the property value" ]
88get_property() {
89  adb_sh getprop ${1} 2>&1 </dev/null
90}
91
92[ "USAGE: isDebuggable
93
94Returns: true if device is (likely) a debug build" ]
95isDebuggable() {
96  if inAdb && [ 1 -ne `get_property ro.debuggable` ]; then
97    false
98  fi
99}
100
101[ "USAGE: checkDebugBuild [--noerror]
102
103Returns: true if device is a userdebug or eng release" ]
104checkDebugBuild() {
105  if isDebuggable; then
106    echo "INFO: '${TEST}' test requires userdebug build"
107  elif [ -n "${1}" ]; then
108    echo "WARNING: '${TEST}' test requires userdebug build"
109    false
110  else
111    echo "ERROR: '${TEST}' test requires userdebug build, skipping FAILURE"
112    duration_prefix="~"
113    duration_estimate=1
114    false
115  fi >&2
116}
117
118[ "USAGE: setBootloaderBootReason [value]
119
120Returns: true if device supports and set boot reason injection" ]
121setBootloaderBootReason() {
122  inAdb || ( echo "ERROR: device not in adb mode." >&2 ; false ) || return 1
123  if [ -z "`adb_sh ls /etc/init/bootstat-debug.rc 2>/dev/null </dev/null`" ]; then
124    echo "ERROR: '${TEST}' test requires /etc/init/bootstat-debug.rc" >&2
125    return 1
126  fi
127  checkDebugBuild || return 1
128  if adb_su "cat /proc/cmdline | tr '\\0 ' '\\n\\n'" </dev/null |
129     grep '^androidboot[.]bootreason=[^ ]' >/dev/null; then
130    echo "ERROR: '${TEST}' test requires a device with a bootloader that" >&2
131    echo "       does not set androidboot.bootreason kernel parameter." >&2
132    return 1
133  fi
134  adb_su setprop persist.test.boot.reason "'${1}'" 2>/dev/null </dev/null
135  test_reason="`get_property persist.test.boot.reason`"
136  if [ X"${test_reason}" != X"${1}" ]; then
137    echo "ERROR: can not set persist.test.boot.reason to '${1}'." >&2
138    return 1
139  fi
140}
141
142[ "USAGE: enterPstore
143
144Prints a warning string requiring functional pstore
145
146Returns: pstore_ok variable set to true or false" ]
147enterPstore() {
148  if hasPstore; then
149    echo "INFO: '${TEST}' test requires functional and reliable pstore"
150    pstore_ok=true
151  else
152    echo "WARNING: '${TEST}' test requires functional pstore"
153    pstore_ok=false
154  fi >&2
155  ${pstore_ok}
156}
157
158[ "USAGE: exitPstore
159
160Prints an error string requiring functional pstore
161
162Returns: clears error if pstore dysfunctional" ]
163exitPstore() {
164  save_ret=${?}
165  if [ ${save_ret} != 0 ]; then
166    if hasPstore; then
167      return ${save_ret}
168    fi
169    if [ true = ${pstore_ok} ]; then
170      echo "WARNING: '${TEST}' test requires functional pstore"
171      return ${save_ret}
172    fi
173    echo "ERROR: '${TEST}' test requires functional pstore, skipping FAILURE"
174    duration_prefix="~"
175    duration_estimate=1
176  fi >&2
177}
178
179[ "USAGE: format_duration <seconds>
180
181human readable output whole seconds, whole minutes or mm:ss" ]
182format_duration() {
183  if [ -z "${1}" ]; then
184    echo unknown
185    return
186  fi
187  seconds=`expr ${1} % 60`
188  minutes=`expr ${1} / 60`
189  if [ 0 -eq ${minutes} ]; then
190    if [ 1 -eq ${1} ]; then
191      echo 1 second
192      return
193    fi
194    echo ${1} seconds
195    return
196  elif [ 60 -eq ${1} ]; then
197    echo 1 minute
198    return
199  elif [ 0 -eq ${seconds} ]; then
200    echo ${minutes} minutes
201    return
202  fi
203  echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10`
204}
205
206wait_for_screen_timeout=900
207[ "USAGE: wait_for_screen [-n] [TIMEOUT]
208
209-n - echo newline at exit
210TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ]
211wait_for_screen() {
212  exit_function=true
213  if [ X"-n" = X"${1}" ]; then
214    exit_function=echo
215    shift
216  fi
217  timeout=${wait_for_screen_timeout}
218  if [ ${#} -gt 0 ]; then
219    timeout=${1}
220    shift
221  fi
222  counter=0
223  while true; do
224    if inFastboot; then
225      fastboot reboot
226    elif inAdb; then
227      if [ 0 != ${counter} ]; then
228        adb wait-for-device </dev/null >/dev/null 2>/dev/null
229      fi
230      if [ -n "`get_property sys.boot.reason`" ]
231      then
232        vals=`get_property |
233              sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\|bootstat[.]first_boot_completed\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
234        if [ X"${vals}" != X"${vals##*boot_completed=1}" ]; then
235          if [ X"${vals}" != X"${vals##*logbootcomple=1}" ]; then
236            sleep 1
237            break
238          fi
239          if [ X"${vals}" != X"${vals##*bootstat.first_boot_completed=1}" ]; then
240            sleep 1
241            break
242          fi
243        fi
244      fi
245    fi
246    counter=`expr ${counter} + 1`
247    if [ ${counter} -gt ${timeout} ]; then
248      ${exit_function}
249      echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2
250      return 1
251    fi
252    sleep 1
253  done
254  ${exit_function}
255}
256
257[ "USAGE: EXPECT_EQ <lval> <rval> [message]
258
259Returns true if (regex) lval matches rval" ]
260EXPECT_EQ() {
261  lval="${1}"
262  rval="${2}"
263  shift 2
264  if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then
265    if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval%
266*}" ]; then
267      echo "ERROR: expected \"${lval}\"" >&2
268      echo "       got \"${rval}\"" |
269        sed ': again
270             N
271             s/\(\n\)\([^ ]\)/\1             \2/
272             t again' >&2
273      if [ -n "${*}" ] ; then
274        echo "       ${*}" >&2
275      fi
276    else
277      echo "ERROR: expected \"${lval}\" got \"${rval}\" ${*}" >&2
278    fi
279    return 1
280  fi
281  if [ -n "${*}" ] ; then
282    if [ X"${lval}" != X"${rval}" ]; then
283      if [ `echo ${lval}${rval}${*} | wc -c` -gt 60 -o "${rval}" != "${rval%
284*}" ]; then
285        echo "INFO: ok \"${lval}\"" >&2
286        echo "       = \"${rval}\"" |
287          sed ': again
288               N
289               s/\(\n\)\([^ ]\)/\1          \2/
290               t again' >&2
291        if [ -n "${*}" ] ; then
292          echo "      ${*}" >&2
293        fi
294      else
295        echo "INFO: ok \"${lval}\" = \"${rval}\" ${*}" >&2
296      fi
297    else
298      echo "INFO: ok \"${lval}\" ${*}" >&2
299    fi
300  fi
301  return 0
302}
303
304BAD_BOOTLOADER_REASON=
305
306[ "USAGE: EXPECT_PROPERTY <prop> <value> [--allow_failure]
307
308Returns true (0) if current return (regex) value is true and the result matches
309and the incoming return value is true as well (wired-or)" ]
310EXPECT_PROPERTY() {
311  save_ret=${?}
312  property="${1}"
313  value="${2}"
314  shift 2
315  val=`get_property ${property}`
316  EXPECT_EQ "${value}" "${val}" for Android property ${property}
317  local_ret=${?}
318  if [ 0 != ${local_ret} -a "ro.boot.bootreason" = "${property}" ]; then
319    if [ -z "${BAD_BOOTLOADER_REASON}" ]; then
320      BAD_BOOTLOADER_REASON=${val}
321    elif [ X"${BAD_BOOTLOADER_REASON}" = X"${val}" ]; then
322      local_ret=0
323    fi
324  fi
325  if [ 0 != ${local_ret} ]; then
326    if [ -z "${1}" ] ; then
327      save_ret=${local_ret}
328    fi
329  fi
330  return ${save_ret}
331}
332
333[ "USAGE: adb_date >/dev/stdout
334
335Returns: report device epoch time (suitable for logcat -t)" ]
336adb_date() {
337  adb_sh date +%s.%N </dev/null
338}
339
340[ "USAGE: report_bootstat_logs [-t<timestamp>] <expected> ...
341
342if not prefixed with a minus (-), <expected> will become a series of expected
343matches:
344
345    bootstat: Canonical boot reason: <expected_property_value>
346
347If prefixed with a minus, <expected> will look for an exact match after
348removing the minux prefix.  All expected content is _dropped_ from the output
349and in essence forms a known blacklist, unexpected content will show.
350
351Report any logs, minus a known blacklist, preserve the current exit status" ]
352report_bootstat_logs() {
353  save_ret=${?}
354  match=
355  timestamp=-d
356  for i in "${@}"; do
357    if [ X"${i}" != X"${i#-t}" ]; then
358      timestamp="${i}"
359    elif [ X"${i}" != X"${i#-}" ]; then
360      match="${match}
361${i#-}"
362    else
363      match="${match}
364bootstat: Canonical boot reason: ${i}"
365    fi
366  done
367  adb logcat -b all ${timestamp} |
368  grep bootstat[^e] |
369  grep -v -F "bootstat: Service started: /system/bin/bootstat --record_boot_complete${match}
370bootstat: Failed to read /data/misc/bootstat/post_decrypt_time_elapsed: No such file or directory
371bootstat: Failed to parse boot time record: /data/misc/bootstat/post_decrypt_time_elapsed
372bootstat: Service started: /system/bin/bootstat --record_boot_reason
373bootstat: Service started: /system/bin/bootstat --set_system_boot_reason
374bootstat: Service started: /system/bin/bootstat --record_time_since_factory_reset
375bootstat: Service started: /system/bin/bootstat -l
376bootstat: Service started: /system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l
377bootstat: Battery level at shutdown 100%
378bootstat: Battery level at startup 100%
379init    : Parsing file /system/etc/init/bootstat.rc...
380init    : Parsing file /system/etc/init/bootstat-debug.rc...
381init    : processing action (persist.test.boot.reason=*) from (/system/etc/init/bootstat-debug.rc:
382init    : Command 'setprop ro.boot.bootreason \${persist.test.boot.reason}' action=persist.test.boot.reason=* (/system/etc/init/bootstat-debug.rc:
383init    : processing action (post-fs-data) from (/system/etc/init/bootstat.rc
384init    : processing action (boot) from (/system/etc/init/bootstat.rc
385init    : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc
386init    : processing action (ro.boot.bootreason=* && post-fs) from (/system/etc/init/bootstat.rc
387init    : processing action (sys.bootstat.first_zygote_start=0 && zygote-start) from (/system/etc/init/bootstat.rc
388init    : processing action (sys.boot_completed=1 && sys.bootstat.first_boot_completed=0) from (/system/etc/init/bootstat.rc
389 (/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
390 (/system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
391 (/system/bin/bootstat -r post_decrypt_time_elapsed)'
392init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
393init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
394init    : Command 'exec - system log -- /system/bin/bootstat --record_time_since_factory_reset' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
395init    : Command 'exec_background - system log -- /system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc
396 (/system/bin/bootstat --record_boot_complete)'...
397 (/system/bin/bootstat --record_boot_complete)' (pid${SPACE}
398 (/system/bin/bootstat --record_boot_reason)'...
399 (/system/bin/bootstat --record_boot_reason)' (pid${SPACE}
400 (/system/bin/bootstat --record_time_since_factory_reset)'...
401 (/system/bin/bootstat --record_time_since_factory_reset)' (pid${SPACE}
402 (/system/bin/bootstat --set_system_boot_reason)'...
403 (/system/bin/bootstat --set_system_boot_reason)' (pid${SPACE}
404 (/system/bin/bootstat -l)'...
405 (/system/bin/bootstat -l)' (pid " |
406  grep -v 'bootstat: Unknown boot reason: $' # Hikey Special
407  return ${save_ret}
408}
409
410[ "USAGE: start_test [message]
411
412Record start of test, preserve exit status" ]
413start_test() {
414  save_ret=${?}
415  duration_prefix="~"
416  duration_estimate=1
417  START=`date +%s`
418  echo "${GREEN}[ RUN      ]${NORMAL} ${TEST} ${*}"
419  return ${save_ret}
420}
421
422duration_sum_diff=0
423duration_num=0
424[ "USAGE: duration_test [[prefix]seconds]
425
426Report the adjusted and expected test duration" ]
427duration_test() {
428  duration_prefix=${1%%[0123456789]*}
429  if [ -z "${duration_prefix}" ]; then
430    duration_prefix="~"
431  fi
432  duration_estimate="${1#${duration_prefix}}"
433  if [ -z "${duration_estimate}" ]; then
434    duration_estimate="${DURATION_DEFAULT}"
435  fi
436  duration_new_estimate="${duration_estimate}"
437  if [ 0 -ne ${duration_num} ]; then
438    duration_new_estimate=`expr ${duration_new_estimate} + \
439      \( ${duration_num} / 2 + ${duration_sum_diff} \) / ${duration_num}`
440    # guard against catastrophe
441    if [ -z "${duration_new_estimate}" ]; then
442      duration_new_estimate=${duration_estimate}
443    fi
444  fi
445  # negative values are so undignified
446  if [ 0 -ge ${duration_new_estimate} ]; then
447    duration_new_estimate=1
448  fi
449  echo "INFO: expected duration of '${TEST}' test" \
450       "${duration_prefix}`format_duration ${duration_new_estimate}`" >&2
451}
452
453[ "USAGE: end_test [message]
454
455Document duration and success of test, preserve exit status" ]
456end_test() {
457  save_ret=${?}
458  END=`date +%s`
459  duration=`expr ${END} - ${START} 2>/dev/null`
460  [ 0 -ge ${duration} ] ||
461    echo "INFO: '${TEST}' test duration `format_duration ${duration}`" >&2
462  if [ ${save_ret} = 0 ]; then
463    if [ 0 -lt ${duration} -a 0 -lt ${duration_estimate} -a \( \
464           X"~" = X"${duration_prefix}" -o \
465           ${duration_estimate} -gt ${duration} \) ]; then
466      duration_sum_diff=`expr ${duration_sum_diff} + \
467                              ${duration} - ${duration_estimate}`
468      duration_num=`expr ${duration_num} + 1`
469    fi
470    echo "${GREEN}[       OK ]${NORMAL} ${TEST} ${*}"
471  else
472    echo "${RED}[  FAILED  ]${NORMAL} ${TEST} ${*}"
473    if ${STOP_ON_FAILURE}; then
474      exit ${save_ret}
475    fi
476  fi
477  return ${save_ret}
478}
479
480[ "USAGE: wrap_test <test> [message]
481
482All tests below are wrapped with this helper" ]
483wrap_test() {
484  if [ -z "${1}" -o X"nothing" = X"${1}" ]; then
485    return
486  fi
487  TEST=${1}
488  shift
489  start_test ${1}
490  eval test_${TEST}
491  end_test ${2}
492}
493
494[ "USAGE: validate_reason <value>
495
496Check property for CTS compliance with our expectations. Return a cleansed
497string representing what is acceptable.
498
499NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ]
500validate_reason() {
501  var=`echo -n ${*} |
502       tr '[A-Z]' '[a-z]' |
503       tr ' \f\t\r\n' '_____'`
504  case ${var} in
505    watchdog | watchdog,?* ) ;;
506    kernel_panic | kernel_panic,?* ) ;;
507    recovery | recovery,?* ) ;;
508    bootloader | bootloader,?* ) ;;
509    cold | cold,?* ) ;;
510    hard | hard,?* ) ;;
511    warm | warm,?* ) ;;
512    shutdown | shutdown,?* ) ;;
513    reboot,reboot | reboot,reboot,* )     var=${var#reboot,} ; var=${var%,} ;;
514    reboot,cold | reboot,cold,* )         var=${var#reboot,} ; var=${var%,} ;;
515    reboot,hard | reboot,hard,* )         var=${var#reboot,} ; var=${var%,} ;;
516    reboot,warm | reboot,warm,* )         var=${var#reboot,} ; var=${var%,} ;;
517    reboot,recovery | reboot,recovery,* ) var=${var#reboot,} ; var=${var%,} ;;
518    reboot,bootloader | reboot,bootloader,* ) var=${var#reboot,} ; var=${var%,} ;;
519    reboot | reboot,?* ) ;;
520    # Aliases and Heuristics
521    *wdog* | *watchdog* )                   var="watchdog" ;;
522    *powerkey* | *power_key* | *PowerKey* ) var="cold,powerkey" ;;
523    *panic* | *kernel_panic* )              var="kernel_panic" ;;
524    *thermal* )                             var="shutdown,thermal" ;;
525    *s3_wakeup* )                           var="warm,s3_wakeup" ;;
526    *hw_reset* )                            var="hard,hw_reset" ;;
527    *usb* )                                 var="cold,charger" ;;
528    *rtc* )                                 var="cold,rtc" ;;
529    *2sec_reboot* )                         var="cold,rtc,2sec" ;;
530    *wdt_by_pass_pwk* )                     var="warm" ;;
531    wdt )                                   var="reboot" ;;
532    *tool_by_pass_pwk* )                    var="reboot,tool" ;;
533    *bootloader* )                          var="bootloader" ;;
534    * )                                     var="reboot" ;;
535  esac
536  echo ${var}
537}
538
539[ "USAGE: validate_property <property>
540
541Check property for CTS compliance with our expectations. Return a cleansed
542string representing what is acceptable.
543
544NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ]
545validate_property() {
546  val=`get_property ${1}`
547  ret=`validate_reason "${val}"`
548  if [ "reboot" = "${ret}" ]; then
549    ret=`validate_reason "reboot,${val}"`
550  fi
551  echo ${ret}
552}
553
554[ "USAGE: check_boilerblate_properties
555
556Check for common property values" ]
557check_boilerplate_properties() {
558  EXPECT_PROPERTY persist.sys.boot.reason ""
559  save_ret=${?}
560  reason=`validate_property sys.boot.reason`
561  ( exit ${save_ret} )  # because one can not just do ?=${save_ret}
562  EXPECT_PROPERTY persist.sys.boot.reason.history "${reason},[1-9][0-9]*\(\|[^0-9].*\)"
563}
564
565#
566# Actual test frames
567#
568
569[ "USAGE: test_properties
570
571properties test
572- (wait until screen is up, boot has completed)
573- adb shell getprop ro.boot.bootreason (bootloader reason)
574- adb shell getprop persist.sys.boot.reason (last reason)
575- adb shell getprop sys.boot.reason.last (last last reason)
576- adb shell getprop sys.boot.reason (system reason)
577- NB: all should have a value that is compliant with our known set." ]
578test_properties() {
579  duration_test 1
580  wait_for_screen
581  retval=0
582  # sys.boot.reason is last for a reason
583  check_set="ro.boot.bootreason sys.boot.reason.last sys.boot.reason"
584  bootloader=""
585  # NB: this test could fail if performed _after_ optional_factory_reset test
586  # and will report
587  #  ERROR: expected "reboot" got ""
588  #        for Android property sys.boot.reason.last
589  # following is mitigation for the persist.sys.boot.reason, skip it
590  if [ "reboot,factory_reset" = "`validate_property ro.boot_bootreason`" ]; then
591    check_set="ro.boot.bootreason sys.boot.reason"
592    bootloader="bootloader"
593  fi
594  for prop in ${check_set}; do
595    reason=`validate_property ${prop}`
596    EXPECT_PROPERTY ${prop} ${reason} || retval=${?}
597  done
598  check_boilerplate_properties || retval=${?}
599  report_bootstat_logs ${reason} ${bootloader}
600  return ${retval}
601}
602
603[ "USAGE: test_ota
604
605ota test
606- rm out/.kati_stamp-* out/build_date.txt out/build_number.txt
607- rm out/target/product/*/*/*.prop
608- rm -r out/target/product/*/obj/ETC/system_build_prop_intermediates
609- m
610- NB: ro.build.date.utc should update
611- fastboot flashall
612- (wait until screen is up, boot has completed)
613- adb shell getprop sys.boot.reason
614- NB: should report ota
615
616Decision to change the build itself rather than trick bootstat by
617rummaging through its data files was made." ]
618test_ota() {
619  duration_test ">300"
620  echo "      extended by build and flashing times" >&2
621  if [ -z "${TARGET_PRODUCT}" -o \
622       -z "${ANDROID_PRODUCT_OUT}" -o \
623       -z "${ANDROID_BUILD_TOP}" -o \
624       -z "${TARGET_BUILD_VARIANT}" ]; then
625    echo "ERROR: Missing envsetup.sh and lunch" >&2
626    return 1
627  fi
628  rm ${ANDROID_PRODUCT_OUT%/out/*}/out/.kati_stamp-* ||
629    true
630  rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_date.txt ||
631    true
632  rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_number.txt ||
633    true
634  rm ${ANDROID_PRODUCT_OUT}/*/*.prop ||
635    true
636  rm -r ${ANDROID_PRODUCT_OUT}/obj/ETC/system_build_prop_intermediates ||
637    true
638  pushd ${ANDROID_BUILD_TOP} >&2
639  build/soong/soong_ui.bash --make-mode >&2
640  if [ ${?} != 0 ]; then
641    popd >&2
642    return 1
643  fi
644  if ! inFastboot; then
645    adb reboot-bootloader >&2
646  fi
647  fastboot flashall >&2
648  popd >&2
649  wait_for_screen
650  EXPECT_PROPERTY sys.boot.reason "\(reboot,ota\|bootloader\)"
651  EXPECT_PROPERTY sys.boot.reason.last bootloader
652  check_boilerplate_properties
653  report_bootstat_logs reboot,ota bootloader
654}
655
656[ "USAGE: test_optional_ota
657
658fast and fake (touch build_date on device to make it different)" ]
659test_optional_ota() {
660  checkDebugBuild || return
661  duration_test
662  adb_su touch /data/misc/bootstat/build_date >&2 </dev/null
663  adb reboot ota
664  wait_for_screen
665  EXPECT_PROPERTY sys.boot.reason reboot,ota
666  EXPECT_PROPERTY sys.boot.reason.last reboot,ota
667  check_boilerplate_properties
668  report_bootstat_logs reboot,ota
669}
670
671[ "USAGE: [TEST=<test>] blind_reboot_test
672
673Simple tests helper
674- adb reboot <test>
675- (wait until screen is up, boot has completed)
676- adb shell getprop sys.boot.reason
677- NB: should report <test>, or reboot,<test> depending on canonical rules
678
679We interleave the simple reboot tests between the hard/complex ones
680as a means of checking sanity and any persistent side effect of the
681other tests." ]
682blind_reboot_test() {
683  duration_test
684  case ${TEST} in
685    bootloader | recovery | cold | hard | warm ) reason=${TEST} ;;
686    *)                                           reason=reboot,${TEST#optional_} ;;
687  esac
688  adb reboot ${TEST#optional_}
689  wait_for_screen
690  bootloader_reason=`validate_property ro.boot.bootreason`
691  EXPECT_PROPERTY ro.boot.bootreason ${bootloader_reason}
692  # to make sys.boot.reason report user friendly
693  reasons=${reason}
694  if [ "${bootloader_reason}" != "${reason}" -a -n "${bootloader_reason}" ]; then
695    reasons="\(${reason}\|${bootloader_reason}\)"
696  fi
697  EXPECT_PROPERTY sys.boot.reason ${reasons}
698  EXPECT_PROPERTY sys.boot.reason.last ${reason}
699  check_boilerplate_properties
700  report_bootstat_logs ${reason} ${bootloader_reason}
701}
702
703[ "USAGE: test_cold
704
705cold test
706- adb reboot cold
707- (wait until screen is up, boot has completed)
708- adb shell getprop sys.boot.reason
709- NB: should report cold" ]
710test_cold() {
711  blind_reboot_test
712}
713
714[ "USAGE: test_factory_reset
715
716factory_reset test
717- adb shell su root rm /data/misc/bootstat/build_date
718- adb reboot
719- (wait until screen is up, boot has completed)
720- adb shell getprop sys.boot.reason
721- NB: should report factory_reset
722
723Decision to rummage through bootstat data files was made as
724a _real_ factory_reset is too destructive to the device." ]
725test_factory_reset() {
726  checkDebugBuild || return
727  duration_test
728  adb_su rm /data/misc/bootstat/build_date >&2 </dev/null
729  adb reboot >&2
730  wait_for_screen
731  EXPECT_PROPERTY sys.boot.reason reboot,factory_reset
732  EXPECT_PROPERTY sys.boot.reason.last "reboot,.*"
733  check_boilerplate_properties
734  report_bootstat_logs reboot,factory_reset reboot, reboot,adb \
735    "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \
736    "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date"
737}
738
739[ "USAGE: test_optional_factory_reset
740
741factory_reset test
742- adb reboot-bootloader
743- fastboot format userdata
744- fastboot reboot
745- (wait until screen is up, boot has completed)
746- adb shell getprop sys.boot.reason
747- NB: should report factory_reset
748
749For realz, and disruptive" ]
750test_optional_factory_reset() {
751  duration_test 60
752  if ! inFastboot; then
753    adb reboot-bootloader
754  fi
755  fastboot format userdata >&2
756  save_ret=${?}
757  if [ 0 != ${save_ret} ]; then
758    echo "ERROR: fastboot can not format userdata" >&2
759  fi
760  fastboot reboot >&2
761  wait_for_screen
762  ( exit ${save_ret} )  # because one can not just do ?=${save_ret}
763  EXPECT_PROPERTY sys.boot.reason reboot,factory_reset
764  EXPECT_PROPERTY sys.boot.reason.last "\(\|bootloader\)"
765  check_boilerplate_properties
766  report_bootstat_logs reboot,factory_reset bootloader \
767    "-bootstat: Failed to read /data/misc/bootstat/last_boot_time_utc: No such file or directory" \
768    "-bootstat: Failed to parse boot time record: /data/misc/bootstat/last_boot_time_utc" \
769    "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \
770    "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date" \
771    "-bootstat: Failed to read /data/misc/bootstat/factory_reset: No such file or directory" \
772    "-bootstat: Failed to parse boot time record: /data/misc/bootstat/factory_reset"
773}
774
775[ "USAGE: test_hard
776
777hard test:
778- adb reboot hard
779- (wait until screen is up, boot has completed)
780- adb shell getprop sys.boot.reason
781- NB: should report hard" ]
782test_hard() {
783  blind_reboot_test
784}
785
786[ "USAGE: test_battery
787
788battery test (trick):
789- echo healthd: battery l=2<space> | adb shell su root tee /dev/kmsg
790- adb reboot cold
791- (wait until screen is up, boot has completed)
792- adb shell getprop sys.boot.reason
793- NB: should report reboot,battery, unless healthd managed to log
794  before reboot in above trick.
795
796- Bonus points (manual extras)
797- Make sure the following is added to the /init.rc file in post-fs
798  section before logd is started:
799    +    setprop logd.kernel false
800    +    rm /sys/fs/pstore/console-ramoops
801    +    rm /sys/fs/pstore/console-ramoops-0
802    +    write /dev/kmsg \"healthd: battery l=2${SPACE}
803    +\"
804- adb reboot fs
805- (wait until screen is up, boot has completed)
806- adb shell getprop sys.boot.reason
807- NB: should report reboot,battery
808- (replace set logd.kernel true to the above, and retry test)" ]
809test_battery() {
810  checkDebugBuild || return
811  duration_test 120
812  enterPstore
813  # Send it _many_ times to combat devices with flakey pstore
814  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
815    echo 'healthd: battery l=2 ' | adb_su tee /dev/kmsg >/dev/null
816  done
817  adb reboot cold >&2
818  adb wait-for-device
819  wait_for_screen
820  adb_su </dev/null \
821    cat /proc/fs/pstore/console-ramoops \
822        /proc/fs/pstore/console-ramoops-0 2>/dev/null |
823    grep 'healthd: battery l=' |
824    tail -1 |
825    grep 'healthd: battery l=2 ' >/dev/null || (
826      if ! EXPECT_PROPERTY sys.boot.reason reboot,battery >/dev/null 2>/dev/null; then
827        # retry
828        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
829          echo 'healthd: battery l=2 ' | adb_su tee /dev/kmsg >/dev/null
830        done
831        adb reboot cold >&2
832        adb wait-for-device
833        wait_for_screen
834      fi
835    )
836
837  EXPECT_PROPERTY sys.boot.reason shutdown,battery
838  EXPECT_PROPERTY sys.boot.reason.last cold
839  check_boilerplate_properties
840  report_bootstat_logs shutdown,battery "-bootstat: Battery level at shutdown 2%"
841  exitPstore
842}
843
844[ "USAGE: test_optional_battery
845
846battery shutdown test:
847- adb shell setprop sys.powerctl shutdown,battery
848- (power up the device)
849- (wait until screen is up, boot has completed)
850- adb shell getprop sys.boot.reason
851- NB: should report shutdown,battery" ]
852test_optional_battery() {
853  duration_test ">60"
854  echo "      power on request" >&2
855  adb_sh setprop sys.powerctl shutdown,battery </dev/null
856  sleep 5
857  echo -n "WARNING: Please power device back up, waiting ... " >&2
858  wait_for_screen -n >&2
859  EXPECT_PROPERTY sys.boot.reason shutdown,battery
860  EXPECT_PROPERTY sys.boot.reason.last shutdown,battery
861  check_boilerplate_properties
862  report_bootstat_logs shutdown,battery
863}
864
865[ "USAGE: test_optional_battery_thermal
866
867battery thermal shutdown test:
868- adb shell setprop sys.powerctl shutdown,thermal,battery
869- (power up the device)
870- (wait until screen is up, boot has completed)
871- adb shell getprop sys.boot.reason
872- NB: should report shutdown,thermal,battery" ]
873test_optional_battery_thermal() {
874  duration_test ">60"
875  echo "      power on request" >&2
876  adb_sh setprop sys.powerctl shutdown,thermal,battery </dev/null
877  sleep 5
878  echo -n "WARNING: Please power device back up, waiting ... " >&2
879  wait_for_screen -n >&2
880  EXPECT_PROPERTY sys.boot.reason shutdown,thermal,battery
881  EXPECT_PROPERTY sys.boot.reason.last shutdown,thermal,battery
882  check_boilerplate_properties
883  report_bootstat_logs shutdown,thermal,battery
884}
885
886[ "USAGE: test_unknown
887
888unknown test
889- adb reboot unknown
890- (wait until screen is up, boot has completed)
891- adb shell getprop sys.boot.reason
892- NB: should report reboot,unknown
893- NB: expect log \"... I bootstat: Unknown boot reason: reboot,unknown\"" ]
894test_unknown() {
895  blind_reboot_test
896}
897
898[ "USAGE: test_kernel_panic
899
900kernel_panic test:
901- echo c | adb shell su root tee /proc/sysrq-trigger
902- (wait until screen is up, boot has completed)
903- adb shell getprop sys.boot.reason
904- NB: should report kernel_panic,sysrq" ]
905test_kernel_panic() {
906  checkDebugBuild || return
907  duration_test ">90"
908  panic_msg="kernel_panic,sysrq"
909  enterPstore
910  if [ ${?} != 0 ]; then
911    echo "         or functional bootloader" >&2
912    panic_msg="\(kernel_panic,sysrq\|kernel_panic\)"
913    pstore_ok=true
914  fi
915  echo c | adb_su tee /proc/sysrq-trigger >/dev/null
916  wait_for_screen
917  EXPECT_PROPERTY sys.boot.reason ${panic_msg}
918  EXPECT_PROPERTY sys.boot.reason.last ${panic_msg}
919  check_boilerplate_properties
920  report_bootstat_logs kernel_panic,sysrq
921  exitPstore
922}
923
924[ "USAGE: test_kernel_panic_subreason
925
926kernel_panic_subreason test:
927- echo SysRq : Trigger a crash : 'test' | adb shell su root tee /dev/kmsg
928- echo c | adb shell su root tee /proc/sysrq-trigger
929- (wait until screen is up, boot has completed)
930- adb shell getprop sys.boot.reason
931- NB: should report kernel_panic,sysrq,test" ]
932test_kernel_panic_subreason() {
933  checkDebugBuild || return
934  duration_test ">90"
935  panic_msg="kernel_panic,sysrq,test"
936  enterPstore
937  if [ ${?} != 0 ]; then
938    echo "         or functional bootloader" >&2
939    panic_msg="\(kernel_panic,sysrq,test\|kernel_panic\)"
940    pstore_ok=true
941  fi
942  echo "SysRq : Trigger a crash : 'test'" | adb_su tee /dev/kmsg
943  echo c | adb_su tee /proc/sysrq-trigger >/dev/null
944  wait_for_screen
945  EXPECT_PROPERTY sys.boot.reason ${panic_msg}
946  EXPECT_PROPERTY sys.boot.reason.last ${panic_msg}
947  check_boilerplate_properties
948  report_bootstat_logs kernel_panic,sysrq,test \
949    "-bootstat: Unknown boot reason: kernel_panic,sysrq,test"
950  exitPstore
951}
952
953[ "USAGE: test_kernel_panic_hung
954
955kernel_panic_hung test:
956- echo Kernel panic - not synching: hung_task: blocked tasks |
957  adb shell su root tee /dev/kmsg
958- adb reboot warm
959- (wait until screen is up, boot has completed)
960- adb shell getprop sys.boot.reason
961- NB: should report kernel_panic,hung" ]
962test_kernel_panic_hung() {
963  checkDebugBuild || return
964  duration_test
965  panic_msg="kernel_panic,hung"
966  enterPstore
967  if [ ${?} != 0 ]; then
968    echo "         or functional bootloader" >&2
969    panic_msg="\(kernel_panic,hung\|reboot,hung\)"
970    pstore_ok=true
971  fi
972  echo "Kernel panic - not syncing: hung_task: blocked tasks" |
973    adb_su tee /dev/kmsg
974  adb reboot warm
975  wait_for_screen
976  EXPECT_PROPERTY sys.boot.reason ${panic_msg}
977  EXPECT_PROPERTY sys.boot.reason.last ${panic_msg}
978  check_boilerplate_properties
979  report_bootstat_logs kernel_panic,hung
980  exitPstore
981}
982
983[ "USAGE: test_warm
984
985warm test
986- adb reboot warm
987- (wait until screen is up, boot has completed)
988- adb shell getprop sys.boot.reason
989- NB: should report warm" ]
990test_warm() {
991  blind_reboot_test
992}
993
994[ "USAGE: test_thermal_shutdown
995
996thermal shutdown test:
997- adb shell setprop sys.powerctl shutdown,thermal
998- (power up the device)
999- (wait until screen is up, boot has completed)
1000- adb shell getprop sys.boot.reason
1001- NB: should report shutdown,thermal" ]
1002test_thermal_shutdown() {
1003  duration_test ">60"
1004  echo "      power on request" >&2
1005  adb_sh setprop sys.powerctl shutdown,thermal </dev/null
1006  sleep 5
1007  echo -n "WARNING: Please power device back up, waiting ... " >&2
1008  wait_for_screen -n >&2
1009  EXPECT_PROPERTY sys.boot.reason shutdown,thermal
1010  EXPECT_PROPERTY sys.boot.reason.last shutdown,thermal
1011  check_boilerplate_properties
1012  report_bootstat_logs shutdown,thermal
1013}
1014
1015[ "USAGE: test_userrequested_shutdown
1016
1017userrequested shutdown test:
1018- adb shell setprop sys.powerctl shutdown,userrequested
1019- (power up the device)
1020- (wait until screen is up, boot has completed)
1021- adb shell getprop sys.boot.reason
1022- NB: should report shutdown,userrequested" ]
1023test_userrequested_shutdown() {
1024  duration_test ">60"
1025  echo "      power on request" >&2
1026  adb_sh setprop sys.powerctl shutdown,userrequested </dev/null
1027  sleep 5
1028  echo -n "WARNING: Please power device back up, waiting ... " >&2
1029  wait_for_screen -n >&2
1030  EXPECT_PROPERTY sys.boot.reason shutdown,userrequested
1031  EXPECT_PROPERTY sys.boot.reason.last shutdown,userrequested
1032  check_boilerplate_properties
1033  report_bootstat_logs shutdown,userrequested
1034}
1035
1036[ "USAGE: test_shell_reboot
1037
1038shell reboot test:
1039- adb shell reboot
1040- (wait until screen is up, boot has completed)
1041- adb shell getprop sys.boot.reason
1042- NB: should report reboot,shell" ]
1043test_shell_reboot() {
1044  duration_test
1045  adb_sh reboot </dev/null
1046  wait_for_screen
1047  EXPECT_PROPERTY sys.boot.reason reboot,shell
1048  EXPECT_PROPERTY sys.boot.reason.last reboot,shell
1049  check_boilerplate_properties
1050  report_bootstat_logs reboot,shell
1051}
1052
1053[ "USAGE: test_adb_reboot
1054
1055adb reboot test:
1056- adb reboot
1057- (wait until screen is up, boot has completed)
1058- adb shell getprop sys.boot.reason
1059- NB: should report reboot,adb" ]
1060test_adb_reboot() {
1061  duration_test
1062  adb reboot
1063  wait_for_screen
1064  EXPECT_PROPERTY sys.boot.reason reboot,adb
1065  EXPECT_PROPERTY sys.boot.reason.last reboot,adb
1066  check_boilerplate_properties
1067  report_bootstat_logs reboot,adb
1068}
1069
1070[ "USAGE: test_rescueparty
1071
1072rescueparty test
1073- adb reboot rescueparty
1074- (wait until screen is up, boot has completed)
1075- adb shell getprop sys.boot.reason
1076- adb shell getprop ro.boot.bootreason
1077- NB: should report reboot,rescueparty" ]
1078test_optional_rescueparty() {
1079  blind_reboot_test
1080  echo "WARNING: legacy devices are allowed to fail following ro.boot.bootreason result" >&2
1081  EXPECT_PROPERTY ro.boot.bootreason '\(reboot\|reboot,rescueparty\)'
1082}
1083
1084[ "USAGE: test_Its_Just_So_Hard_reboot
1085
1086Its Just So Hard reboot test:
1087- adb shell reboot 'Its Just So Hard'
1088- (wait until screen is up, boot has completed)
1089- adb shell getprop sys.boot.reason
1090- NB: should report reboot,its_just_so_hard
1091- NB: expect log \"... I bootstat: Unknown boot reason: reboot,its_just_so_hard\"" ]
1092test_Its_Just_So_Hard_reboot() {
1093  if isDebuggable; then       # see below
1094    duration_test
1095  else
1096    duration_test `expr ${DURATION_DEFAULT} + ${DURATION_DEFAULT}`
1097  fi
1098  adb_sh 'reboot "Its Just So Hard"' </dev/null
1099  wait_for_screen
1100  EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard
1101  EXPECT_PROPERTY sys.boot.reason.last reboot,its_just_so_hard
1102  check_boilerplate_properties
1103  report_bootstat_logs reboot,its_just_so_hard
1104}
1105
1106[ "USAGE: run_bootloader [value [expected]]
1107
1108bootloader boot reason injection tests:
1109- setBootloaderBootReason value
1110- adb shell reboot
1111- (wait until screen is up, boot has completed)
1112- adb shell getprop sys.boot.reason
1113- NB: should report reboot,value" ]
1114run_bootloader() {
1115  bootloader_expected="${1}"
1116  if [ -z "${bootloader_expected}" ]; then
1117    bootloader_expected="${TEST#bootloader_}"
1118  fi
1119  if ! setBootloaderBootReason ${bootloader_expected}; then
1120    echo "       Skipping FAILURE." 2>&1
1121    return
1122  fi
1123  duration_test
1124  if [ X"warm" = X"${bootloader_expected}" ]; then
1125    last_expected=cold
1126  else
1127    last_expected=warm
1128  fi
1129  adb reboot ${last_expected}
1130  wait_for_screen
1131  # Reset so that other tests do not get unexpected injection
1132  setBootloaderBootReason
1133  # Determine the expected values
1134  sys_expected="${2}"
1135  if [ -z "${sys_expected}" ]; then
1136    sys_expected="`validate_reason ${bootloader_expected}`"
1137    if [ "reboot" = "${sys_expected}" ]; then
1138      sys_expected="${last_expected}"
1139    fi
1140  else
1141    sys_expected=`validate_reason ${sys_expected}`
1142  fi
1143  case ${sys_expected} in
1144    kernel_panic | kernel_panic,* | watchdog | watchdog,* )
1145      last_expected=${sys_expected}
1146      ;;
1147  esac
1148  # Check values
1149  EXPECT_PROPERTY ro.boot.bootreason "${bootloader_expected}"
1150  EXPECT_PROPERTY sys.boot.reason "${sys_expected}"
1151  EXPECT_PROPERTY sys.boot.reason.last "${last_expected}"
1152  check_boilerplate_properties
1153  report_bootstat_logs "${sys_expected}"
1154}
1155
1156[ "USAGE: test_bootloader_<type>
1157
1158bootloader boot reasons test injection" ]
1159test_bootloader_normal() {
1160  run_bootloader
1161}
1162
1163test_bootloader_watchdog() {
1164  run_bootloader
1165}
1166
1167test_bootloader_kernel_panic() {
1168  run_bootloader
1169}
1170
1171test_bootloader_oem_powerkey() {
1172  run_bootloader
1173}
1174
1175test_bootloader_wdog_reset() {
1176  run_bootloader
1177}
1178
1179test_bootloader_cold() {
1180  run_bootloader
1181}
1182
1183test_bootloader_warm() {
1184  run_bootloader
1185}
1186
1187test_bootloader_hard() {
1188  run_bootloader
1189}
1190
1191test_bootloader_recovery() {
1192  run_bootloader
1193}
1194
1195[ "USAGE: run_kBootReasonMap [--boot_reason_enum] value expected
1196
1197bootloader boot reason injection tests:
1198- if --boot_reason_enum run bootstat executable for result instead.
1199- inject boot reason into sys.boot.reason
1200- run bootstat --set_system_boot_reason
1201- check for expected enum
1202- " ]
1203run_kBootReasonMap() {
1204  if [ X"--boot_reason_enum" = X"${1}" ]; then
1205    shift
1206    local sys_expected="${1}"
1207    shift
1208    local enum_expected="${1}"
1209    adb_su bootstat --boot_reason_enum="${sys_expected}" |
1210      (
1211        local retval=-1
1212        while read -r id match; do
1213          if [ ${retval} = -1 -a ${enum_expected} = ${id} ]; then
1214            retval=0
1215          fi
1216          if [ ${enum_expected} != ${id} ]; then
1217            echo "ERROR: ${enum_expected} ${sys_expected} got ${id} ${match}" >&2
1218            retval=1
1219          fi
1220        done
1221        exit ${retval}
1222      )
1223    return
1224  fi
1225  local sys_expected="${1}"
1226  shift
1227  local enum_expected="${1}"
1228  adb_su setprop sys.boot.reason "${sys_expected}" </dev/null
1229  adb_su bootstat --record_boot_reason </dev/null
1230  # Check values
1231  EXPECT_PROPERTY sys.boot.reason "${sys_expected}"
1232  local retval=${?}
1233  local result=`adb_su stat -c %Y /data/misc/bootstat/system_boot_reason </dev/null 2>/dev/null`
1234  [ "${enum_expected}" = "${result}" ] ||
1235    (
1236      [ -n "${result}" ] || result="<nothing>"
1237      echo "ERROR: ${enum_expected} ${sys_expected} got ${result}" >&2
1238      false
1239    ) ||
1240    retval=${?}
1241  return ${retval}
1242}
1243
1244[ "USAGE: filter_kBootReasonMap </dev/stdin >/dev/stdout
1245
1246convert any regex expressions into a series of non-regex test strings" ]
1247filter_kBootReasonMap() {
1248  while read -r id match; do
1249    case ${match} in
1250      'reboot,[empty]')
1251        echo ${id}          # matches b/c of special case
1252        echo ${id} reboot,y # matches b/c of regex
1253        echo 1 reboot,empty # negative test (ID for unknown is 1)
1254        ;;
1255      reboot)
1256        echo 1 reboog       # negative test (ID for unknown is 1)
1257        ;;
1258      'reboot,pmic_off_fault,.*')
1259        echo ${id} reboot,pmic_off_fault,hello,world
1260        echo ${id} reboot,pmic_off_fault,
1261        echo 1 reboot,pmic_off_fault
1262        ;;
1263    esac
1264    echo ${id} "${match}"   # matches b/c of exact
1265  done
1266}
1267
1268[ "USAGE: test_kBootReasonMap
1269
1270kBootReasonMap test
1271- (wait until screen is up, boot has completed)
1272- read bootstat for kBootReasonMap entries and test them all" ]
1273test_kBootReasonMap() {
1274  checkDebugBuild || return
1275  duration_test 15
1276  local tempfile="`mktemp`"
1277  local arg=--boot_reason_enum
1278  adb_su bootstat ${arg} </dev/null 2>/dev/null |
1279    filter_kBootReasonMap >${tempfile}
1280  if [ ! -s "${tempfile}" ]; then
1281    wait_for_screen
1282    arg=
1283    sed -n <${progpath}bootstat.cpp \
1284      '/kBootReasonMap = {/,/^};/s/.*{"\([^"]*\)", *\([0-9][0-9]*\)},.*/\2 \1/p' |
1285      sed 's/\\\\/\\/g' |
1286      filter_kBootReasonMap >${tempfile}
1287  fi
1288  T=`adb_date`
1289  retval=0
1290  while read -r enum string; do
1291    if [ X"${string}" != X"${string#*[[].[]]}" -o X"${string}" != X"${string#*\\.}" ]; then
1292      if [ 'reboot\.empty' != "${string}" ]; then
1293        echo "WARNING: regex snuck through filter_kBootReasonMap ${enum} ${string}" >&2
1294        enum=1
1295      fi
1296    fi
1297    run_kBootReasonMap ${arg} "${string}" "${enum}" </dev/null || retval=${?}
1298  done <${tempfile}
1299  rm ${tempfile}
1300  ( exit ${retval} )
1301  # See filter_kBootReasonMap() for negative tests and add them here too
1302  report_bootstat_logs -t${T} \
1303    '-bootstat: Service started: bootstat --boot_reason_enum=' \
1304    '-bootstat: Unknown boot reason: reboot,empty' \
1305    '-bootstat: Unknown boot reason: reboog' \
1306    '-bootstat: Unknown boot reason: reboot,pmic_off_fault'
1307}
1308
1309[ "USAGE: ${progname} [-s SERIAL] [tests]...
1310
1311Mainline executive to run the above tests" ]
1312
1313# Rudimentary argument parsing
1314
1315if [ ${#} -ge 2 -a X"-s" = X"${1}" ]; then
1316  export ANDROID_SERIAL="${2}"
1317  shift 2
1318fi
1319
1320# Helpful for debugging, allows us to import the functions.
1321if [ X"--macros" != X"${1}" ]; then
1322
1323  if [ X"--help" = X"${1}" -o X"-h" = X"${1}" -o X"-?" = X"${1}" ]; then
1324    echo "USAGE: ${progname} [-s SERIAL] [tests]..."
1325    echo tests - `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null`
1326    exit 0
1327  fi
1328
1329  if [ X"--stop" = X"${1}" ]; then
1330    STOP_ON_FAILURE=true
1331    shift
1332  fi
1333
1334  # Check if all conditions for the script are valid
1335
1336  if [ -z "${ANDROID_SERIAL}" ]; then
1337    ndev=`(
1338        adb devices | grep -v 'List of devices attached'
1339        fastboot devices
1340      ) |
1341      grep -v "^[${SPACE}${TAB}]*\$" |
1342      wc -l`
1343    if [ ${ndev} -gt 1 ]; then
1344      echo "ERROR: no target device specified, ${ndev} connected" >&2
1345      echo "${RED}[  FAILED  ]${NORMAL}"
1346      exit 1
1347    fi
1348    echo "WARNING: no target device specified" >&2
1349  fi
1350
1351  ret=0
1352
1353  # Test Series
1354  if [ X"all" = X"${*}" ]; then
1355    # automagically pick up all test_<function>s.
1356    eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null`
1357    if [ X"nothing" = X"${1}" ]; then
1358      shift 1
1359    fi
1360  fi
1361  if [ -z "$*" ]; then
1362    # automagically pick up all test_<function>, except test_optional_<function>.
1363    eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null |
1364                              grep -v '^optional_'`
1365    if [ -z "${2}" ]; then
1366      # Hard coded should shell fail to find them (search/permission issues)
1367      eval set properties ota cold factory_reset hard battery unknown \
1368               kernel_panic kernel_panic_subreason kernel_panic_hung warm \
1369               thermal_shutdown userrequested_shutdown shell_reboot adb_reboot \
1370               Its_Just_So_Hard_reboot bootloader_normal bootloader_watchdog \
1371               bootloader_kernel_panic bootloader_oem_powerkey \
1372               bootloader_wdog_reset bootloader_cold bootloader_warm \
1373               bootloader_hard bootloader_recovery kBootReasonMap
1374    fi
1375    if [ X"nothing" = X"${1}" ]; then
1376      shift 1
1377    fi
1378  fi
1379  echo "INFO: selected test(s): ${@}" >&2
1380  echo
1381  # Prepare device
1382  setBootloaderBootReason 2>/dev/null
1383  # Start pouring through the tests.
1384  failures=
1385  successes=
1386  for t in "${@}"; do
1387    wrap_test ${t}
1388    retval=${?}
1389    if [ 0 = ${retval} ]; then
1390      if [ -z "${successes}" ]; then
1391        successes=${t}
1392      else
1393        successes="${successes} ${t}"
1394      fi
1395    else
1396      ret=${retval}
1397      if [ -z "${failures}" ]; then
1398        failures=${t}
1399      else
1400        failures="${failures} ${t}"
1401      fi
1402    fi
1403    echo
1404  done
1405
1406  if [ -n "${successes}" ]; then
1407    echo "${GREEN}[  PASSED  ]${NORMAL} ${successes}"
1408  fi
1409  if [ -n "${failures}" ]; then
1410    echo "${RED}[  FAILED  ]${NORMAL} ${failures}"
1411  fi
1412  exit ${ret}
1413
1414fi
1415