1#!/usr/bin/env python3.4 2# 3# Copyright 2017 - Google 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 Test Script for Telephony Pre Check In Sanity 18""" 19 20import re 21import time 22from acts import signals 23from acts.utils import get_current_epoch_time 24from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest 25from acts_contrib.test_utils.tel.tel_bootloader_utils import reset_device_password 26from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phone_default_state 27from acts_contrib.test_utils.tel.tel_test_utils import abort_all_tests 28from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name 29from acts_contrib.test_utils.tel.tel_test_utils import get_service_state_by_adb 30from acts_contrib.test_utils.tel.tel_test_utils import is_sim_lock_enabled 31from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode_by_adb 32from acts_contrib.test_utils.tel.tel_test_utils import unlock_sim 33from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection 34from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection 35from acts_contrib.test_utils.tel.tel_voice_utils import call_setup_teardown 36from acts_contrib.test_utils.tel.tel_voice_utils import dumpsys_last_call_info 37from acts_contrib.test_utils.tel.tel_voice_utils import dumpsys_last_call_number 38from acts_contrib.test_utils.tel.tel_voice_utils import dumpsys_new_call_info 39from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call_by_adb 40from acts_contrib.test_utils.tel.tel_voice_utils import initiate_call 41from acts_contrib.test_utils.tel.tel_voice_utils import initiate_emergency_dialer_call_by_adb 42from acts_contrib.test_utils.tel.tel_voice_utils import last_call_drop_reason 43 44CARRIER_OVERRIDE_CMD = ( 45 "am broadcast -a com.google.android.carrier.action.LOCAL_OVERRIDE -n " 46 "com.google.android.carrier/.ConfigOverridingReceiver --ez") 47IMS_FIRST = "carrier_use_ims_first_for_emergency_bool" 48ALLOW_NON_EMERGENCY_CALL = "allow_non_emergency_calls_in_ecm_bool" 49BLOCK_DURATION_CMD = "duration_blocking_disabled_after_emergency_int" 50BLOCK_DURATION = 300 51 52 53class TelLiveEmergencyBase(TelephonyBaseTest): 54 def setup_class(self): 55 TelephonyBaseTest.setup_class(self) 56 self.number_of_devices = 1 57 fake_number = self.user_params.get("fake_emergency_number", "411") 58 self.fake_emergency_number = fake_number.strip("+").replace("-", "") 59 self.my_devices = self.android_devices[:] 60 61 for ad in self.android_devices: 62 if not is_sim_lock_enabled(ad): 63 self.setup_dut(ad) 64 return True 65 self.log.error("No device meets SIM READY or LOADED requirement") 66 raise signals.TestAbortClass("No device meets SIM requirement") 67 68 def setup_dut(self, ad): 69 self.dut = ad 70 output = self.dut.adb.shell("dumpsys carrier_config") 71 self.default_settings = {} 72 for setting in (IMS_FIRST, ALLOW_NON_EMERGENCY_CALL, 73 BLOCK_DURATION_CMD): 74 values = re.findall(r"%s = (\S+)" % setting, output) 75 if values: 76 self.default_settings[setting] = values[-1] 77 else: 78 self.default_settings[setting] = "" 79 self.dut.adb.shell(" ".join( 80 [CARRIER_OVERRIDE_CMD, BLOCK_DURATION_CMD, 81 "%s" % BLOCK_DURATION])) 82 self.dut_operator = get_operator_name(self.log, ad) 83 if self.dut_operator == "tmo": 84 self.fake_emergency_number = "611" 85 elif self.dut_operator == "vzw": 86 self.fake_emergency_number = "922" 87 elif self.dut_operator == "spt": 88 self.fake_emergency_number = "526" 89 if len(self.my_devices) > 1: 90 self.android_devices.remove(ad) 91 self.android_devices.insert(0, ad) 92 93 def teardown_class(self): 94 self.android_devices = self.my_devices 95 TelephonyBaseTest.teardown_class(self) 96 97 def setup_test(self): 98 if not unlock_sim(self.dut): 99 abort_all_tests(self.dut.log, "unable to unlock SIM") 100 self.expected_call_result = True 101 102 def teardown_test(self): 103 self.dut.ensure_screen_on() 104 self.dut.exit_setup_wizard() 105 reset_device_password(self.dut, None) 106 output = self.dut.adb.shell("dumpsys carrier_config") 107 for setting, state in self.default_settings.items(): 108 values = re.findall(r"%s = (\S+)" % setting, output) 109 if values and values[-1] != state: 110 self.dut.adb.shell(" ".join( 111 [CARRIER_OVERRIDE_CMD, setting, state])) 112 ensure_phone_default_state(self.log, self.dut) 113 114 def change_emergency_number_list(self): 115 test_number = "%s:%s" % (self.fake_emergency_number, 116 self.fake_emergency_number) 117 output = self.dut.adb.getprop("ril.test.emergencynumber") 118 if output != test_number: 119 cmd = "setprop ril.test.emergencynumber %s" % test_number 120 self.dut.log.info(cmd) 121 self.dut.adb.shell(cmd) 122 for _ in range(5): 123 existing = self.dut.adb.getprop("ril.ecclist") 124 self.dut.log.info("Existing ril.ecclist is: %s", existing) 125 if self.fake_emergency_number in existing: 126 return True 127 emergency_numbers = "%s,%s" % (existing, 128 self.fake_emergency_number) 129 cmd = "setprop ril.ecclist %s" % emergency_numbers 130 self.dut.log.info(cmd) 131 self.dut.adb.shell(cmd) 132 # After some system events, ril.ecclist might change 133 # wait sometime for it to settle 134 time.sleep(10) 135 if self.fake_emergency_number in existing: 136 return True 137 return False 138 139 def change_qcril_emergency_source_mcc_table(self): 140 # This will add the fake number into emergency number list for a mcc 141 # in qcril. Please note, the fake number will be send as an emergency 142 # number by modem and reach the real 911 by this 143 qcril_database_path = self.dut.adb.shell("find /data -iname qcril.db") 144 if not qcril_database_path: return 145 mcc = self.dut.droid.telephonyGetNetworkOperator() 146 mcc = mcc[:3] 147 self.dut.log.info("Add %s mcc %s in qcril_emergency_source_mcc_table") 148 self.dut.adb.shell( 149 "sqlite3 %s \"INSERT INTO qcril_emergency_source_mcc_table VALUES('%s','%s','','')\"" 150 % (qcril_database_path, mcc, self.fake_emergency_number)) 151 152 def fake_emergency_call_test(self, by_emergency_dialer=True, attemps=3): 153 self.dut.log.info("ServiceState is in %s", 154 get_service_state_by_adb(self.log, self.dut)) 155 if by_emergency_dialer: 156 dialing_func = initiate_emergency_dialer_call_by_adb 157 callee = self.fake_emergency_number 158 else: 159 dialing_func = initiate_call 160 # Initiate_call method has to have "+" in front 161 # otherwise the number will be in dialer without dial out 162 # with sl4a fascade. Need further investigation 163 callee = "+%s" % self.fake_emergency_number 164 for i in range(attemps): 165 begin_time = get_current_epoch_time() 166 result = True 167 if not self.change_emergency_number_list(): 168 self.dut.log.error("Unable to add number to ril.ecclist") 169 return False 170 time.sleep(1) 171 last_call_number = dumpsys_last_call_number(self.dut) 172 call_result = dialing_func(self.log, self.dut, callee) 173 time.sleep(3) 174 hangup_call_by_adb(self.dut) 175 if not call_result: 176 last_call_drop_reason(self.dut, begin_time) 177 self.dut.send_keycode("BACK") 178 self.dut.send_keycode("BACK") 179 if not dumpsys_new_call_info(self.dut, last_call_number): 180 result = False 181 if call_result == self.expected_call_result: 182 self.dut.log.info("Call to %s returns %s as expected", callee, 183 self.expected_call_result) 184 else: 185 self.dut.log.info("Call to %s returns %s", callee, 186 not self.expected_call_result) 187 result = False 188 if result: 189 return True 190 ecclist = self.dut.adb.getprop("ril.ecclist") 191 self.dut.log.info("ril.ecclist = %s", ecclist) 192 if self.fake_emergency_number in ecclist: 193 if i == attemps - 1: 194 self.dut.log.error("%s is in ril-ecclist, but call failed", 195 self.fake_emergency_number) 196 else: 197 self.dut.log.warning( 198 "%s is in ril-ecclist, but call failed, try again", 199 self.fake_emergency_number) 200 else: 201 if i == attemps - 1: 202 self.dut.log.error("Fail to write %s to ril-ecclist", 203 self.fake_emergency_number) 204 else: 205 self.dut.log.info("%s is not in ril-ecclist", 206 self.fake_emergency_number) 207 self.dut.log.info("fake_emergency_call_test result is %s", result) 208 return result 209 210 def set_ims_first(self, state): 211 output = self.dut.adb.shell( 212 "dumpsys carrier_config | grep %s | tail -1" % IMS_FIRST) 213 self.dut.log.info(output) 214 if state in output: return 215 cmd = " ".join([CARRIER_OVERRIDE_CMD, IMS_FIRST, state]) 216 self.dut.log.info(cmd) 217 self.dut.adb.shell(cmd) 218 self.dut.log.info( 219 self.dut.adb.shell( 220 "dumpsys carrier_config | grep %s | tail -1" % IMS_FIRST)) 221 222 def set_allow_non_emergency_call(self, state): 223 output = self.dut.adb.shell( 224 "dumpsys carrier_config | grep %s | tail -1" % 225 ALLOW_NON_EMERGENCY_CALL) 226 self.dut.log.info(output) 227 if state in output: return 228 cmd = " ".join([CARRIER_OVERRIDE_CMD, ALLOW_NON_EMERGENCY_CALL, state]) 229 self.dut.log.info(cmd) 230 self.dut.adb.shell(cmd) 231 self.dut.log.info( 232 self.dut.adb.shell("dumpsys carrier_config | grep %s | tail -1" % 233 ALLOW_NON_EMERGENCY_CALL)) 234 235 def check_emergency_call_back_mode(self, 236 by_emergency_dialer=True, 237 non_emergency_call_allowed=True, 238 attemps=3): 239 state = "true" if non_emergency_call_allowed else "false" 240 self.set_allow_non_emergency_call(state) 241 result = True 242 for _ in range(attemps): 243 if not self.change_emergency_number_list(): 244 self.dut.log.error("Unable to add number to ril.ecclist") 245 return False 246 last_call_number = dumpsys_last_call_number(self.dut) 247 self.dut.log.info("Hung up fake emergency call in ringing") 248 if by_emergency_dialer: 249 initiate_emergency_dialer_call_by_adb( 250 self.log, self.dut, self.fake_emergency_number, timeout=0) 251 else: 252 callee = "+%s" % self.fake_emergency_number 253 self.dut.droid.telecomCallNumber(callee) 254 time.sleep(3) 255 hangup_call_by_adb(self.dut) 256 ecclist = self.dut.adb.getprop("ril.ecclist") 257 self.dut.log.info("ril.ecclist = %s", ecclist) 258 if self.fake_emergency_number in ecclist: 259 break 260 call_info = dumpsys_new_call_info(self.dut, last_call_number) 261 if not call_info: 262 return False 263 call_tech = call_info.get("callTechnologies", "") 264 if "CDMA" in call_tech: 265 expected_ecbm = True 266 expected_data = False 267 expected_call = non_emergency_call_allowed 268 elif "GSM" in call_tech: 269 expected_ecbm = True 270 expected_data = True 271 expected_call = True 272 else: 273 expected_ecbm = False 274 expected_data = True 275 expected_call = True 276 last_call_number = dumpsys_last_call_number(self.dut) 277 begin_time = get_current_epoch_time() 278 self.dut.ensure_screen_on() 279 self.dut.exit_setup_wizard() 280 reset_device_password(self.dut, None) 281 call_check = call_setup_teardown( 282 self.log, self.dut, self.android_devices[1], ad_hangup=self.dut) 283 if call_check != expected_call: 284 self.dut.log.error("Regular phone call is %s, expecting %s", 285 call_check, expected_call) 286 result = False 287 call_info = dumpsys_new_call_info(self.dut, last_call_number) 288 if not call_info: 289 self.dut.log.error("New call is not in dumpsys telecom") 290 return False 291 if expected_ecbm: 292 if "ecbm" in call_info["callProperties"]: 293 self.dut.log.info("New call is in ecbm.") 294 else: 295 self.dut.log.error( 296 "New call is not in emergency call back mode.") 297 result = False 298 else: 299 if "ecbm" in call_info["callProperties"]: 300 self.dut.log.error("New call is in emergency call back mode") 301 result = False 302 if not expected_data: 303 if self.dut.droid.telephonyGetDataConnectionState(): 304 self.dut.log.info( 305 "Data connection is off as expected in ECB mode") 306 self.dut.log.info("Wait for getting out of ecbm") 307 if not wait_for_cell_data_connection(self.log, self.dut, True, 308 400): 309 self.dut.log.error( 310 "Data connection didn't come back after 5 minutes") 311 result = False 312 #if not self.dut.droid.telephonyGetDataConnectionState(): 313 # self.dut.log.error( 314 # "Data connection is not coming back") 315 # result = False 316 elif not verify_internet_connection(self.log, self.dut): 317 self.dut.log.error( 318 "Internet connection check failed after getting out of ECB" 319 ) 320 result = False 321 322 else: 323 self.dut.log.error("Data connection is not off in ECB mode") 324 if not verify_internet_connection(self.log, self.dut, False): 325 self.dut.log.error("Internet connection is not off") 326 result = False 327 else: 328 if self.dut.droid.telephonyGetDataConnectionState(): 329 self.dut.log.info("Data connection is on as expected") 330 if not verify_internet_connection(self.log, self.dut): 331 self.dut.log.error("Internet connection check failed") 332 result = False 333 else: 334 self.dut.log.error("Data connection is off, expecting on") 335 result = False 336 if expected_call: 337 return result 338 elapsed_time = (get_current_epoch_time() - begin_time) / 1000 339 if elapsed_time < BLOCK_DURATION: 340 time.sleep(BLOCK_DURATION - elapsed_time + 10) 341 if not call_setup_teardown( 342 self.log, self.dut, self.android_devices[1], 343 ad_hangup=self.dut): 344 self.dut.log.error("Regular phone call failed after out of ecbm") 345 result = False 346 return result 347 348 def check_normal_call(self): 349 result = True 350 if "wfc" not in self.test_name: 351 toggle_airplane_mode_by_adb(self.log, self.dut, False) 352 self.dut.ensure_screen_on() 353 self.dut.exit_setup_wizard() 354 reset_device_password(self.dut, None) 355 begin_time = get_current_epoch_time() 356 if not call_setup_teardown( 357 self.log, 358 self.android_devices[1], 359 self.dut, 360 ad_hangup=self.android_devices[1]): 361 self.dut.log.error("Regular MT phone call fails") 362 self.dut.log.info("call_info = %s", dumpsys_last_call_info( 363 self.dut)) 364 result = False 365 if not call_setup_teardown( 366 self.log, self.dut, self.android_devices[1], 367 ad_hangup=self.dut): 368 self.dut.log.error("Regular MO phone call fails") 369 self.dut.log.info("call_info = %s", dumpsys_last_call_info( 370 self.dut)) 371 result = False 372 return result 373