1#! /bin/bash 2 3YELLOW="\033[1;33m" 4NOCOLOR="\033[0m" 5BLUE="\033[1;34m" 6RED="\033[1;91m" 7 8function happy_hedgehog { 9 echo -e "\t${BLUE}" 10 echo -e "\t ___------__" 11 echo -e "\t |\__-- /\ _-" 12 echo -e "\t |/_ __ -" 13 echo -e "\t // \ / \ /__" 14 echo -e "\t | 0 | 0 |__ --_ Gotta go fast!" 15 echo -e "\t \\____-- __ \ ___-" 16 echo -e "\t ( @ __/ / /_" 17 echo -e "\t -_____--- --_" 18 echo -e "\t // \ \\ ___-" 19 echo -e "\t //|\__/ \\ \\" 20 echo -e "\t \_-\_____/ \-\\" 21 echo -e "\t // \\--\|" 22 echo -e "\t ${RED}____${BLUE}// ||${RED}_" 23 echo -e "\t${RED} /_____\ /___\\" 24 echo -e "${NOCOLOR}" 25} 26 27function sad_hedgehog { 28 echo -e "\t${BLUE}" 29 echo -e "\t ___------__" 30 echo -e "\t |\__-- /\ _-" 31 echo -e "\t |/_ __ -" 32 echo -e "\t // \ / \ /__" 33 echo -e "\t | 0 | 0 |__ --_ Gotta go sllloowwww!" 34 echo -e "\t \\____-- __ \ ___-" 35 echo -e "\t ( @ __ / /_" 36 echo -e "\t -_____--- --_" 37 echo -e "\t // \ \\ ___-" 38 echo -e "\t //|\__/ \\ \\" 39 echo -e "\t \_-\_____/ \-\\" 40 echo -e "\t // \\--\|" 41 echo -e "\t ${RED} ____${BLUE}// ||${RED}_" 42 echo -e "\t${RED} /_____\ /___\\" 43 echo -e "{$NOCOLOR}" 44} 45 46PYTHON_BIN="python3.10" 47 48function check_environment { 49 if [[ -z "${ANDROID_BUILD_TOP}" ]] || [[ -z "${ANDROID_HOST_OUT}" ]] ; then 50 echo -e "${RED}ANDROID_BUILD_TOP${NOCOLOR} or ${RED}ANDROID_HOST_OUT${NOCOLOR} is not set for host run" 51 echo -e "Navigate to android root and run:" 52 echo -e "${YELLOW}" 53 echo -e ". build/envsetup.sh" 54 echo -e "lunch <fish>" 55 echo -e "${NOCOLOR}" 56 echo 57 exit 1 58 fi 59 if ! [ -x "$(command -v ${PYTHON_BIN})" ] ; then 60 echo -e "${RED}You must have ${PYTHON_BIN} installed${NOCOLOR}" 61 exit 1 62 fi 63 ${PYTHON_BIN} -m virtualenv --version 64 if [[ $? -ne 0 ]] ; then 65 echo -e "${RED}virtualenv not installed for ${PYTHON_BIN}${NOCOLOR}" 66 echo -e "${RED}Please run '${PYTHON_BIN} -m pip install virtualenv' to install it${NOCOLOR}" 67 exit 1 68 fi 69} 70 71ASHMEM_OUT="/dev/shm/out" 72ASHMEM_DIST="${ASHMEM_OUT}/dist" 73ASHMEM_VENV="${ASHMEM_DIST}/bluetooth_venv" 74ASHMEM_GOTTA_GO_FAST="/dev/shm/gottagofast" 75ASHMEM_HOST_LOGS="${ASHMEM_GOTTA_GO_FAST}/logs" 76ASHMEM_OUT_TARGET="${ASHMEM_GOTTA_GO_FAST}/target" 77ASHMEM_SOONG="${ASHMEM_GOTTA_GO_FAST}/out/soong" 78CERT_HOST_LOGS="/tmp/logs/HostOnlyCert" 79CERT_DEVICE_LOGS="TODO: Add this" 80CERT_TEST_VENV=${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv 81OUT_TARGET="${ANDROID_BUILD_TOP}/out/target" 82TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/host_config.yaml" 83TEST_FILTER="--presubmit" 84TEST_RUNNER="blueberry/tests/gd/gd_test_runner.py" 85CPP_BUILD_TARGET="bluetooth_stack_with_facade root-canal bluetooth_packets_python3 gd_hci_packets_python3_gen" 86RUST_BUILD_TARGET="bluetooth_with_facades root-canal bluetooth_packets_python3 bt_topshim_facade gd_hci_packets_python3_gen" 87BUILD_TARGET=$CPP_BUILD_TARGET 88 89CLEAN_VENV=false 90GOTTA_GO_FAST=false 91NUM_REPETITIONS="1" 92SKIP_SOONG_BUILD=false 93USE_ASHMEM_VENV=true 94VERBOSE_MODE=false 95DEVICE_TEST=false 96 97## Verify devices connected and valid 98DUT_SERIAL="DUT Not Set" 99DUT_ADB="DUT Not Set" 100DUT_NAME="DUT Not Set" 101 102# Used for position arguments needed for later 103POSITIONAL=() 104function parse_options { 105 while [[ $# -gt 0 ]] 106 do 107 key="$1" 108 case $key in 109 # This will delete the existing venv before running the test 110 # If you updated external libraries such as ACTS, you need to add this flag 111 --clean) 112 CLEAN_VENV=true 113 shift # past argument 114 ;; 115 --help) 116 echo 117 echo -e "${YELLOW}Help menu${NOCOLOR}" 118 echo -e "===================================" 119 echo -e "${BLUE} --clean${NOCOLOR}" 120 echo -e " Clean the virtul environment; use if ACTS has been updated." 121 echo -e "${BLUE} --disable-ashmem-venv${NOCOLOR}" 122 echo -e " Places the virtual environment on disk rather than in ashmem which is default." 123 echo -e "${BLUE} --gotta-go-fast${NOCOLOR}" 124 echo -e " Makes use of ashmem as best as possible for targeted speed increases." 125 echo -e "${BLUE} --device${NOCOLOR}" 126 echo -e " Run the test on the 2 real devices." 127 echo -e "${BLUE} --sl4a${NOCOLOR}" 128 echo -e " Run GD Sl4A combination tests using the default gd_sl4a config." 129 echo -e " Please install the correct SL4A build to DUT manually before running tests." 130 echo -e "${BLUE} --sl4a_sl4a${NOCOLOR}" 131 echo -e " Run SL$A combination tests using the default sl4a_sl4a config." 132 echo -e " Please install the correct SL4A build to DUT and cert manually before running tests." 133 echo -e "${BLUE} --topshim${NOCOLOR}" 134 echo -e " Run Topshim combination tests using the default topshim config." 135 echo -e "${BLUE} --rust${NOCOLOR}" 136 echo -e " Run the test using the rust implementation on the 2 real devices." 137 echo -e "${BLUE} --rhost${NOCOLOR}" 138 echo -e " Run the test using the rust implementation on the host." 139 echo -e "${BLUE} --repeat=<N>${NOCOLOR}" 140 echo -e " Repeat the test sequence N (int) number of times." 141 echo -e "${BLUE} --skip-soong-build${NOCOLOR}" 142 echo -e " Skips building soong targets. Use when you are just modifying simple python files." 143 echo -e "${BLUE} --test_config=<configfile>${NOCOLOR}" 144 echo -e " Override default test configuration." 145 echo -e "${BLUE} --verbose${NOCOLOR}" 146 echo -e " Displays device logs and test logs to output." 147 echo 148 echo -e "Usage: $0 [--clean|--repeat=<N>|--test_config=<config>] [TestGroupName[.IndividualTestName]]" 149 echo -e " ${YELLOW}e.g." 150 echo -e " $0 --clean SecurityTest" 151 echo -e " $0 --verbose SecurityTest:test_dut_initiated_display_only_display_only ${NOCOLOR}" 152 echo 153 shift 154 exit 0 155 ;; 156 # This will cause the bluetooth_venv to NOT be created in ashmem 157 # Using ashmem increases --clean build times by 40% (~21 seconds on my machine) 158 --disable-ashmem-venv) 159 USE_ASHMEM_VENV=false 160 shift # past argument 161 ;; 162 --gotta-go-fast) 163 GOTTA_GO_FAST=true 164 shift # past argument 165 ;; 166 --device) 167 DEVICE_TEST=true 168 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/devices_config.yaml" 169 shift # past argument 170 ;; 171 # Repeat running the specified test cases by N times in one single setup 172 --repeat=*) 173 NUM_REPETITIONS="${key#*=}" 174 shift # past argument 175 ;; 176 --skip-soong-build) 177 SKIP_SOONG_BUILD=true 178 shift 179 ;; 180 --test_config=*) 181 TEST_CONFIG="${key#*=}" 182 shift # past argument 183 ;; 184 --rust) 185 BUILD_TARGET=$RUST_BUILD_TARGET 186 export RUST_BACKTRACE=1 187 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_devices_config.yaml" 188 DEVICE_TEST=true 189 shift # past argument 190 ;; 191 --rhost) 192 export RUST_BACKTRACE=1 193 BUILD_TARGET=$RUST_BUILD_TARGET 194 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_host_config.yaml" 195 shift # past argument 196 ;; 197 --sl4a) 198 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd_sl4a/gd_sl4a_device_config.yaml" 199 TEST_RUNNER="blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py" 200 DEVICE_TEST=true 201 shift # past argument 202 ;; 203 --sl4a_sl4a) 204 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_device_config.yaml" 205 TEST_RUNNER="blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py" 206 DEVICE_TEST=true 207 shift # past argument 208 ;; 209 --topshim) 210 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/topshim/topshim_host_config.yaml" 211 TEST_RUNNER="blueberry/tests/topshim/topshim_test_runner.py" 212 shift 213 ;; 214 # This will log everything to both log file and stdout 215 --verbose) 216 VERBOSE_MODE=true 217 shift # past argument 218 ;; 219 --*) # unknown argument 220 echo "$0: unrecognized argument '$1'" 221 echo "Try '$0 --help' for more information" 222 exit 1 223 shift 224 ;; 225 *) # unknown option 226 POSITIONAL+=("$1") # save it in an array for later 227 shift # past argument 228 ;; 229 esac 230 done 231 set -- "${POSITIONAL[@]}" # restore positional parameters 232 233 # Set the test filter 234 if [[ -n "$1" ]] ; then 235 TEST_FILTER="--tests $1" 236 fi 237 238 INSTALL_ARGS="--reuse-libraries" 239 if [ "$CLEAN_VENV" == true ] ; then 240 echo -e "${YELLOW}Cleaning up existing virtualenv${NOCOLOR}" 241 rm -rf $CERT_TEST_VENV/* 242 rm -rf $CERT_TEST_VENV 243 mkdir -p ${CERT_TEST_VENV} 244 INSTALL_ARGS="" 245 else 246 echo -e "${YELLOW}Try to reuse existing virtualenv at ${CERT_TEST_VENV}${NOCOLOR}" 247 fi 248 249} 250 251function select_devices { 252 if [ "$DEVICE_TEST" == true ] ; then 253 RR="$(cat ${TEST_CONFIG}|grep \'CERT\\\|DUT\')" 254 if [ "$RR" != "" ]; then 255 DUT_SERIAL="$(menu-adb DUT)" 256 DUT_ADB="adb -s ${DUT_SERIAL}" 257 DUT_NAME="$(adb devices -l | grep -v "List of device" | grep ${DUT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" 258 CERT_SERIAL="$(menu-adb CERT)" 259 CERT_ADB="adb -s ${CERT_SERIAL}" 260 CERT_NAME="$(adb devices -l | grep -v "List of device" | grep ${CERT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" 261 262 if [ "${CERT_SERIAL}" == "${DUT_SERIAL}" ]; then 263 echo 264 echo -e "${RED}ERROR: CERT and DUT cannot be the same device, or you only have one device connected!${NOCOLOR}" 265 echo 266 exit 1 267 fi 268 269 ## Set android devices in config 270 sed -i "s/'DUT'/'${DUT_SERIAL}'/g" ${TEST_CONFIG} 271 sed -i "s/'CERT'/'${CERT_SERIAL}'/g" ${TEST_CONFIG} 272 fi 273 fi 274} 275 276function soong_build { 277 if [ "$CLEAN_VENV" == true ] ; then 278 $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --build-mode --"modules-in-a-dir" --dir="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system" dist $BUILD_TARGET -j $(nproc) 279 if [[ $? -ne 0 ]] ; then 280 echo -e "${RED}Failed to build ${BUILD_TARGET}${NOCOLOR}" 281 exit 1 282 fi 283 else 284 $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --build-mode --"all-modules" --dir="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system" dist $BUILD_TARGET -j $(nproc) 285 if [[ $? -ne 0 ]] ; then 286 echo -e "${RED}Failed to build ${BUILD_TARGET}${NOCOLOR}" 287 exit 1 288 fi 289 fi 290} 291 292function setup_venv { 293 # Make venv in memory, decreases --clean build times by 40% 294 # Caveat is you lose the venv if the computer reboots 295 if [ "${USE_ASHMEM_VENV}" == true ] ; then 296 echo -e "${BLUE}Using ashmem virtual environment.${NOCOLOR}" 297 if [[ ! -L ${CERT_TEST_VENV} ]] ; then 298 echo -e "${BLUE}" 299 echo -ne "Creating ashmem dist folder..." 300 mkdir -p "${ASHMEM_VENV}" 301 # Ensure the directory doesn't exist 302 rm -rf "${CERT_TEST_VENV}" 303 echo -e "Done" 304 echo -ne "Sym linking ${ASHMEM_VENV} to ${CERT_TEST_VENV}..." 305 ln -s "${ASHMEM_VENV}" "${CERT_TEST_VENV}" 306 echo -e "Done" 307 echo -e "${NOCOLOR}" 308 fi 309 else 310 echo -e "${RED}Not using ashmem virtual environment.${NOCOLOR}" 311 if [[ -L ${CERT_TEST_VENV} ]] ; then 312 echo -e "${RED}" 313 echo -en "Removing sym link from ${ASHMEM_VENV} to ${CERT_TEST_VENV}..." 314 rm -rf ""${ASHMEM_VENV} "${CERT_TEST_VENV}" 315 echo -e "Done" 316 echo -en "Cleaning up memory..." 317 rm -rf "${ASHMEM_VENV}" 318 echo -e "Done" 319 echo -e "${NOCOLOR}" 320 fi 321 fi 322 ${PYTHON_BIN} -m virtualenv --python `which "${PYTHON_BIN}"` "${CERT_TEST_VENV}" 323 if [[ $? -ne 0 ]] ; then 324 echo -e "${RED}Error setting up virtualenv${NOCOLOR}" 325 exit 1 326 fi 327 328 unzip -o -q "${ANDROID_BUILD_TOP}/out/dist/bluetooth_cert_tests.zip" -d "${CERT_TEST_VENV}/sources" 329 if [[ $? -ne 0 ]] ; then 330 echo -e "${RED}Error unzipping bluetooth_cert_tests.zip${NOCOLOR}" 331 exit 1 332 fi 333 334 venv_common 335} 336 337function incremental_venv { 338#LINT.IfChange 339 HOST_BIN="${ANDROID_BUILD_TOP}/out/host/linux-x86/bin" 340 HOST_LIB="${ANDROID_BUILD_TOP}/out/host/linux-x86/lib64" 341 DEST_DIR="${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv/sources" 342 DEST_LIB_DIR="${DEST_DIR}/lib64" 343 cp {$HOST_BIN,$DEST_DIR}/bluetooth_stack_with_facade 344 cp {$HOST_BIN,$DEST_DIR}/bluetooth_with_facades 345 cp {$HOST_BIN,$DEST_DIR}/bt_topshim_facade 346 cp {$HOST_BIN,$DEST_DIR}/root-canal 347 348 cp {$HOST_LIB,$DEST_DIR}/bluetooth_packets_python3.so 349 350 cp {$HOST_LIB,$DEST_LIB_DIR}/libbase.so 351 cp {$HOST_LIB,$DEST_LIB_DIR}/libbluetooth_gd.so 352 cp {$HOST_LIB,$DEST_LIB_DIR}/libc++.so 353 cp {$HOST_LIB,$DEST_LIB_DIR}/libchrome.so 354 cp {$HOST_LIB,$DEST_LIB_DIR}/libcrypto-host.so 355 cp {$HOST_LIB,$DEST_LIB_DIR}/libevent-host.so 356 cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc++_unsecure.so 357 cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc++.so 358 cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc_wrap.so 359 cp {$HOST_LIB,$DEST_LIB_DIR}/liblog.so 360 cp {$HOST_LIB,$DEST_LIB_DIR}/libssl-host.so 361 cp {$HOST_LIB,$DEST_LIB_DIR}/libz-host.so 362 cp {$HOST_LIB,$DEST_LIB_DIR}/libprotobuf-cpp-full.so 363 cp {$HOST_LIB,$DEST_LIB_DIR}/libunwindstack.so 364 cp {$HOST_LIB,$DEST_LIB_DIR}/liblzma.so 365 366 i="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/setup.py" 367 cp {${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system,$DEST_DIR}${i#${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system} 368 for i in `find ${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry -name "*.py" -type f`; do 369 cp {${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system,$DEST_DIR}${i#${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system} 370 done 371#LINT.ThenChange(../../Android.mk) 372 373 venv_common 374} 375 376function venv_common { 377 $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/setup.py" --quiet build --force "${INSTALL_ARGS}") 378 if [[ $? -ne 0 ]] ; then 379 echo -e "${RED}Error building GD Python libraries${NOCOLOR}" 380 echo -e "${YELLOW}NOTE:${NOCOLOR} To build external libraries the first time, please add --clean option." 381 exit 1 382 fi 383 384 $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/setup.py" --quiet install --skip-build --force "${INSTALL_ARGS}") 385 if [[ $? -ne 0 ]] ; then 386 echo -e "${RED}Error installing GD Python libraries${NOCOLOR}" 387 exit 1 388 fi 389 390"${CERT_TEST_VENV}/bin/python" -c " 391import bluetooth_packets_python3 as bp3 392bp3.BaseStruct 393" 394if [[ $? -ne 0 ]] ; then 395 echo -e "${RED}Setup failed as bluetooth_packets_python3 cannot be imported${NOCOLOR}" 396 exit 1 397fi 398 399if [ "${VERBOSE_MODE}" == true ] ; then 400 TEMP_CONFIG=/tmp/temp_mobly_config.yaml 401 cat "${TEST_CONFIG}" | "${CERT_TEST_VENV}/bin/python" -c " 402import sys 403import yaml 404config = yaml.load(sys.stdin) 405config['verbose_mode'] = True 406print(yaml.dump(config)) 407 " > "${TEMP_CONFIG}" 408 TEST_CONFIG="${TEMP_CONFIG}" 409 if [[ $? -ne 0 ]] ; then 410 echo -e "${RED}Setup failed as verbose mode is chosen but cannot be enabled${NOCOLOR}" 411 exit 1 412 fi 413fi 414} 415 416function gotta_go_fast { 417 if [ "${GOTTA_GO_FAST}" == true ] ; then 418 # Call here to explicitly note the flag is in use 419 happy_hedgehog 420 if [[ ! -L "${CERT_HOST_LOGS}" ]] ; then 421 rm -rf "${CERT_HOST_LOGS}" 422 mkdir -p "${ASHMEM_HOST_LOGS}" 423 ln -s "${ASHMEM_HOST_LOGS}" "${CERT_HOST_LOGS}" 424 fi 425 426 if [[ ! -L "${OUT_TARGET}" ]] ; then 427 rm -rf "${OUT_TARGET}" 428 mkdir -p "${ASHMEM_OUT_TARGET}" 429 ln -s "${ASHMEM_OUT_TARGET}" "${OUT_TARGET}" 430 fi 431 else 432 if [[ -L "${CERT_HOST_LOGS}" ]] ; then 433 # Call here so we don't spam anyone not using the flag 434 sad_hedgehog 435 rm -rf "${CERT_HOST_LOGS}" 436 rm -rf "${ASHMEM_HOST_LOGS}" 437 fi 438 439 if [[ -L "${OUT_TARGET}" ]] ; then 440 rm -rf "${OUT_TARGET}" 441 rm -rf "${ASHMEM_OUT_TARGET}" 442 fi 443 fi 444} 445 446function run_tests { 447 for n in $(seq "${NUM_REPETITIONS}"); do 448 $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/${TEST_RUNNER}" \ 449 "-c ${TEST_CONFIG}" "${TEST_FILTER}") 450 done 451 452 if [ "${CLEAN_VENV}" != true ] ; then 453 echo -e "${YELLOW}NOTE:${NOCOLOR} Completed tests using existing external libraries in virtualenv." 454 echo -e "${YELLOW}NOTE:${NOCOLOR} To update external libraries, please add --clean option." 455 fi 456} 457 458function menu-adb() { 459 TMP=$(adb devices -l | grep -v "List of device" | awk '{ print $1 }') 460 # TODO(optedoblivion): If the device doesn't have a name (offline), it misnames them 461 NTMP=$(adb devices -l | grep -v "List of device" | awk '{ print $6 }' | cut -d ':' -f 2) 462 SERIALS=($TMP) 463 DEVICES=($NTMP) 464 LEN=${#SERIALS[@]} 465 result=0 466 if [ $LEN -lt 1 ]; then 467 echo -e "${YELLOW}No devices connected!${NOCOLOR}" 468 return 1 469 fi 470 471 if [ "$LEN" == "" ]; then 472 LEN=0 473 fi 474 475 answer=0 476 477 DEVICE_NAME="$1 device" 478 479 if [ $LEN -gt 1 ]; then 480 echo "+-------------------------------------------------+" 1>&2 481 echo "| Choose a ${DEVICE_NAME}: " 1>&2 482 echo "+-------------------------------------------------+" 1>&2 483 echo "| |" 1>&2 484 let fixed_len=$LEN-1 485 for i in `seq 0 $fixed_len`; 486 do 487 serial=${SERIALS[i]} 488 device=${DEVICES[i]} 489 echo "| $i) $serial $device" 1>&2 490 ## TODO[MSB]: Find character count, fill with space and ending box wall 491 done 492 echo "| |" 1>&2 493 echo "+-------------------------------------------------+" 1>&2 494 echo 1>&2 495 echo -n "Index number: " 1>&2 496 read answer 497 fi 498 499 if [ $answer -ge $LEN ]; then 500 echo 501 echo "Please choose a correct index!" 1>&2 502 echo 503 return 1 504 fi 505 506 SERIAL=${SERIALS[$answer]} 507 echo $SERIAL 508} 509 510function main { 511 check_environment 512 parse_options $@ 513 select_devices 514 if [[ "${SKIP_SOONG_BUILD}" != true ]] ; then 515 soong_build 516 fi 517 if [ "$CLEAN_VENV" == true ] ; then 518 setup_venv 519 else 520 incremental_venv 521 fi 522 gotta_go_fast 523 run_tests 524} 525 526main $@ 527