#!/bin/bash
#
# Copyright 2010 Google Inc. All Rights Reserved.
# Author: bgay@google.com (Bruce Gay)
#
# The labpretest.sh script is designed to emulate a typical automated test lab
# session. It puts a device into bootloader mode, reboots into bootloader mode,
# determines device type, erases user cache, flashes a generic userdata image,
# updates the bootloader image, updates the radio image, updates the system
# image and reboots, sets up for a monkey run and finally runs a random monkey
# test. It will repeat this based on an optional parameter(-i) or default to 100
# times. It will detect if it is in a low battery situation and wait for it to
# charge again.
COUNT=100
ROOT=$(cd `dirname $0` && pwd)
ADB="$ROOT/tools/adb"
FASTBOOT="$ROOT/tools/fastboot"
MEVENTS=200
NOMONKEY=0
buildfile=''
device=''
product=''
bootpart=''
bootfile=''
while getopts "d:i::m:xh" optionName; do
case "$optionName" in
d) device="$OPTARG";;
i) COUNT=$OPTARG;;
m) MEVENTS=$OPTARG;;
x) NOMONKEY=1;;
h) echo "options: [-d <device ID>, -i <loop count>, -m <monkey events> -x (skips monkey)]"; exit;;
*) echo "invalid parameter -$optionName"; exit -1;;
esac
done
declare -r COUNT
declare -r MEVENTS
declare -r NOMONKEY
################################################
# Prints output to console with time stamp
# Arguments:
# None
# Returns:
# None
################################################
log_print()
{
if [ -z "$1" ]; then
echo "# $(date +'%D %T')"
else
echo "# $(date +'%D %T'): $1"
fi
}
################################################
# Blocks until battery level is at least
# above TARGET if below LIMIT
# Globals:
# ADB
# device
# Arguments:
# None
# Returns:
# None
################################################
wait_for_battery()
{
TARGET=80
LIMIT=20
local battery
local tick
log_print "checking battery level"
while [ "$battery" = "" ]; do
battery=`$ADB -s $device shell dumpsys battery | tr -d '\r' | awk '/level:/ {print $2}'`
sleep 2
done
if [ $battery -lt $LIMIT ]; then
log_print "Battery is low, waiting for charge"
while true; do
battery=`$ADB -s $device shell dumpsys battery | tr -d '\r' | awk '/level:/ {print $2}'`
if (( $battery >= $TARGET )); then break; fi
tick=$[$TARGET - $battery]
echo "battery charge level is $battery, sleeping for $tick seconds"
sleep $[$TARGET - $battery * 10]
done
log_print "resuming test run with battery level at $battery%"
else
log_print "resuming test run with battery level at $battery%"
fi
}
################################################
# Blocks until device is in fastboot mode or
# time out is reached
# Globals:
# loop
# device
# Arguments:
# None
# Returns:
# None
################################################
fastboot_wait_for_device()
{
local fdevice=""
local n=0
while [ "$device" != "$fdevice" -a $n -le 30 ]; do
sleep 6
fdevice=`$FASTBOOT devices | sed -n "s/\($device\).*/\1/ p"`
let n+=1
done
if [ $n -gt 30 ]; then
log_print "device time out after $loop iterations"
exit
else
log_print "device returned and available"
fi
}
################################################
# reboots device into fastboot mode or
# time out is reached
# Globals:
# device
# ADB
# Arguments:
# None
# Returns:
# None
################################################
reboot_into_fastboot_from_adb()
{
log_print "rebooting into bootloader and waiting for availability via fastboot"
$ADB -s $device reboot bootloader
fastboot_wait_for_device
}
################################################
# reboots device into fastboot mode or
# times out
# Globals:
# device
# FASTBOOT
# Arguments:
# None
# Returns:
# None
################################################
reboot_into_fastboot_from_fastboot()
{
log_print "rebooting into bootloader and waiting for availability via fastboot"
$FASTBOOT -s $device reboot-bootloader
fastboot_wait_for_device
}
################################################
# reboots device from fastboot to adb or
# times out
# Globals:
# device
# FASTBOOT
# ADB
# Arguments:
# None
# Returns:
# None
################################################
reboot_into_adb_from_fastboot()
{
log_print "rebooting and waiting for availability via adb"
$FASTBOOT -s $device reboot
$ADB -s $device wait-for-device
}
################################################
# reboots device from fastboot to adb or
# times out
# Globals:
# device
# ADB
# Arguments:
# None
# Returns:
# None
################################################
wait_for_boot_complete()
{
log_print "waiting for device to finish booting"
local result=$($ADB -s $device shell getprop dev.bootcomplete)
local result_test=${result:1:1}
echo -n "."
while [ -z $result_test ]; do
sleep 1
echo -n "."
result=$($ADB -s $device shell getprop dev.bootcomplete)
result_test=${result:0:1}
done
log_print "finished booting"
}
################################################
# fastboot flashes partition
#
# Globals:
# device
# FASTBOOT
# Arguments:
# command_name
# command_parameters
# Returns:
# None
################################################
fastboot_command()
{
$FASTBOOT -s $device $1 $2 $3
sleep 5
}
################################################
# fastboot command wrapper
#
# Globals:
# device
# FASTBOOT
# Arguments:
# partition_name
# file_name
# Returns:
# None
################################################
flash_partition()
{
$FASTBOOT -s $device flash $1 $2
sleep 5
}
################################################
# adb command wrapper
#
# Globals:
# device
# ADB
# Arguments:
# command_name
# command_parameters
# Returns:
# None
################################################
adb_command()
{
$ADB -s $device $1 $2 $3 $4 $5
sleep 5
}
################################################
# sets the name of the boot partition and
# bootfile, then flashes device
#
# Globals:
# product
# ROOT
# bootloaderfile
# bootpart
# device
# Arguments:
# None
# Returns:
# None
################################################
flash_bootloader_image()
{
if [ "$bootpart" == '' ]; then
log_print "bootpart not defined"
exit
fi
if [ "$bootloaderfile" == '' ]; then
log_print "getting bootloader file for $product"
bootloaderfile=`ls -1 $ROOT/$product | sed -n 's/\(.*boot[0-9._]\+img\)/\1/ p'`
if [ "$bootloaderfile" == '' ]; then
log_print "bootloader file empty: $bootloaderfile"
exit
fi
if [ ! -e "$ROOT/$product/$bootloaderfile" ]; then
log_print "bootloader file not found: ./$product/$bootloaderfile"
exit
fi
log_print "using $ROOT/$product/$bootloaderfile as the bootloader image file"
fi
log_print "downloading bootloader image to $device"
flash_partition $bootpart $ROOT/$product/$bootloaderfile
reboot_into_fastboot_from_fastboot
}
################################################
# sets the name of the radio partition and
# radiofile and flashes device
#
# Globals:
# product
# ROOT
# radiofile
# radiopart
# device
# Arguments:
# None
# Returns:
# None
################################################
flash_radio_image()
{
if [ "$radiopart" == '' ]; then
log_print "setting radio partion to 'radio'"
radiopart='radio'
fi
if [ "$radiofile" == "" ]; then
log_print "getting radio file for $product"
radiofile=`ls -1 $ROOT/$product | sed -n 's/\(radio[0-9._A-Za-z]\+img\)/\1/ p'`
if [ "$radiofile" == "" ]; then
log_print "radio file empty: $radiofile"
exit
fi
if [ ! -e "$ROOT/$product/$radiofile" ]; then
log_print "radio file not found: ./$product/$radiofile"
exit
fi
log_print "using $ROOT/$product/$radiofile as the radio image file"
fi
log_print "downloading radio image to $device"
flash_partition $radiopart $ROOT/$product/$radiofile
reboot_into_fastboot_from_fastboot
}
################################################
# sets the name of the boot partition and
# bootfile
#
# Globals:
# product
# ROOT
# buildfile
# device
# Arguments:
# None
# Returns:
# None
################################################
flash_system_image()
{
if [ "$buildfile" == "" ]; then
log_print "getting build file for $product"
buildfile=`\ls -1 $ROOT/$product 2>&1 | sed -n 's/\([a-z]\+-img-[0-9]\+.zip\)/\1/ p'`
if [ "$buildfile" == "" ]; then
log_print "build file empty: $buildfile"
exit
fi
if [ ! -e "$ROOT/$product/$buildfile" ]; then
log_print "build file not found: ./$product/$buildfile"
exit
fi
log_print "using $ROOT/$product/$buildfile as the system image file"
fi
log_print "downloading system image to $device"
fastboot_command update $ROOT/$product/$buildfile
}
################################################
# flashes the userdata partition
#
# Globals:
# product
# ROOT
# Arguments:
# None
# Returns:
# None
################################################
flash_userdata_image()
{
log_print "flashing userdata..."
if [ -e $ROOT/$product/userdata.img ];then
flash_partition userdata $ROOT/$product/userdata.img
else
log_print "userdata.img file not found: $ROOT/$product/userdata.img"
exit
fi
}
################################################
# flashes the device
#
# Globals:
# product
# ROOT
# FASTBOOT
# bootfile
# bootpart
# radiofile
# Arguments:
# None
# Returns:
# None
################################################
flash_device()
{
log_print "erasing cache..."
fastboot_command erase cache
flash_userdata_image
flash_bootloader_image
flash_radio_image
flash_system_image
#device has been rebooted
adb_command wait-for-device
}
################################################
# gets the device product type and sets product
#
# Globals:
# product
# ROOT
# FASTBOOT
# device
# Arguments:
# None
# Returns:
# None
################################################
set_product_type()
{
if [ "$product" == "" ]; then
log_print "getting device product type"
product=`$FASTBOOT -s $device getvar product 2>&1 | sed -n 's/product: \([a-z]*\)\n*/\1/ p'`
if [ ! -e "$ROOT/$product" ]; then
log_print "device product id not supported: $product"
exit
fi
fi
log_print "using $product as device product id"
}
#start of script
#test for dependencies
if [ ! -e $ADB ]; then
echo "Error: adb not in path! Please correct this."
exit
fi
if [ ! -e $FASTBOOT ]; then
echo "Error: fastboot not in path! Please correct this."
exit
fi
#checks to see if the called device is available
if [ "$device" != "" ]; then
tmpdevice=`$ADB devices | sed -n "s/\($device\).*/\1/ p"`
if [ "$device" != "$tmpdevice" ]; then
tmpdevice=`$FASTBOOT devices | sed -n "s/\($device\).*/\1/ p"`
if [ "$device" != "$tmpdevice" ]; then
echo "Warning: device not found... $device"
exit
else
echo "'Device '$device' found!'"
reboot_into_adb_from_fastboot
wait_for_boot_complete
fi
fi
else
device=`$ADB devices | sed -n 's/.*\(^[0-9A-Z]\{2\}[0-9A-Z]*\).*/\1/ p'`
if [ `echo $device | wc -w` -ne 1 ]; then
echo 'There is more than one device found,'
echo 'please pass the correct device ID in as a parameter.'
exit
fi
fi
if [ "$device" == "" ]; then
echo 'Device not found via adb'
device=`$FASTBOOT devices | sed -n 's/.*\(^[0-9A-Z]\{2\}[0-9A-Z]*\).*/\1/ p'`
if [ `echo $device | wc -w` -ne 1 ]; then
echo "There is more than one device available,"
echo "please pass the correct device ID in as a parameter."
exit
fi
if [ "$device" == "" ]; then
echo 'Device not found via fastboot, please investigate'
exit
else
echo 'Device '$device' found!'
reboot_into_adb_from_fastboot
wait_for_boot_complete
echo 'Hammering on '$device
fi
else
echo 'Hammering on '$device
fi
reboot_into_fastboot_from_adb
set_product_type
reboot_into_adb_from_fastboot
wait_for_boot_complete
#check for availability of a custom flash info file and retreive it
if [ -e "$ROOT/$product/custom_flash.sh" ]; then
. $ROOT/$product/custom_flash.sh
fi
echo $'\n\n'
#start of looping
for ((loop=1 ; loop <= $COUNT ; loop++ )) ; do
echo ""
echo ""
echo ________________ $(date +'%D %T') - $loop - $device ______________________
log_print "setting adb root and sleeping for 7 seconds"
adb_command root
wait_for_battery
log_print "rebooting into bootloader and waiting for availability via fastboot"
reboot_into_fastboot_from_adb
# not necessary, but useful in testing
log_print "using fastboot to reboot to bootloader for test purposes"
reboot_into_fastboot_from_fastboot
#flashing the device
flash_device
#preping device for monkey run
log_print "setting adb root"
adb_command root
log_print "setting ro.test_harness property"
adb_command shell setprop ro.test_harness 1
log_print "waiting for device to finish booting"
result=$($ADB -s $device shell getprop dev.bootcomplete)
result_test=${result:1:1}
echo -n "."
while [ -z $result_test ]; do
sleep 1
echo -n "."
result=$($ADB -s $device shell getprop dev.bootcomplete)
result_test=${result:0:1}
done
log_print "finished booting"
log_print "waiting for the Package Manager"
result=$($ADB -s $device shell pm path android)
result_test=${result:0:7}
echo -n "."
while [ $result_test != "package" ]; do
sleep 1
echo -n "."
result=$($ADB -s $device shell pm path android)
result_test=${result:0:7}
done
echo "Package Manager available"
#lets you see what's going on
log_print "setting shell svc power stayon true"
adb_command shell svc power stayon true
#calls the monkey run if not skipped
if [ $NOMONKEY == 0 ]; then
seed=$(($(date +%s) % 99))
log_print "running short monkey run..."
$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
log_print "finished running monkey, rinse, repeat..."
else
log_print "-x parameter used, skipping the monkey run"
fi
if [ $loop -eq $COUNT ]; then
log_print "device $device has returned, testing completed, count = $loop"
echo `echo "Device $device has returned, testing completed, count = $loop." > $ROOT/$device.log`
else
log_print "device $device has returned, rinse and repeat count = $loop"
echo `echo "Device $device has returned, rinse and repeat count = $loop." > $ROOT/$device.log`
fi
done