Skip to content

Instantly share code, notes, and snippets.

@stackedsax
Created May 8, 2012 21:42
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save stackedsax/2639601 to your computer and use it in GitHub Desktop.
Save stackedsax/2639601 to your computer and use it in GitHub Desktop.
Script for starting up multiple android emulators per box
#!/bin/bash
#####
#
# This script creates android emulators on the fly.
#
# Please refer to the README for usage instructions.
#
####
# Set-up ANDROID_SDK_HOME
# this creates all the AVD's and the emulator will look for them in the same location
if [ "x${avd_dir}" != "x" ]; then
export ANDROID_SDK_HOME="${avd_dir}"
else
export ANDROID_SDK_HOME="/var/yandroid_sdk/avd_dir"
fi
# set the directory to find the current webdriver apk
## I downlaod the apk separately and keep it somewhere special
if [ "x${selenium_grid_android_server__apk_dir}" != "x" ]; then
APK_DIR="${apk_dir}"
else
APK_DIR="/usr/lib/selenium_grid_android_server"
fi
# grab some variables
## emulator_count
if [ "x${emulator_count}" != "x" ]; then
EMULATOR_COUNT="${emulator_count}"
else
EMULATOR_COUNT="1"
fi
## android_target
if [ "x${android_target}" != "x" ]; then
ANDROID_TARGET="${android_target}"
else
ANDROID_TARGET="anrdoid-15"
fi
## android_target
if [ "x${android_abi}" != "x" ]; then
ANDROID_ABI="${android_abi}"
else
ANDROID_ABI="x86"
fi
## sdcard_size
if [ "x${sdcard_size}" != "x" ]; then
SDCARD="${sdcard_size}"
else
SDCARD="60M"
fi
## port number to start searching for free ports for the console
if [ "x${console_port_start}" != "x" ]; then
console_port="${console_port_start}"
else
console_port="5554"
fi
## port number to start searching for free ports for the listener
if [ "x${listener_port_start}" != "x" ]; then
listener_port="${listener_port_start}"
else
listener_port="8000"
fi
## port number to start searching for free ports for socat
if [ "x${socat_port_start}" != "x" ]; then
socat_port="${socat_port_start}"
else
socat_port="9000"
fi
## set the hub_host
if [ "x${hub_host}" != "x" ]; then
HUB_HOST="${hub_host}"
else
HUB_HOST="localhost"
fi
## set the hub_port
if [ "x${hub_port}" != "x" ]; then
HUB_PORT="${hub_port}"
else
HUB_PORT="4444"
fi
## set the local ip
LOCAL_IP=`hostname -i`
# Funtions
# Create an array of free port numbers to use for the emulators
# Yes, this looks unnecessarily complex, but CONSOLE_PORT needs to
# be an even integer and can only be within a range of 5554-5584.
function findFreePorts {
k=0
for (( i=0 ; i < $EMULATOR_COUNT; i++ ))
{
while netstat -atwn | grep "^.*{console_port}.*:\*\s*LISTEN\s*$"
do
#Console Port should and can only be an even number
#Android allows only even numbers
console_port=$(( ${console_port} + 2 ))
echo PORT1 ${console_port}
done
ports[k]=${console_port}
k=$(( $k + 1 ))
while netstat -atwn | grep "^.*{listener_port}.*:\*\s*LISTEN\s*$"
do
listener_port=$(( ${listener_port} + 1 ))
echo PORT2 ${listener_port}
done
ports[k]=${listener_port}
k=$(( $k + 1 ))
while netstat -atwn | grep "^.*{socat_port}.*:\*\s*LISTEN\s*$"
do
socat_port=$(( ${socat_port} + 1 ))
echo PORT3 ${socat_port}
done
ports[k]=${socat_port}
k=$(( $k + 1 ))
#Console Port should and can only be an even number
#Android allows only even numbers
console_port=$(( ${console_port} + 2 ))
listener_port=$(( ${listener_port} + 1 ))
socat_port=$(( ${socat_port} + 1 ))
}
}
# create the AVD
function createAVD {
local CONSOLE_PORT=$1
echo no | android -s create avd -n avd_$CONSOLE_PORT -t "$ANDROID_TARGET" -c $SDCARD -f -b $ANDROID_ABI
}
# start the AVD
# This starts the emulator
function startEmulator {
local CONSOLE_PORT=$1
echo "[emulator-$CONSOLE_PORT] Starting emulator with avd avd_$CONSOLE_PORT and console port $CONSOLE_PORT"
emulator -avd avd_$CONSOLE_PORT -port $CONSOLE_PORT -no-boot-anim -noaudio -no-window &
# This waits for emulator to start up
echo "[emulator-$CONSOLE_PORT] Waiting for emulator to boot completely"
wait_for_boot_complete "getprop dev.bootcomplete" 1
wait_for_boot_complete "getprop sys.boot_completed" 1
wait_for_boot_complete "pm path android" package
}
# function to really, really check things are booted up
function wait_for_boot_complete {
local boot_property=$1
local boot_property_test=$2
echo "[emulator-$CONSOLE_PORT] Checking $boot_property..."
local result=`adb -s emulator-$CONSOLE_PORT shell $boot_property 2>/dev/null | grep "$boot_property_test"`
while [ -z $result ]; do
sleep 1
result=`adb -s emulator-$CONSOLE_PORT shell $boot_property 2>/dev/null | grep "$boot_property_test"`
done
echo "[emulator-$CONSOLE_PORT] All boot properties succesful"
}
# Copy the APK in and start webdriver
function installWebdriverAPK {
local CONSOLE_PORT=$1
echo "[emulator-$CONSOLE_PORT] Installing WebDriver apk"
adb -s emulator-$CONSOLE_PORT install $APK_DIR/android-server.apk
}
# Activating Webdriver
function activateWebdriver {
local CONSOLE_PORT=$1
echo "[emulator-$CONSOLE_PORT] Getting out of home screen"
adb -s emulator-$CONSOLE_PORT shell input keyevent 82
adb -s emulator-$CONSOLE_PORT shell input keyevent 4
echo "[emulator-$CONSOLE_PORT] Activating WebDriver app"
adb -s emulator-$CONSOLE_PORT shell am start -a android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity
}
# set up port forwarding
function portForward {
local CONSOLE_PORT=$1
local LISTENER_PORT=$2
echo "[emulator-$CONSOLE_PORT] Setting up port forwarding"
adb -s emulator-$CONSOLE_PORT forward tcp:$LISTENER_PORT tcp:8080
}
# start up socat
function start_socat {
local CONSOLE_PORT=$1
local LISTENER_PORT=$2
local SOCAT_PORT=$3
echo "[emulator-$CONSOLE_PORT] Starting up socat on port $SOCAT_PORT"
socat TCP-LISTEN:$SOCAT_PORT,fork TCP:localhost:$LISTENER_PORT &
}
# register the node on the grid
function register_node {
local CONSOLE_PORT=$1
local SOCAT_PORT=$2
JSON="{'configuration': {'registerCycle': 5000, 'hub': 'http://<HUB_HOST>:<HUB_PORT>/grid/register', 'host': '<LOCAL_IP>', 'proxy': 'org.openqa.grid.selenium.proxy.DefaultRemoteProxy', 'maxSession': 1, 'port': <SOCAT_PORT>, 'hubPort': <HUB_PORT>, 'hubHost': '<HUB_HOST>', 'url': 'http://<LOCAL_IP>:<SOCAT_PORT>', 'remoteHost': 'http://<LOCAL_IP>:<SOCAT_PORT>', 'register': true, 'role': 'node'}, 'class': 'org.openqa.grid.common.RegistrationRequest', 'capabilities': [{'seleniumProtocol': 'WebDriver', 'platform': 'ANDROID', 'browserName': 'android', 'version': null, 'maxInstances': 1}]}"
JSON=${JSON//<HUB_HOST>/$HUB_HOST}
JSON=${JSON//<HUB_PORT>/$HUB_PORT}
JSON=${JSON//<LOCAL_IP>/$LOCAL_IP}
JSON=${JSON//<SOCAT_PORT>/$SOCAT_PORT}
echo "[emulator-$CONSOLE_PORT] json is: ${JSON}"
curl -X POST -d "${JSON}" http://$HUB_HOST:$HUB_PORT/grid/register
}
# create one emulator instance
function createOneEmulatorInstance {
local CONSOLE_PORT=$1
local LISTENER_PORT=$2
local SOCAT_PORT=$3
createAVD $CONSOLE_PORT
startEmulator $CONSOLE_PORT
installWebdriverAPK $CONSOLE_PORT
activateWebdriver $CONSOLE_PORT
portForward $CONSOLE_PORT $LISTENER_PORT
start_socat $CONSOLE_PORT $LISTENER_PORT $SOCAT_PORT
register_node $CONSOLE_PORT $SOCAT_PORT
}
## The main function :)
function main {
# Get an array of free port numbers to use
findFreePorts
# Based on the port number found, create an instance of an emulator up to the EMULATOR_COUNT specified
for (( l=0, i=0 ; l < ${#ports[@]}, i < $EMULATOR_COUNT; i++, l=l+3 ))
{
echo "ports for emulator $((i+1)): console=${ports[$l]}, listener=${ports[$l+1]}, socat=${ports[$l+2]}"
createOneEmulatorInstance ${ports[$l]} ${ports[$l+1]} ${ports[$l+2]} &
}
# Wait until those emulators are registered on the grid
# TODO: make this check an all-in-one comparison, not sequentially checking each IP as it does now.
# However, this won't really block anything more than a millisecond more than reality
for (( l=0, i=0 ; l < ${#ports[@]}, i < $EMULATOR_COUNT; i++, l=l+3 ))
{
echo "[emulator-${ports[$l]}] testing for $LOCAL_IP:${ports[$l+2]} on grid $HUB_HOST:$HUB_PORT ..."
while [[ `curl -s http://$HUB_HOST:$HUB_PORT/grid/console` != *$LOCAL_IP:${ports[$l+2]}* ]]
do
sleep 1
done
echo ""
echo "[emulator-${ports[$l]}] testing for $LOCAL_IP:${ports[$l+2]} on grid $HUB_HOST:$HUB_PORT successful!"
}
echo Emulator startup complete!
}
## Execute the script
main
@stackedsax
Copy link
Author

Also, try downloading the sdk and then running something like:

android update sdk -u -t "tools,platform-tools,platforms,sysimg-15"

and try installing this:

wget http://download.testobject.org/dev/android_ics_x86_goldfish.tar.gz

To get an x86 emulator.

@27Prac
Copy link

27Prac commented Jul 29, 2013

Hey,
Thanks for the information
You mentioned above "Please refer to the README for usage instructions."

Can you please share the ReadMe Usage Instruction file as soon as possible. I could not find it on this page.

Thanks,
27Prac

@isaaclacoba
Copy link

Thanks a lot for publishing this code. It helped me a lot to know how automatically run my tests.

@afjoseph
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment