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 Project Fi Setting 18""" 19 20import time 21 22from acts.test_decorators import test_tracker_info 23from acts.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest 24from acts.test_utils.tel.tel_defines import CARRIER_SPT 25from acts.test_utils.tel.tel_defines import CARRIER_TMO 26from acts.test_utils.tel.tel_defines import CARRIER_USCC 27from acts.test_utils.tel.tel_lookup_tables import operator_name_from_plmn_id 28from acts.test_utils.tel.tel_test_utils import abort_all_tests 29from acts.test_utils.tel.tel_test_utils import ensure_phone_subscription 30from acts.test_utils.tel.tel_test_utils import ensure_wifi_connected 31from acts.test_utils.tel.tel_test_utils import is_sim_ready 32from acts.test_utils.tel.tel_test_utils import log_screen_shot 33from acts.test_utils.tel.tel_test_utils import multithread_func 34from acts.test_utils.tel.tel_test_utils import reboot_device 35from acts.test_utils.tel.tel_test_utils import refresh_droid_config 36from acts.test_utils.tel.tel_test_utils import send_dialer_secret_code 37from acts.test_utils.tel.tel_test_utils import toggle_airplane_mode_by_adb 38from acts.test_utils.tel.tel_test_utils import wait_for_state 39from acts.test_utils.tel.tel_test_utils import add_google_account 40from acts.test_utils.tel.tel_test_utils import remove_google_account 41 42CARRIER_AUTO = "auto" 43 44_CARRIER_DIALER_CODE_LOOKUP = { 45 CARRIER_AUTO: '342886', 46 CARRIER_SPT: '34777', 47 CARRIER_TMO: '34866', 48 CARRIER_USCC: '34872' 49} 50 51_SWITCHING_PREF_FILE = ( 52 '/data/data/com.google.android.apps.tycho/shared_prefs/switching.xml') 53 54_INTENT_FLAGS = int(0x00008000 | 0x10000000 | 0x00080000 | 0x00020000) 55_TYCHO_PKG = 'com.google.android.apps.tycho' 56_MAX_WAIT_TIME = 600 57_TYCHO_VERBOSE_LOGGING_CMDS = [ 58 "setprop log.tag.Tycho VERBOSE", 59 "CLASSPATH=/system/framework/am.jar su root app_process " 60 "/system/bin com.android.commands.am.Am broadcast -a " 61 "com.google.gservices.intent.action.GSERVICES_OVERRIDE " 62 "-e tycho.enable_request_logging true", 63 "CLASSPATH=/system/framework/am.jar su root app_process " 64 "/system/bin com.android.commands.am.Am broadcast -a " 65 "com.google.gservices.intent.action.GSERVICES_OVERRIDE " 66 "-e tycho.enable_sensitive_logging true", 67 "CLASSPATH=/system/framework/am.jar su root app_process " 68 "/system/bin com.android.commands.am.Am broadcast -a " 69 "com.google.gservices.intent.action.GSERVICES_OVERRIDE " 70 "-e tycho.enable_ample_logging true" 71] 72 73_TYCHO_SERVER_LAB_OVERRIDE_CMD = ( 74 "am broadcast -a com.google.gservices.intent.action.GSERVICES_OVERRIDE -e " 75 "url:tycho_server_endpoint https://android.googleapis.com/nova/nfe/ rewrite" 76 " https://android.googleapis.com/lab/nova/nfe/") 77 78 79class TychoClassId(object): 80 """Tycho Activity/Service Classnames.""" 81 # Activities 82 CARRIER_SETUP = 'CarrierSetupEntryPointTrampoline' 83 INIT_ACTIVITY = 'InitActivity' 84 # Services 85 SYNC_SERVICE = 'services.SyncService' 86 ACTIVATE_SUPER_NETWORK_SERVICE = 'services.SuperNetworkConfigurationService' 87 88 89class ActionTypeId(object): 90 """Andorid Action Type to trigger events.""" 91 MAIN = 'android.intent.action.MAIN' 92 MASTER_CLEAR_NOTIFICATION = 'android.intent.action.MASTER_CLEAR_NOTIFICATION' 93 TYCHO_ACTIVATE_SUPER_NETWORK = ( 94 'com.google.android.apps.tycho.ActionType.ACTIVATE_SUPER_NETWORK') 95 96 97class TelLiveProjectFiTest(TelephonyBaseTest): 98 def setup_class(self): 99 self.activation_attemps = self.user_params.get("activation_attemps", 3) 100 101 def _install_account_util(self, ad): 102 account_util = self.user_params["account_util"] 103 if isinstance(account_util, list): 104 account_util = account_util[0] 105 ad.log.info("Install account_util %s", account_util) 106 ad.ensure_screen_on() 107 ad.adb.install("-r %s" % account_util, timeout=300, ignore_status=True) 108 time.sleep(3) 109 if not ad.is_apk_installed("com.google.android.tradefed.account"): 110 ad.log.info("com.google.android.tradefed.account is not installed") 111 return False 112 return True 113 114 def _account_registration(self, ad): 115 toggle_airplane_mode_by_adb(self.log, ad, new_state=False) 116 for cmd in _TYCHO_VERBOSE_LOGGING_CMDS: 117 ad.adb.shell(cmd) 118 if hasattr(ad, "user_account"): 119 ad.exit_setup_wizard() 120 if not ad.is_apk_installed("com.google.android.tradefed.account" 121 ) and self.user_params.get( 122 "account_util"): 123 for _ in range(2): 124 if self._install_account_util(ad): 125 break 126 else: 127 ad.log.error( 128 "Fail to install com.google.android.tradefed.account") 129 return False 130 ad.force_stop_apk(_TYCHO_PKG) 131 if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid, 132 self.wifi_network_pass): 133 ad.log.error("Failed to connect to wifi") 134 return False 135 ad.log.info("Add google account") 136 if not add_google_account(ad): 137 ad.log.error("Failed to add google account") 138 return False 139 ad.adb.shell( 140 'am instrument -w -e account "%[email protected]" -e password ' 141 '"%s" -e sync true -e wait-for-checkin false ' 142 'com.google.android.tradefed.account/.AddAccount' % 143 (ad.user_account, ad.user_password)) 144 ad.log.info("Enable and activate tycho apk") 145 if not ad.is_apk_installed(_TYCHO_PKG): 146 ad.log.info("%s is not installed", _TYCHO_PKG) 147 return False 148 ad.adb.shell('pm enable %s' % _TYCHO_PKG) 149 # ad.adb.shell(_TYCHO_SERVER_LAB_OVERRIDE_CMD) 150 for i in range(1, self.activation_attemps + 1): 151 if i == self.activation_attemps: 152 ad.log.info("Reboot and try Fi activation again") 153 reboot_device(ad) 154 self.activate_fi_account(ad) 155 if not self.check_project_fi_activated(ad): 156 ad.log.error("Fail to activate Fi account on attempt-%s", 157 i) 158 if i == self.activation_attemps: 159 return False 160 else: 161 ad.log.info("Fi account is activated successfully") 162 break 163 elif "Fi Network" in ad.adb.getprop("gsm.sim.operator.alpha"): 164 ad.log.error("Google account is not provided for Fi Network") 165 return False 166 if not ensure_phone_subscription(self.log, ad): 167 ad.log.error("Unable to find a valid subscription!") 168 return False 169 refresh_droid_config(self.log, ad) 170 return True 171 172 def start_service(self, ad, package, service_id, extras, action_type): 173 """Starts the specified service. 174 175 Args: 176 ad: (android_device.AndroidDevice) device to start activity on 177 package: (str) the package to start the service from 178 service_id: (str) service to start 179 extras: (dict) extras needed to specify with the activity id 180 action_type: The action type id to create the intent 181 """ 182 ad.log.info('Starting service %s/.%s.', package, service_id) 183 intent = ad.droid.makeIntent(action_type, None, None, extras, 184 ['android.intent.category.DEFAULT'], 185 package, package + '.' + service_id, 186 _INTENT_FLAGS) 187 ad.droid.startServiceIntent(intent) 188 189 def start_activity(self, ad, package, activity_id, extras=None): 190 """Starts the specified activity. 191 192 Args: 193 ad: (android_device.AndroidDevice) device to start activity on 194 package: (str) the package to start 195 activity_id: (str) activity to start 196 extras: (dict) extras needed to specify with the activity id 197 """ 198 ad.log.info('Starting activity %s/.%s.', package, activity_id) 199 intent = ad.droid.makeIntent(ActionTypeId.MAIN, None, None, extras, 200 ['android.intent.category.LAUNCHER'], 201 package, package + '.' + activity_id, 202 _INTENT_FLAGS) 203 ad.droid.startActivityIntent(intent, False) 204 205 def activate_fi_account(self, ad): 206 """Start Tycho InitActivity. 207 208 For in-app Tycho activition (post-SUW tests), Tycho does not 209 automatically trigger OMADM process. This method is used to start 210 Tycho InitActivity before launching super network activation. 211 212 The device will finally stay on Sprint network if everything goes well. 213 214 Args: 215 ad: Android device need to start Tycho InitActivity. 216 """ 217 ad.force_stop_apk(_TYCHO_PKG) 218 ad.send_keycode("HOME") 219 extra = {'in_setup_wizard': False, 'force_show_account_chooser': False} 220 self.start_activity(ad, _TYCHO_PKG, TychoClassId.INIT_ACTIVITY, extra) 221 for _ in range(30): 222 ad.send_keycode("WAKEUP") 223 time.sleep(1) 224 current_window = ad.get_my_current_focus_window() 225 log_screen_shot(ad, self.test_name) 226 if ad.adb.shell( 227 "settings get global device_provisioning_mobile_data" 228 ) != "1": 229 ad.adb.shell( 230 "settings put global device_provisioning_mobile_data 1") 231 if 'SwitchConfirmDialogActivity' in current_window: 232 ad.log.info("In Switch Confirmation Dialog") 233 if ad.adb.getprop("ro.build.version.release")[0] not in ("8", 234 "O"): 235 ad.send_keycode("TAB") 236 ad.send_keycode("TAB") 237 ad.send_keycode("ENTER") 238 time.sleep(10) 239 elif 'tycho.InitActivity' in current_window: 240 ad.log.info("In Tycho InitActivity") 241 ad.send_keycode("TAB") 242 ad.send_keycode("TAB") 243 ad.send_keycode("ENTER") 244 time.sleep(10) 245 246 elif 'tycho.AccountChooserActivity' in current_window: 247 ad.send_keycode("ENTER") 248 else: 249 ad.log.info("Finished activation process") 250 return 251 252 def check_project_fi_activated(self, ad, retries=20): 253 for _ in range(retries): 254 if is_sim_ready(self.log, ad) and ( 255 ad.droid.telephonyGetSimOperatorName() == "Fi Network"): 256 ad.log.info("SIM state is READY, SIM operator is Fi") 257 return True 258 time.sleep(5) 259 260 def start_tycho_activation(self, ad): 261 """Start the Tycho client and register to cellular network. 262 263 Starts Tycho within SUW: 264 - Tycho is expected to follow the in-SUW work flow: 265 - Tycho will perform TychoInit, handshake to server, 266 account configuration, etc 267 - If successful, Tycho will trigger a switch to Sprint Network 268 - If successful, Tycho will start OMA-DM activation sessions 269 270 The device will finally stay on Sprint network if everything goes well. 271 272 Args: 273 ad: Android device need to start Tycho activation. 274 """ 275 extra = {'device_setup': True, 'has_account': True} 276 self.start_activity(ad, _TYCHO_PKG, TychoClassId.CARRIER_SETUP, extra) 277 278 def start_super_network_activation(self, ad): 279 """Start the Super-Network activation. 280 281 For in-app Tycho activition (post-SUW tests), this method starts 282 super-network activation after Tycho is initialized. 283 284 The device will finally stay on Sprint network if everything goes well. 285 286 Args: 287 ad: Android device need to start Tycho super network activation. 288 """ 289 extra = {'in_setup_wizard': False, 'is_interactive': True} 290 self.start_service(ad, _TYCHO_PKG, 291 TychoClassId.ACTIVATE_SUPER_NETWORK_SERVICE, extra, 292 ActionTypeId.TYCHO_ACTIVATE_SUPER_NETWORK) 293 294 def get_active_carrier(self, ad): 295 """Gets the active carrier profile value from the device. 296 297 Args: 298 ad: An AndroidDevice Object. 299 300 Returns: 301 (string) A key from the CARRIER_TO_MCC_MNC map representing the 302 active carrier. 303 304 Raises: 305 KeyError: when an mcc_mnc code reported by the device is not a 306 recognized Fi partner carrier. 307 """ 308 mcc_mnc = ad.droid.telephonyGetSimOperator() 309 if not mcc_mnc: 310 return "UNKNOWN" 311 try: 312 return operator_name_from_plmn_id(mcc_mnc) 313 except KeyError: 314 ad.log.error('Unknown Mobile Country Code/Mobile Network Code %s', 315 mcc_mnc) 316 raise 317 318 def switch_sim(self, ad): 319 """Requests switch between physical sim and esim. 320 321 Args: 322 ad: An AndroidDevice Object. 323 timeout: (optional -- integer) the number of seconds in which a 324 switch should be completed. 325 326 Raises: 327 Error: whenever a device is not set to the desired carrier within 328 the timeout window. 329 """ 330 old_sim_operator = ad.droid.telephonyGetSimOperatorName() 331 ad.log.info("Before SIM switch, SIM operator = %s", old_sim_operator) 332 send_dialer_secret_code(ad, "794824746") 333 time.sleep(10) 334 new_sim_operator = ad.droid.telephonyGetSimOperatorName() 335 ad.log.info("After SIM switch, SIM operator = %s", new_sim_operator) 336 refresh_droid_config(self.log, ad) 337 return old_sim_operator != new_sim_operator 338 339 def set_active_carrier(self, 340 ad, 341 carrier, 342 timeout=_MAX_WAIT_TIME, 343 check_interval=10): 344 """Requests an active carrier to be set on the device sim. 345 346 If switching to a different carrier, after the switch is completed 347 auto-switching will be disabled. To re-enable, call enable_auto_switching. 348 349 Args: 350 ad: An AndroidDevice Object. 351 carrier: (carrier_constants.Carrier) Which carrier to switch to. 352 timeout: (optional -- integer) the number of seconds in which a 353 switch should be completed. 354 355 Raises: 356 Error: whenever a device is not set to the desired carrier within 357 the timeout window. 358 """ 359 # If there's no need to switch, then don't. 360 max_time = timeout 361 while max_time >= 0: 362 if self.is_ready_to_make_carrier_switch(ad): 363 break 364 time.sleep(check_interval) 365 max_time -= check_interval 366 else: 367 ad.log.error("Device stays in carrier switch lock state") 368 return False 369 if carrier == CARRIER_AUTO: 370 send_dialer_secret_code(ad, _CARRIER_DIALER_CODE_LOOKUP[carrier]) 371 return True 372 old_carrier = self.get_active_carrier(ad) 373 if carrier == old_carrier: 374 ad.log.info('Already on %s, so no need to switch', carrier) 375 return True 376 377 # Start switch on device, using events to verify that the switch starts. 378 ad.log.info('Initiating unsolicited switch from %s to %s.', 379 old_carrier, carrier) 380 send_dialer_secret_code(ad, _CARRIER_DIALER_CODE_LOOKUP[carrier]) 381 return self.wait_for_carrier_switch_completed( 382 ad, carrier, timeout=timeout, check_interval=check_interval) 383 384 def is_switching_silent(self, ad): 385 """Checks if Tycho switching controller is in silent mode. 386 387 Note that silent mode is a sign of airplane mode, not of a switching lock. 388 389 Args: ad: An AndroidDevice Object. 390 391 Returns: 392 A Boolean True if the preferences file reports True, False otherwise. 393 """ 394 return "isInSilentMode\" value=\"true" in ad.adb.shell( 395 "cat %s | grep isInSilentMode" % _SWITCHING_PREF_FILE, 396 ignore_status=True) 397 398 def is_switching_locked(self, ad): 399 """Checks if Tycho switching controller is locked. 400 401 Args: ad: An AndroidDevice Object. 402 403 Returns: 404 A Boolean True if the switching controller is locked for any reason, 405 False otherwise. 406 """ 407 return "switchingInProgress\" value=\"true" in ad.adb.shell( 408 "cat %s | grep switchingInProgress" % _SWITCHING_PREF_FILE) 409 410 def is_ready_to_make_carrier_switch(self, ad): 411 """Checks if device is ready to make carrier switch. 412 413 Args: 414 ad: An AndroidDevice Object. 415 416 Returns: 417 A Boolean True if it is ready to make switch, False otherwise. 418 """ 419 # Check Tycho switching controller states. 420 if self.is_switching_silent(ad): 421 ad.log.info( 422 "Cannot make carrier switch: SwitchingController is in silent " 423 "mode!") 424 return False 425 if self.is_switching_locked(ad): 426 ad.log.info( 427 "Cannot make carrier switch: SwitchingController is locked!") 428 return False 429 if self.is_carrier_switch_in_progress(ad): 430 ad.log.info("Cannot make carrier switch: Switch in progress!") 431 return False 432 return True 433 434 def is_carrier_switch_in_progress(self, ad): 435 """Checks if Tycho says that a switch is currently in progress. 436 437 Args: 438 ad: An AndroidDevice Object. 439 440 Returns: 441 A Boolean True if the preferences file reports True, False otherwise. 442 """ 443 switching_preferences = ad.adb.shell("cat %s" % _SWITCHING_PREF_FILE) 444 return 'InProgress\" value=\"true' in switching_preferences 445 446 def check_network_carrier(self, ad, carrier): 447 current_carrier = self.get_active_carrier(ad) 448 ad.log.info("Current network carrier is %s", current_carrier) 449 is_in_switch = self.is_carrier_switch_in_progress(ad) 450 ad.log.info("Device in carrier switch progress mode") 451 return current_carrier == carrier and is_in_switch 452 453 def wait_for_carrier_switch_completed(self, 454 ad, 455 carrier, 456 timeout=_MAX_WAIT_TIME, 457 check_interval=10): 458 """Wait for carrier switch to complete. 459 460 This function waits for a carrier switch to complete by monitoring the 461 Tycho switching controller preference file. 462 463 Args: 464 ad: An Android device object. 465 carrier: The target carrier network to switch to. 466 timeout: (integer) Time wait for switch to complete. 467 468 Return: 469 True or False for successful/unsuccessful switch. 470 """ 471 check_args = [ad, carrier] 472 if wait_for_state(self.check_network_carrier, True, check_interval, 473 timeout, *check_args): 474 ad.log.info("Switched to %s successfully", carrier) 475 ad.send_keycode("ENTER") 476 return True 477 else: 478 active_carrier = self.get_active_carrier(ad) 479 if active_carrier == carrier: 480 ad.log.info("Switched to %s successfully", carrier) 481 return True 482 ad.log.error("Carrier is %s. Fail to switch to %s", active_carrier, 483 carrier) 484 return False 485 486 def operator_network_switch(self, ad, carrier): 487 if ad.droid.telephonyGetSimOperatorName() == "Fi Network": 488 for i in range(3): 489 if self.set_active_carrier(ad, carrier): 490 break 491 elif i == 2: 492 ad.log.error("Failed to switch to %s", carrier) 493 return False 494 if not ensure_phone_subscription(self.log, ad): 495 ad.log.error("Unable to find a valid subscription!") 496 return False 497 refresh_droid_config(self.log, ad) 498 return True 499 500 def network_switch_test(self, carrier): 501 tasks = [(self.operator_network_switch, [ad, carrier]) 502 for ad in self.android_devices] 503 if not multithread_func(self.log, tasks): 504 abort_all_tests(self.log, 505 "Unable to switch to network %s" % carrier) 506 return True 507 508 """ Tests Begin """ 509 510 @test_tracker_info(uuid="4d92318e-4980-471a-882b-3136c5dda384") 511 @TelephonyBaseTest.tel_test_wrap 512 def test_project_fi_account_activation(self): 513 """Test activate Fi account. 514 515 Returns: 516 True if success. 517 False if failed. 518 """ 519 tasks = [(self._account_registration, [ad]) 520 for ad in self.android_devices] 521 try: 522 if not multithread_func(self.log, tasks): 523 abort_all_tests(self.log, "Unable to activate Fi account!") 524 except Exception as e: 525 self.log.error(e) 526 abort_all_tests(self.log, "Unable to activate Fi account!") 527 return True 528 529 @test_tracker_info(uuid="6bfbcc1d-e318-4964-bf36-5b82f086860d") 530 @TelephonyBaseTest.tel_test_wrap 531 def test_switch_to_tmobile_network(self): 532 """Test switch to tmobile network. 533 534 Returns: 535 True if success. 536 False if failed. 537 """ 538 return self.network_switch_test(CARRIER_TMO) 539 540 @test_tracker_info(uuid="4f27944d-f3c5-423d-b0c5-5c66dbb98376") 541 @TelephonyBaseTest.tel_test_wrap 542 def test_switch_to_sprint_network(self): 543 """Test switch to tmobile network. 544 545 Returns: 546 True if success. 547 False if failed. 548 """ 549 return self.network_switch_test(CARRIER_SPT) 550 551 @test_tracker_info(uuid="5f30c9bd-b79e-4805-aa46-7855ed9023f0") 552 @TelephonyBaseTest.tel_test_wrap 553 def test_switch_to_uscc_network(self): 554 """Test switch to tmobile network. 555 556 Returns: 557 True if success. 558 False if failed. 559 """ 560 return self.network_switch_test(CARRIER_USCC) 561 562 @test_tracker_info(uuid="0b062751-d59d-420e-941e-3ffa02aea0d5") 563 @TelephonyBaseTest.tel_test_wrap 564 def test_switch_to_auto_network(self): 565 """Test switch to auto network selection. 566 567 Returns: 568 True if success. 569 False if failed. 570 """ 571 return self.network_switch_test(CARRIER_AUTO) 572 573 @test_tracker_info(uuid="13c5f080-69bf-42fd-86ed-c67b1984c347") 574 @TelephonyBaseTest.tel_test_wrap 575 def test_switch_between_sim(self): 576 """Test switch between physical sim and esim. 577 578 Returns: 579 True if success. 580 False if failed. 581 """ 582 for ad in self.android_devices: 583 self.switch_sim(ad) 584 585 @test_tracker_info(uuid="") 586 @TelephonyBaseTest.tel_test_wrap 587 def test_remove_google_account(self): 588 for ad in self.android_devices: 589 remove_google_account(ad) 590 591 592""" Tests End """ 593