1#!/bin/bash
2#
3# Copyright 2010 Google Inc. All Rights Reserved.
4# Author: bgay@google.com (Bruce Gay)
5#
6# The labpretest.sh script is designed to emulate a typical automated test lab
7# session.  It puts a device into bootloader mode, reboots into bootloader mode,
8# determines device type, erases user cache, flashes a generic userdata image,
9# updates the bootloader image, updates the radio image, updates the system
10# image and reboots, sets up for a monkey run and finally runs a random monkey
11# test. It will repeat this based on an optional parameter(-i) or default to 100
12# times. It will detect if it is in a low battery situation and wait for it to
13# charge again.
14
15
16COUNT=100
17ROOT=$(cd `dirname $0` && pwd)
18ADB="$ROOT/tools/adb"
19FASTBOOT="$ROOT/tools/fastboot"
20MEVENTS=200
21NOMONKEY=0
22
23buildfile=''
24device=''
25product=''
26bootpart=''
27bootfile=''
28
29while getopts "d:i::m:xh" optionName; do
30  case "$optionName" in
31    d) device="$OPTARG";;
32    i) COUNT=$OPTARG;;
33    m) MEVENTS=$OPTARG;;
34    x) NOMONKEY=1;;
35    h) echo "options: [-d <device ID>, -i <loop count>, -m <monkey events> -x (skips monkey)]"; exit;;
36    *) echo "invalid parameter -$optionName"; exit -1;;
37  esac
38done
39
40declare -r COUNT
41declare -r MEVENTS
42declare -r NOMONKEY
43
44
45################################################
46# Prints output to console with time stamp
47# Arguments:
48#   None
49# Returns:
50#   None
51################################################
52log_print()
53{
54  if [ -z "$1" ]; then
55    echo "# $(date +'%D %T')"
56  else
57    echo "# $(date +'%D %T'): $1"
58  fi
59}
60
61################################################
62# Blocks until battery level is at least
63# above TARGET if below LIMIT
64# Globals:
65#   ADB
66#   device
67# Arguments:
68#   None
69# Returns:
70#   None
71################################################
72wait_for_battery()
73{
74  TARGET=80
75  LIMIT=20
76  local battery
77  local tick
78  log_print "checking battery level"
79  while [ "$battery" = "" ]; do
80    battery=`$ADB -s $device shell dumpsys battery | tr -d '\r' | awk '/level:/ {print $2}'`
81    sleep 2
82  done
83  if [ $battery -lt $LIMIT ]; then
84    log_print "Battery is low, waiting for charge"
85    while true; do
86      battery=`$ADB -s $device shell dumpsys battery | tr -d '\r' | awk '/level:/ {print $2}'`
87      if (( $battery >= $TARGET )); then break; fi
88      tick=$[$TARGET - $battery]
89      echo "battery charge level is $battery, sleeping for $tick seconds"
90      sleep $[$TARGET - $battery * 10]
91    done
92    log_print "resuming test run with battery level at $battery%"
93  else
94    log_print "resuming test run with battery level at $battery%"
95  fi
96}
97
98################################################
99# Blocks until device is in fastboot mode or
100# time out is reached
101# Globals:
102#   loop
103#   device
104# Arguments:
105#   None
106# Returns:
107#   None
108################################################
109fastboot_wait_for_device()
110{
111  local fdevice=""
112  local n=0
113  while [ "$device" != "$fdevice" -a $n -le 30 ]; do
114    sleep 6
115    fdevice=`$FASTBOOT devices | sed -n "s/\($device\).*/\1/ p"`
116    let n+=1
117  done
118  if [ $n -gt 30 ]; then
119    log_print "device time out after $loop iterations"
120    exit
121  else
122    log_print "device returned and available"
123  fi
124}
125
126################################################
127# reboots device into fastboot mode or
128# time out is reached
129# Globals:
130#   device
131#   ADB
132# Arguments:
133#   None
134# Returns:
135#   None
136################################################
137reboot_into_fastboot_from_adb()
138{
139  log_print "rebooting into bootloader and waiting for availability via fastboot"
140  $ADB -s $device reboot bootloader
141  fastboot_wait_for_device
142}
143
144################################################
145# reboots device into fastboot mode or
146# times out
147# Globals:
148#   device
149#   FASTBOOT
150# Arguments:
151#   None
152# Returns:
153#   None
154################################################
155reboot_into_fastboot_from_fastboot()
156{
157  log_print "rebooting into bootloader and waiting for availability via fastboot"
158  $FASTBOOT -s $device reboot-bootloader
159  fastboot_wait_for_device
160}
161
162################################################
163# reboots device from fastboot to adb or
164# times out
165# Globals:
166#   device
167#   FASTBOOT
168#   ADB
169# Arguments:
170#   None
171# Returns:
172#   None
173################################################
174reboot_into_adb_from_fastboot()
175{
176  log_print "rebooting and waiting for availability via adb"
177  $FASTBOOT -s $device reboot
178  $ADB -s $device wait-for-device
179}
180
181################################################
182# reboots device from fastboot to adb or
183# times out
184# Globals:
185#   device
186#   ADB
187# Arguments:
188#   None
189# Returns:
190#   None
191################################################
192wait_for_boot_complete()
193{
194  log_print "waiting for device to finish booting"
195  local result=$($ADB -s $device shell getprop dev.bootcomplete)
196  local result_test=${result:1:1}
197  echo -n "."
198  while [ -z $result_test ]; do
199    sleep 1
200    echo -n "."
201    result=$($ADB -s $device shell getprop dev.bootcomplete)
202    result_test=${result:0:1}
203  done
204  log_print "finished booting"
205}
206
207################################################
208# fastboot flashes partition
209#
210# Globals:
211#   device
212#   FASTBOOT
213# Arguments:
214#   command_name
215#   command_parameters
216# Returns:
217#   None
218################################################
219fastboot_command()
220{
221  $FASTBOOT -s $device $1 $2 $3
222  sleep 5
223}
224
225################################################
226# fastboot command wrapper
227#
228# Globals:
229#   device
230#   FASTBOOT
231# Arguments:
232#   partition_name
233#   file_name
234# Returns:
235#   None
236################################################
237flash_partition()
238{
239  $FASTBOOT -s $device flash $1 $2
240  sleep 5
241}
242
243################################################
244# adb command wrapper
245#
246# Globals:
247#   device
248#   ADB
249# Arguments:
250#   command_name
251#   command_parameters
252# Returns:
253#   None
254################################################
255adb_command()
256{
257  $ADB -s $device $1 $2 $3 $4 $5
258  sleep 5
259}
260
261################################################
262# sets the name of the boot partition and
263# bootfile, then flashes device
264#
265# Globals:
266#   product
267#   ROOT
268#   bootloaderfile
269#   bootpart
270#   device
271# Arguments:
272#   None
273# Returns:
274#   None
275################################################
276flash_bootloader_image()
277{
278  if [ "$bootpart" == '' ]; then
279    log_print "bootpart not defined"
280    exit
281  fi
282  if [ "$bootloaderfile" == '' ]; then
283    log_print "getting bootloader file for $product"
284    bootloaderfile=`ls -1 $ROOT/$product | sed -n 's/\(.*boot[0-9._]\+img\)/\1/ p'`
285    if [ "$bootloaderfile" == '' ]; then
286      log_print "bootloader file empty: $bootloaderfile"
287      exit
288    fi
289    if [ ! -e "$ROOT/$product/$bootloaderfile" ]; then
290      log_print "bootloader file not found: ./$product/$bootloaderfile"
291      exit
292    fi
293    log_print "using $ROOT/$product/$bootloaderfile as the bootloader image file"
294  fi
295  log_print "downloading bootloader image to $device"
296  flash_partition $bootpart $ROOT/$product/$bootloaderfile
297  reboot_into_fastboot_from_fastboot
298}
299
300################################################
301# sets the name of the radio partition and
302# radiofile and flashes device
303#
304# Globals:
305#   product
306#   ROOT
307#   radiofile
308#   radiopart
309#   device
310# Arguments:
311#   None
312# Returns:
313#   None
314################################################
315flash_radio_image()
316{
317  if [ "$radiopart" == '' ]; then
318    log_print "setting radio partion to 'radio'"
319    radiopart='radio'
320  fi
321  if [ "$radiofile" == "" ]; then
322    log_print "getting radio file for $product"
323    radiofile=`ls -1 $ROOT/$product | sed -n 's/\(radio[0-9._A-Za-z]\+img\)/\1/ p'`
324    if [ "$radiofile" == "" ]; then
325      log_print "radio file empty: $radiofile"
326      exit
327    fi
328    if [ ! -e "$ROOT/$product/$radiofile" ]; then
329      log_print "radio file not found: ./$product/$radiofile"
330      exit
331    fi
332    log_print "using $ROOT/$product/$radiofile as the radio image file"
333  fi
334  log_print "downloading radio image to $device"
335  flash_partition $radiopart  $ROOT/$product/$radiofile
336  reboot_into_fastboot_from_fastboot
337}
338
339################################################
340# sets the name of the boot partition and
341# bootfile
342#
343# Globals:
344#   product
345#   ROOT
346#   buildfile
347#   device
348# Arguments:
349#   None
350# Returns:
351#   None
352################################################
353flash_system_image()
354{
355  if [ "$buildfile" == "" ]; then
356    log_print "getting build file for $product"
357    buildfile=`\ls -1 $ROOT/$product 2>&1 | sed -n 's/\([a-z]\+-img-[0-9]\+.zip\)/\1/ p'`
358    if [ "$buildfile" == "" ]; then
359      log_print "build file empty: $buildfile"
360      exit
361    fi
362    if [ ! -e "$ROOT/$product/$buildfile" ]; then
363      log_print "build file not found: ./$product/$buildfile"
364      exit
365    fi
366    log_print "using $ROOT/$product/$buildfile as the system image file"
367  fi
368  log_print "downloading system image to $device"
369  fastboot_command update $ROOT/$product/$buildfile
370
371}
372################################################
373# flashes the userdata partition
374#
375# Globals:
376#   product
377#   ROOT
378# Arguments:
379#   None
380# Returns:
381#   None
382################################################
383flash_userdata_image()
384{
385  log_print "flashing userdata..."
386  if [ -e $ROOT/$product/userdata.img ];then
387    flash_partition userdata $ROOT/$product/userdata.img
388  else
389    log_print "userdata.img file not found: $ROOT/$product/userdata.img"
390    exit
391  fi
392}
393
394
395################################################
396# flashes the device
397#
398# Globals:
399#   product
400#   ROOT
401#   FASTBOOT
402#   bootfile
403#   bootpart
404#   radiofile
405# Arguments:
406#   None
407# Returns:
408#   None
409################################################
410flash_device()
411{
412  log_print "erasing cache..."
413  fastboot_command erase cache
414  flash_userdata_image
415  flash_bootloader_image
416  flash_radio_image
417  flash_system_image
418  #device has been rebooted
419  adb_command wait-for-device
420}
421
422################################################
423# gets the device product type and sets product
424#
425# Globals:
426#   product
427#   ROOT
428#   FASTBOOT
429#   device
430# Arguments:
431#   None
432# Returns:
433#   None
434################################################
435set_product_type()
436{
437  if [ "$product" == "" ]; then
438    log_print "getting device product type"
439    product=`$FASTBOOT -s $device getvar product 2>&1 | sed -n 's/product: \([a-z]*\)\n*/\1/ p'`
440    if [ ! -e "$ROOT/$product" ]; then
441      log_print "device product id not supported: $product"
442      exit
443    fi
444  fi
445  log_print "using $product as device product id"
446}
447
448
449
450#start of script
451#test for dependencies
452if [ ! -e $ADB ]; then
453  echo "Error: adb not in path! Please correct this."
454  exit
455fi
456if [ ! -e $FASTBOOT ]; then
457  echo "Error: fastboot not in path! Please correct this."
458  exit
459fi
460#checks to see if the called device is available
461if [ "$device" != "" ]; then
462  tmpdevice=`$ADB devices | sed -n "s/\($device\).*/\1/ p"`
463  if [ "$device" != "$tmpdevice" ]; then
464      tmpdevice=`$FASTBOOT devices | sed -n "s/\($device\).*/\1/ p"`
465    if [ "$device" != "$tmpdevice" ]; then
466      echo "Warning: device not found... $device"
467      exit
468    else
469      echo "'Device '$device' found!'"
470      reboot_into_adb_from_fastboot
471      wait_for_boot_complete
472    fi
473  fi
474else
475  device=`$ADB devices | sed -n 's/.*\(^[0-9A-Z]\{2\}[0-9A-Z]*\).*/\1/ p'`
476  if [ `echo $device | wc -w` -ne 1 ]; then
477    echo 'There is more than one device found,'
478    echo 'please pass the correct device ID in as a parameter.'
479    exit
480  fi
481fi
482if [ "$device" == "" ]; then
483  echo 'Device not found via adb'
484  device=`$FASTBOOT devices | sed -n 's/.*\(^[0-9A-Z]\{2\}[0-9A-Z]*\).*/\1/ p'`
485  if [ `echo $device | wc -w` -ne 1 ]; then
486    echo "There is more than one device available,"
487    echo "please pass the correct device ID in as a parameter."
488    exit
489  fi
490  if [ "$device" == "" ]; then
491    echo 'Device not found via fastboot, please investigate'
492    exit
493  else
494    echo 'Device '$device' found!'
495    reboot_into_adb_from_fastboot
496    wait_for_boot_complete
497    echo 'Hammering on '$device
498  fi
499else
500  echo 'Hammering on '$device
501fi
502reboot_into_fastboot_from_adb
503set_product_type
504reboot_into_adb_from_fastboot
505wait_for_boot_complete
506
507#check for availability of a custom flash info file and retreive it
508if [ -e "$ROOT/$product/custom_flash.sh" ]; then
509  . $ROOT/$product/custom_flash.sh
510fi
511echo $'\n\n'
512
513#start of looping
514for ((loop=1 ; loop <= $COUNT ; loop++ )) ; do
515  echo ""
516  echo ""
517  echo ________________ $(date +'%D %T') - $loop - $device ______________________
518
519  log_print "setting adb root and sleeping for 7 seconds"
520  adb_command root
521  wait_for_battery
522  log_print "rebooting into bootloader and waiting for availability via fastboot"
523  reboot_into_fastboot_from_adb
524  # not necessary, but useful in testing
525  log_print "using fastboot to reboot to bootloader for test purposes"
526  reboot_into_fastboot_from_fastboot
527
528  #flashing the device
529  flash_device
530
531  #preping device for monkey run
532  log_print "setting adb root"
533  adb_command root
534  log_print "setting ro.test_harness property"
535  adb_command shell setprop ro.test_harness 1
536
537  log_print "waiting for device to finish booting"
538  result=$($ADB -s $device shell getprop dev.bootcomplete)
539  result_test=${result:1:1}
540  echo -n "."
541  while [ -z $result_test ]; do
542    sleep 1
543    echo -n "."
544    result=$($ADB -s $device shell getprop dev.bootcomplete)
545    result_test=${result:0:1}
546  done
547
548  log_print "finished booting"
549  log_print "waiting for the Package Manager"
550  result=$($ADB -s $device shell pm path android)
551  result_test=${result:0:7}
552  echo -n "."
553  while [ $result_test != "package" ]; do
554    sleep 1
555    echo -n "."
556    result=$($ADB -s $device shell pm path android)
557    result_test=${result:0:7}
558  done
559  echo "Package Manager available"
560
561  #lets you see what's going on
562  log_print "setting shell svc power stayon true"
563  adb_command shell svc power stayon true
564
565  #calls the monkey run if not skipped
566  if [ $NOMONKEY == 0 ]; then
567    seed=$(($(date +%s) % 99))
568    log_print "running short monkey run..."
569    $ADB -s $device shell monkey -p com.android.alarmclock -p com.android.browser -p com.android.calculator2 -p com.android.calendar -p com.android.camera -p com.android.contacts -p com.google.android.gm -p com.android.im -p com.android.launcher -p com.google.android.apps.maps -p com.android.mms -p com.android.music -p com.android.phone -p com.android.settings -p com.google.android.street -p com.android.vending -p com.google.android.youtube -p com.android.email -p com.google.android.voicesearch  -c android.intent.category.LAUNCHER  --ignore-security-exceptions  -s $seed $MEVENTS
570    log_print "finished running monkey, rinse, repeat..."
571  else
572    log_print "-x parameter used, skipping the monkey run"
573  fi
574
575  if [ $loop -eq $COUNT ]; then
576    log_print "device $device has returned, testing completed, count = $loop"
577    echo `echo "Device $device has returned, testing completed, count = $loop." > $ROOT/$device.log`
578  else
579    log_print "device $device has returned, rinse and repeat count = $loop"
580    echo `echo "Device $device has returned, rinse and repeat count = $loop." > $ROOT/$device.log`
581  fi
582done
583