1#!/bin/bash 2 3# Copyright (C) 2019 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18# Test Android Runtime (Boot) device configuration flags (living in namespace 19# `runtime_native_boot`). 20 21me=$(basename $0) 22 23# Namespace containing the tested flag. 24namespace=runtime_native_boot 25# Default set of checked zygote processes. 26zygotes= 27 28# Status of whole test script. 29exit_status=0 30 31function say { 32 echo "$me: $*" 33} 34 35function banner { 36 local separator=$(echo "$@" | sed s/./=/g ) 37 say "$separator" 38 say "$@" 39 say "$separator" 40} 41 42function fail { 43 say "FAILED: $@" 44 exit_status=1 45} 46 47function reboot_and_wait_for_device { 48 say "Rebooting device..." 49 adb reboot 50 adb wait-for-device >/dev/null 51 # Wait until the device has finished booting. Give the device 60 iterations 52 # (~60 seconds) to try and finish booting before declaring defeat. 53 local niters=60 54 for i in $(seq $niters); do 55 [[ $(adb shell getprop sys.boot_completed) -eq 1 ]] && return 0 56 sleep 1 57 done 58 fail "Device did not finish booting before timeout (~$niters seconds)" 59} 60 61# check_device_config_flag CONTEXT FLAG VALUE 62# ------------------------------------------- 63# Check that the device configuration flag FLAG is set to VALUE. Use CONTEXT in 64# logging. 65function check_device_config_flag { 66 local context=$1 67 local flag=$2 68 local value=$3 69 70 say "[$context] Check that the device configuration flag is set..." 71 local flag_value=$(adb shell device_config get "$namespace" "$flag") 72 [[ "$flag_value" = "$value" ]] \ 73 || fail "Device configuration flag \`$flag\` set to \`$flag_value\` (expected \`$value\`)" 74} 75 76# check_no_device_config_flag CONTEXT FLAG 77# ---------------------------------------- 78# Check that the device configuration flag FLAG is not set. Use CONTEXT in 79# logging. 80function check_no_device_config_flag { 81 local context=$1 82 local flag=$2 83 84 say "[$context] Check that the device configuration flag is not set..." 85 local flag_value=$(adb shell device_config get "$namespace" "$flag") 86 [[ "$flag_value" = null ]] \ 87 || fail "Device configuration flag \`$flag\` set to \`$flag_value\` (expected `null`)" 88} 89 90# get_system_property PROP 91# ------------------------ 92# Get system property PROP associated with a device configuration flag. 93function get_system_property { 94 local prop=$1 95 96 # Note that we need to be root to read that system property. 97 adb root >/dev/null 98 local prop_value=$(adb shell getprop "$prop") 99 adb unroot >/dev/null 100 echo "$prop_value" 101} 102 103# check_system_property CONTEXT PROP VALUE 104# ---------------------------------------- 105# Check that the system property PROP associated with a device configuration 106# flag is set to VALUE. Use CONTEXT in logging. 107function check_system_property { 108 local context=$1 109 local prop=$2 110 local value=$3 111 112 say "[$context] Check that the persistent system property is set..." 113 local prop_value=$(get_system_property "$prop") 114 [[ "$prop_value" = "$value" ]] \ 115 || fail "System property \`$prop\` set to \`$prop_value\` (expected \`$value\`)" 116} 117 118# check_no_system_property CONTEXT PROP 119# ------------------------------------- 120# Check that the system property PROP associated with a device configuration 121# flag is not set. Use CONTEXT in logging. 122function check_no_system_property { 123 local context=$1 124 local prop=$2 125 126 say "[$context] Check that the persistent system property is not set..." 127 local prop_value=$(get_system_property "$prop") 128 [[ -z "$prop_value" ]] \ 129 || fail "System property \`$prop\` set to \`$prop_value\` (expected unset property)" 130} 131 132# find_zygote_runtime_option ZYGOTE RUNTIME_OPTION 133# ------------------------------------------------ 134# Return whether ZYGOTE is passed RUNTIME_OPTION. 135function find_zygote_runtime_option { 136 local zygote=$1 137 local runtime_option=$2 138 139 adb logcat -d -s "$zygote" | grep -q -e "option\[[0-9]\+\]=$runtime_option" 140} 141 142# check_zygote_runtime_option CONTEXT RUNTIME_OPTION 143# -------------------------------------------------- 144# Check that all zygote processes are passed RUNTIME_OPTION as runtime option. Use 145# CONTEXT in logging. 146function check_zygote_runtime_option { 147 local context=$1 148 local runtime_option=$2 149 150 say \ 151 "[$context] Check that all zygote processes are passed \`$runtime_option\` as runtime option..." 152 for zygote in $zygotes; do 153 find_zygote_runtime_option "$zygote" "$runtime_option" \ 154 || fail "Found no \`$runtime_option\` among runtime options passed to \`$zygote\`" 155 done 156} 157 158# check_no_zygote_runtime_option CONTEXT RUNTIME_OPTION 159# ----------------------------------------------------- 160# Check that no zygote process is passed RUNTIME_OPTION as runtime option. Use 161# CONTEXT in logging. 162function check_no_zygote_runtime_option { 163 local context=$1 164 local runtime_option=$2 165 166 say "[$context] Check that no zygote process is passed \`$runtime_option\` as runtime option..." 167 for zygote in $zygotes; do 168 find_zygote_runtime_option "$zygote" "$runtime_option" \ 169 && fail "Found \`$runtime_option\` among runtime options passed to \`$zygote\`" 170 done 171} 172 173# check_android_runtime_message CONTEXT MESSAGE 174# --------------------------------------------- 175# Return whether AndroidRuntime generated MESSAGE in logcat. Use CONTEXT in 176# logging. 177function check_android_runtime_message { 178 local context=$1 179 local message=$2 180 181 say "[$context] Check that AndroidRuntime generated expected message in logcat..." 182 adb logcat -d -s AndroidRuntime | grep -F -q "$message" \ 183 || fail "Found no message \"$message\" generated by AndroidRuntime" 184} 185 186# check_no_android_runtime_message CONTEXT MESSAGE 187# ------------------------------------------------ 188# Return whether AndroidRuntime did not generate MESSAGE in logcat. Use CONTEXT 189# in logging. 190function check_no_android_runtime_message { 191 local context=$1 192 local message=$2 193 194 say "[$context] Check that AndroidRuntime did not generate unexpected message in logcat..." 195 adb logcat -d -s AndroidRuntime | grep -F -q -v "$message" \ 196 || fail "Found message \"$message\" generated by AndroidRuntime" 197} 198 199# test_android_runtime_flag FLAG VALUE CHECK_EFFECT CHECK_NO_EFFECT 200# ----------------------------------------------------------------- 201# Test device configuration FLAG with VALUE. CHECK_EFFECT and CHECK_NO_EFFECT 202# are functions that are passed a context as sole argument and that respectively 203# check the effect or the absence of effect of the flag. 204function test_android_runtime_flag { 205 local flag=$1 206 local value=$2 207 local check_effect=$3 208 local check_no_effect=$4 209 210 # Persistent system property (set after a reboot) associated with the device 211 # configuration flag. 212 local prop="persist.device_config.$namespace.$flag" 213 214 banner "Testing \`$flag\` value \`$value\`." 215 216 say "Setting device configuration flag..." 217 adb shell device_config put "$namespace" "$flag" "$value" 218 # Give some time to the device to digest this change before rebooting. 219 sleep 3 220 221 # Check that both the device configuration flag and the associated system 222 # property are set, but that flag has not produced an effect on the system (as 223 # we haven't rebooted yet). 224 local context="Flag set, before reboot" 225 check_device_config_flag "$context" "$flag" "$value" 226 check_system_property "$context" "$prop" "$value" 227 $check_no_effect "$context" 228 229 # Reboot device for the flag value to take effect. 230 reboot_and_wait_for_device 231 context="Flag set, after 1st reboot" 232 check_device_config_flag "$context" "$flag" "$value" 233 check_system_property "$context" "$prop" "$value" 234 $check_effect "$context" 235 236 # Reboot device a second time and check that the state has persisted. 237 reboot_and_wait_for_device 238 context="Flag set, after 2nd reboot" 239 check_device_config_flag "$context" "$flag" "$value" 240 check_system_property "$context" "$prop" "$value" 241 $check_effect "$context" 242 243 say "Unsetting device configuration flag..." 244 adb shell device_config delete "$namespace" "$flag" >/dev/null 245 # Give some time to the device to digest this change before rebooting. 246 sleep 3 247 248 # Reboot and check that the device is back to its default state. 249 reboot_and_wait_for_device 250 context="Flag unset, after 3rd reboot" 251 check_no_device_config_flag "$context" "$flag" 252 check_no_system_property "$context" "$prop" 253 $check_no_effect "$context" 254} 255 256 257# Pre-test actions. 258# ================= 259 260# Enumerate Zygote processes. 261case $(adb shell getprop ro.zygote) in 262 (zygote32) zygotes="zygote";; 263 (zygote64) zygotes="zygote64";; 264 (zygote32_64|zygote64_32) zygotes="zygote zygote64";; 265esac 266 267# Test "enable_generational_cc" flag values. 268# ========================================== 269 270function check_nogenerational_cc { 271 check_zygote_runtime_option "$1" "-Xgc:nogenerational_cc" 272} 273function check_no_nogenerational_cc { 274 check_no_zygote_runtime_option "$1" "-Xgc:nogenerational_cc" 275} 276 277function check_generational_cc { 278 check_zygote_runtime_option "$1" "-Xgc:generational_cc" 279} 280function check_no_generational_cc { 281 check_no_zygote_runtime_option "$1" "-Xgc:generational_cc" 282} 283 284test_android_runtime_flag \ 285 enable_generational_cc false check_nogenerational_cc check_no_nogenerational_cc 286test_android_runtime_flag \ 287 enable_generational_cc true check_generational_cc check_no_generational_cc 288 289# Test "enable_apex_image" flag values. 290# ===================================== 291 292default_boot_image_message="Using default boot image" 293function check_default_boot_image { 294 check_android_runtime_message "$1" "$default_boot_image_message" 295} 296function check_no_default_boot_image { 297 check_no_android_runtime_message "$1" "$default_boot_image_message" 298} 299 300apex_boot_image_option="-Ximage:/system/framework/apex.art" 301apex_boot_image_message="Using Apex boot image: '$apex_boot_image_option'" 302function check_apex_boot_image { 303 check_zygote_runtime_option "$1" "$apex_boot_image_option" 304 check_android_runtime_message "$1" "$apex_boot_image_message" 305} 306function check_no_apex_boot_image { 307 check_no_zygote_runtime_option "$1" "$apex_boot_image_option" 308 check_no_android_runtime_message "$1" "$apex_boot_image_message" 309} 310 311test_android_runtime_flag \ 312 enable_apex_image false check_default_boot_image check_no_default_boot_image 313test_android_runtime_flag \ 314 enable_apex_image true check_apex_boot_image check_no_apex_boot_image 315 316# Post-test actions. 317# ================== 318 319if [[ "$exit_status" -eq 0 ]]; then 320 banner "All tests passed." 321else 322 banner "Test(s) failed." 323fi 324exit $exit_status 325