blob: c151811b5de8995824ca046bc98ae03ffc85cb3e [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright 2016 - The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Fi Switching Methods
"""
import time
from acts.libs.utils.multithread import multithread_func
from acts.controllers.anritsu_lib._anritsu_utils import AnritsuError
from acts.controllers.anritsu_lib.md8475a import MD8475A
from acts_contrib.test_utils.tel.anritsu_utils import cb_serial_number
from acts_contrib.test_utils.tel.anritsu_utils import set_system_model_lte
from acts_contrib.test_utils.tel.anritsu_utils import set_usim_parameters
from acts_contrib.test_utils.tel.anritsu_utils import set_post_sim_params
from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_LTE_GSM_WCDMA
from acts_contrib.test_utils.tel.tel_defines import RAT_FAMILY_LTE
from acts.test_decorators import test_tracker_info
from acts_contrib.test_utils.tel.tel_defines import RAT_LTE
from acts_contrib.test_utils.tel.tel_defines import CARRIER_SPT
from acts_contrib.test_utils.tel.tel_defines import CARRIER_TMO
from acts_contrib.test_utils.tel.tel_defines import CARRIER_USCC
from acts_contrib.test_utils.tel.tel_logging_utils import log_screen_shot
from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_loggers
from acts_contrib.test_utils.tel.tel_lookup_tables import operator_name_from_plmn_id
from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phone_subscription
from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_preferred_network_type_for_subscription
from acts_contrib.test_utils.tel.tel_test_utils import abort_all_tests
from acts_contrib.test_utils.tel.tel_test_utils import is_sim_ready
from acts_contrib.test_utils.tel.tel_test_utils import reboot_device
from acts_contrib.test_utils.tel.tel_test_utils import refresh_droid_config
from acts_contrib.test_utils.tel.tel_test_utils import send_dialer_secret_code
from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode_by_adb
from acts_contrib.test_utils.tel.tel_test_utils import wait_for_state
from acts_contrib.test_utils.tel.tel_test_utils import add_google_account
from acts_contrib.test_utils.tel.tel_test_utils import remove_google_account
from acts_contrib.test_utils.tel.tel_wifi_utils import ensure_wifi_connected
WAIT_TIME_BETWEEN_REG_AND_MSG = 15 # default 15 sec
CARRIER = None
CARRIER_AUTO = "auto"
_CARRIER_DIALER_CODE_LOOKUP = {
CARRIER_AUTO: '342886',
CARRIER_SPT: '34777',
CARRIER_TMO: '34866',
CARRIER_USCC: '34872'
}
_SWITCHING_PREF_FILE = (
'/data/data/com.google.android.apps.tycho/shared_prefs/switching.xml')
_INTENT_FLAGS = int(0x00008000 | 0x10000000 | 0x00080000 | 0x00020000)
_TYCHO_PKG = 'com.google.android.apps.tycho'
_MAX_WAIT_TIME = 120
_TYCHO_VERBOSE_LOGGING_CMDS = [
"setprop log.tag.Tycho VERBOSE",
"CLASSPATH=/system/framework/am.jar su root app_process "
"/system/bin com.android.commands.am.Am broadcast -a "
"com.google.gservices.intent.action.GSERVICES_OVERRIDE "
"-e tycho.enable_request_logging true",
"CLASSPATH=/system/framework/am.jar su root app_process "
"/system/bin com.android.commands.am.Am broadcast -a "
"com.google.gservices.intent.action.GSERVICES_OVERRIDE "
"-e tycho.enable_sensitive_logging true",
"CLASSPATH=/system/framework/am.jar su root app_process "
"/system/bin com.android.commands.am.Am broadcast -a "
"com.google.gservices.intent.action.GSERVICES_OVERRIDE "
"-e tycho.enable_ample_logging true"
]
_TYCHO_SERVER_LAB_OVERRIDE_CMD = (
"am broadcast -a com.google.gservices.intent.action.GSERVICES_OVERRIDE -e "
"url:tycho_server_endpoint https://android.googleapis.com/nova/nfe/ rewrite"
" https://android.googleapis.com/lab/nova/nfe/")
class TychoClassId(object):
"""Tycho Activity/Service Classnames."""
# Activities
CARRIER_SETUP = 'CarrierSetupEntryPointTrampoline'
INIT_ACTIVITY = 'InitActivity'
# Services
SYNC_SERVICE = 'services.SyncService'
ACTIVATE_SUPER_NETWORK_SERVICE = 'services.SuperNetworkConfigurationService'
class ActionTypeId(object):
"""Andorid Action Type to trigger events."""
MAIN = 'android.intent.action.MAIN'
MASTER_CLEAR_NOTIFICATION = 'android.intent.action.MASTER_CLEAR_NOTIFICATION'
TYCHO_ACTIVATE_SUPER_NETWORK = (
'com.google.android.apps.tycho.ActionType.ACTIVATE_SUPER_NETWORK')
class TelLabProjectFiTest(TelephonyBaseTest):
SERIAL_NO = cb_serial_number()
def setup_class(self):
super().setup_class()
self.ad = self.android_devices[0]
self.ad.sim_card = getattr(self.ad, "sim_card", None)
self.md8475a_ip_address = self.user_params[
"anritsu_md8475a_ip_address"]
self.wlan_option = self.user_params.get("anritsu_wlan_option", False)
self.md8475_version = self.user_params.get("md8475", "A")
self.ad.adb.shell("settings put secure cmas_additional_broadcast_pkg "
"com.googlecode.android_scripting")
self.wait_time_between_reg_and_msg = self.user_params.get(
"wait_time_between_reg_and_msg", WAIT_TIME_BETWEEN_REG_AND_MSG)
try:
self.anritsu = MD8475A(self.md8475a_ip_address, self.wlan_option,
self.md8475_version)
except AnritsuError:
self.log.error("Error in connecting to Anritsu Simulator")
return False
self.activation_attemps = self.user_params.get("activation_attemps", 3)
return True
def setup_test(self):
if getattr(self, "qxdm_log", True):
start_qxdm_loggers(self.log, self.android_devices)
ensure_phones_idle(self.log, self.android_devices)
toggle_airplane_mode(self.log, self.ad, True)
return True
def teardown_test(self):
self.log.info("Stopping Simulation")
self.anritsu.stop_simulation()
toggle_airplane_mode(self.log, self.ad, True)
def teardown_class(self):
self.anritsu.disconnect()
return True
def _bring_up_callbox(
self,
set_simulation_func,
rat):
try:
[self.bts1] = set_simulation_func(self.anritsu, self.user_params,
self.ad.sim_card)
set_usim_parameters(self.anritsu, self.ad.sim_card)
if rat == RAT_LTE:
set_post_sim_params(self.anritsu, self.user_params,
self.ad.sim_card)
self.anritsu.start_simulation()
if rat == RAT_LTE:
preferred_network_setting = NETWORK_MODE_LTE_GSM_WCDMA
rat_family = RAT_FAMILY_LTE
else:
self.log.error("No valid RAT provided to bring up callbox.")
return False
if not ensure_preferred_network_type_for_subscription(
self.ad,
preferred_network_setting):
self.log.error(
"Failed to set rat family {}, preferred network:{}".format(
rat_family, preferred_network_setting))
return False
if self.ad.droid.connectivityCheckAirplaneMode():
toggle_airplane_mode(self.log, self.ad, False)
except AnritsuError as e:
self.log.error("Error in connection with Anritsu Simulator: " +
str(e))
return False
return True
def pre_switching_callbox_setup(self):
""" Setup environment to enable carrier switching
Returns:
True if pass; False if fail
"""
return self._bring_up_callbox(set_system_model_lte, RAT_LTE)
def _install_account_util(self, ad):
account_util = self.user_params["account_util"]
if isinstance(account_util, list):
account_util = account_util[0]
ad.log.info("Install account_util %s", account_util)
ad.ensure_screen_on()
ad.adb.install("-r %s" % account_util, timeout=300, ignore_status=True)
time.sleep(3)
if not ad.is_apk_installed("com.google.android.tradefed.account"):
ad.log.info("com.google.android.tradefed.account is not installed")
return False
return True
def _account_registration(self, ad):
toggle_airplane_mode_by_adb(self.log, ad, new_state=False)
for cmd in _TYCHO_VERBOSE_LOGGING_CMDS:
ad.adb.shell(cmd)
if hasattr(ad, "user_account"):
ad.exit_setup_wizard()
if not ad.is_apk_installed("com.google.android.tradefed.account"
) and \
self.user_params.get("account_util"):
for _ in range(2):
if self._install_account_util(ad):
break
else:
ad.log.error(
"Fail to install com.google.android.tradefed.account")
return False
ad.force_stop_apk(_TYCHO_PKG)
if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid,
self.wifi_network_pass):
ad.log.error("Failed to connect to wifi")
return False
ad.log.info("Add google account")
if not add_google_account(ad):
ad.log.error("Failed to add google account")
return False
ad.adb.shell(
'am instrument -w -e account "%s@gmail.com" -e password '
'"%s" -e sync true -e wait-for-checkin false '
'com.google.android.tradefed.account/.AddAccount' %
(ad.user_account, ad.user_password))
ad.log.info("Enable and activate tycho apk")
if not ad.is_apk_installed(_TYCHO_PKG):
ad.log.info("%s is not installed", _TYCHO_PKG)
return False
ad.adb.shell('pm enable %s' % _TYCHO_PKG)
# ad.adb.shell(_TYCHO_SERVER_LAB_OVERRIDE_CMD)
for i in range(1, self.activation_attemps + 1):
if i == self.activation_attemps:
ad.log.info("Reboot and try Fi activation again")
reboot_device(ad)
self.activate_fi_account(ad)
if not self.check_project_fi_activated(ad):
ad.log.error("Fail to activate Fi account on attempt-%s",
i)
if i == self.activation_attemps:
return False
else:
ad.log.info("Fi account is activated successfully")
break
elif "Fi Network" in ad.adb.getprop("gsm.sim.operator.alpha"):
ad.log.error("Google account is not provided for Fi Network")
return False
if not ensure_phone_subscription(self.log, ad):
ad.log.error("Unable to find a valid subscription!")
return False
refresh_droid_config(self.log, ad)
return True
def start_service(self, ad, package, service_id, extras, action_type):
"""Starts the specified service.
Args:
ad: (android_device.AndroidDevice) device to start activity on
package: (str) the package to start the service from
service_id: (str) service to start
extras: (dict) extras needed to specify with the activity id
action_type: The action type id to create the intent
"""
ad.log.info('Starting service %s/.%s.', package, service_id)
intent = ad.droid.makeIntent(action_type, None, None, extras,
['android.intent.category.DEFAULT'],
package, package + '.' + service_id,
_INTENT_FLAGS)
ad.droid.startServiceIntent(intent)
def start_activity(self, ad, package, activity_id, extras=None):
"""Starts the specified activity.
Args:
ad: (android_device.AndroidDevice) device to start activity on
package: (str) the package to start
activity_id: (str) activity to start
extras: (dict) extras needed to specify with the activity id
"""
ad.log.info('Starting activity %s/.%s.', package, activity_id)
intent = ad.droid.makeIntent(ActionTypeId.MAIN, None, None, extras,
['android.intent.category.LAUNCHER'],
package, package + '.' + activity_id,
_INTENT_FLAGS)
ad.droid.startActivityIntent(intent, False)
def activate_fi_account(self, ad):
"""Start Tycho InitActivity.
For in-app Tycho activition (post-SUW tests), Tycho does not
automatically trigger OMADM process. This method is used to start
Tycho InitActivity before launching super network activation.
The device will finally stay on Sprint network if everything goes well.
Args:
ad: Android device need to start Tycho InitActivity.
"""
ad.force_stop_apk(_TYCHO_PKG)
ad.send_keycode("HOME")
extra = {'in_setup_wizard': False, 'force_show_account_chooser': False}
self.start_activity(ad, _TYCHO_PKG, TychoClassId.INIT_ACTIVITY, extra)
for _ in range(30):
ad.send_keycode("WAKEUP")
time.sleep(1)
current_window = ad.get_my_current_focus_window()
log_screen_shot(ad, self.test_name)
if ad.adb.shell(
"settings get global device_provisioning_mobile_data"
) != "1":
ad.adb.shell(
"settings put global device_provisioning_mobile_data 1")
if 'SwitchConfirmDialogActivity' in current_window:
ad.log.info("In Switch Confirmation Dialog")
if ad.adb.getprop("ro.build.version.release")[0] not in ("8",
"O"):
ad.send_keycode("TAB")
ad.send_keycode("TAB")
ad.send_keycode("ENTER")
time.sleep(10)
elif 'tycho.InitActivity' in current_window:
ad.log.info("In Tycho InitActivity")
ad.send_keycode("TAB")
ad.send_keycode("TAB")
ad.send_keycode("ENTER")
time.sleep(10)
elif 'tycho.AccountChooserActivity' in current_window:
ad.send_keycode("ENTER")
else:
ad.log.info("Finished activation process")
return
def check_project_fi_activated(self, ad, retries=20):
for _ in range(retries):
if is_sim_ready(self.log, ad) and (
ad.droid.telephonyGetSimOperatorName() == "Fi Network"):
ad.log.info("SIM state is READY, SIM operator is Fi")
return True
time.sleep(5)
def start_tycho_activation(self, ad):
"""Start the Tycho client and register to cellular network.
Starts Tycho within SUW:
- Tycho is expected to follow the in-SUW work flow:
- Tycho will perform TychoInit, handshake to server,
account configuration, etc
- If successful, Tycho will trigger a switch to Sprint Network
- If successful, Tycho will start OMA-DM activation sessions
The device will finally stay on Sprint network if everything goes well.
Args:
ad: Android device need to start Tycho activation.
"""
extra = {'device_setup': True, 'has_account': True}
self.start_activity(ad, _TYCHO_PKG, TychoClassId.CARRIER_SETUP, extra)
def start_super_network_activation(self, ad):
"""Start the Super-Network activation.
For in-app Tycho activition (post-SUW tests), this method starts
super-network activation after Tycho is initialized.
The device will finally stay on Sprint network if everything goes well.
Args:
ad: Android device need to start Tycho super network activation.
"""
extra = {'in_setup_wizard': False, 'is_interactive': True}
self.start_service(ad, _TYCHO_PKG,
TychoClassId.ACTIVATE_SUPER_NETWORK_SERVICE, extra,
ActionTypeId.TYCHO_ACTIVATE_SUPER_NETWORK)
def get_active_carrier(self, ad):
"""Gets the active carrier profile value from the device.
Args:
ad: An AndroidDevice Object.
Returns:
(string) A key from the CARRIER_TO_MCC_MNC map representing the
active carrier.
Raises:
KeyError: when an mcc_mnc code reported by the device is not a
recognized Fi partner carrier.
"""
mcc_mnc = ad.droid.telephonyGetSimOperator()
if not mcc_mnc:
return "UNKNOWN"
try:
return operator_name_from_plmn_id(mcc_mnc)
except KeyError:
ad.log.error('Unknown Mobile Country Code/Mobile Network Code %s',
mcc_mnc)
raise
def switch_sim(self, ad):
"""Requests switch between physical sim and esim.
Args:
ad: An AndroidDevice Object.
timeout: (optional -- integer) the number of seconds in which a
switch should be completed.
Raises:
Error: whenever a device is not set to the desired carrier within
the timeout window.
"""
old_sim_operator = ad.droid.telephonyGetSimOperatorName()
ad.log.info("Before SIM switch, SIM operator = %s", old_sim_operator)
send_dialer_secret_code(ad, "794824746")
time.sleep(10)
new_sim_operator = ad.droid.telephonyGetSimOperatorName()
ad.log.info("After SIM switch, SIM operator = %s", new_sim_operator)
refresh_droid_config(self.log, ad)
return old_sim_operator != new_sim_operator
def set_active_carrier(self,
ad,
carrier,
timeout=_MAX_WAIT_TIME,
check_interval=10):
"""Requests an active carrier to be set on the device sim.
If switching to a different carrier, after the switch is completed
auto-switching will be disabled. To re-enable, call
enable_auto_switching.
Args:
ad: An AndroidDevice Object.
carrier: (carrier_constants.Carrier) Which carrier to switch to.
timeout: (optional -- integer) the number of seconds in which a
switch should be completed.
Raises:
Error: whenever a device is not set to the desired carrier within
the timeout window.
"""
# If there's no need to switch, then don't.
if self.pre_switching_callbox_setup():
self.log.info("Turned ON Anritsu for Switching")
pass
else:
self.log.error("Failed to Camp to Anritsu")
return False
max_time = timeout
while max_time >= 0:
if self.is_ready_to_make_carrier_switch(ad):
break
time.sleep(check_interval)
max_time -= check_interval
else:
ad.log.error("Device stays in carrier switch lock state")
return False
if carrier == CARRIER_AUTO:
send_dialer_secret_code(ad, _CARRIER_DIALER_CODE_LOOKUP[carrier])
return True
old_carrier = self.get_active_carrier(ad)
if carrier == old_carrier:
ad.log.info('Already on %s, so no need to switch', carrier)
return True
# Start switch on device, using events to verify that the switch starts.
ad.log.info('Initiating unsolicited switch from %s to %s.',
old_carrier, carrier)
send_dialer_secret_code(ad, _CARRIER_DIALER_CODE_LOOKUP[carrier])
return self.wait_for_carrier_switch_completed(
ad, carrier, timeout=timeout, check_interval=check_interval)
def is_switching_silent(self, ad):
"""Checks if Tycho switching controller is in silent mode.
Note that silent mode is a sign of airplane mode, not of a switching \
lock.
Args: ad: An AndroidDevice Object.
Returns:
A Boolean True if the preferences file reports True, False
otherwise.
"""
return "isInSilentMode\" value=\"true" in ad.adb.shell(
"cat %s | grep isInSilentMode" % _SWITCHING_PREF_FILE,
ignore_status=True)
def is_switching_locked(self, ad):
"""Checks if Tycho switching controller is locked.
Args: ad: An AndroidDevice Object.
Returns:
A Boolean True if the switching controller is locked for any reason,
False otherwise.
"""
return "switchingInProgress\" value=\"true" in ad.adb.shell(
"cat %s | grep switchingInProgress" % _SWITCHING_PREF_FILE)
def is_ready_to_make_carrier_switch(self, ad):
"""Checks if device is ready to make carrier switch.
Args:
ad: An AndroidDevice Object.
Returns:
A Boolean True if it is ready to make switch, False otherwise.
"""
# Check Tycho switching controller states.
if self.is_switching_silent(ad):
ad.log.info(
"Cannot make carrier switch: SwitchingController is in silent "
"mode!")
return False
if self.is_switching_locked(ad):
ad.log.info(
"Cannot make carrier switch: SwitchingController is locked!")
return False
if self.is_carrier_switch_in_progress(ad):
ad.log.info("Cannot make carrier switch: Switch in progress!")
return False
return True
def is_carrier_switch_in_progress(self, ad):
"""Checks if Tycho says that a switch is currently in progress.
Args:
ad: An AndroidDevice Object.
Returns:
A Boolean True if the preferences file reports True, False
otherwise.
"""
switching_preferences = ad.adb.shell("cat %s" % _SWITCHING_PREF_FILE)
return 'InProgress\" value=\"true' in switching_preferences
def check_network_carrier(self, ad, carrier):
current_carrier = self.get_active_carrier(ad)
ad.log.info("Current network carrier is %s", current_carrier)
is_in_switch = self.is_carrier_switch_in_progress(ad)
ad.log.info("Device in carrier switch progress mode")
return current_carrier == carrier and is_in_switch
def wait_for_carrier_switch_completed(self,
ad,
carrier,
timeout=_MAX_WAIT_TIME,
check_interval=10):
"""Wait for carrier switch to complete.
This function waits for a carrier switch to complete by monitoring the
Tycho switching controller preference file.
Args:
ad: An Android device object.
carrier: The target carrier network to switch to.
timeout: (integer) Time wait for switch to complete.
Return:
True or False for successful/unsuccessful switch.
"""
check_args = [ad, carrier]
if wait_for_state(self.check_network_carrier, True, check_interval,
timeout, *check_args):
ad.log.info("Switched to %s successfully", carrier)
ad.send_keycode("ENTER")
return True
else:
active_carrier = self.get_active_carrier(ad)
if active_carrier == carrier:
ad.log.info("Switched to %s successfully", carrier)
return True
ad.log.error("Carrier is %s. Fail to switch to %s", active_carrier,
carrier)
return False
def operator_network_switch(self, ad, carrier):
if ad.droid.telephonyGetSimOperatorName() == "Google Fi":
for i in range(3):
if self.set_active_carrier(ad, carrier):
break
elif i == 2:
ad.log.error("Failed to switch to %s", carrier)
return False
if not ensure_phone_subscription(self.log, ad):
ad.log.error("Unable to find a valid subscription!")
return False
refresh_droid_config(self.log, ad)
return True
def network_switch_test(self, carrier):
tasks = [(self.operator_network_switch, [ad, carrier])
for ad in self.android_devices]
if not multithread_func(self.log, tasks):
abort_all_tests(self.log,
"Unable to switch to network %s" % carrier)
return True
""" Tests Begin """
@test_tracker_info(uuid="4d92318e-4980-471a-882b-3136c5dda384")
@TelephonyBaseTest.tel_test_wrap
def test_project_fi_account_activation(self):
"""Test activate Fi account.
Returns:
True if success.
False if failed.
"""
tasks = [(self._account_registration, [ad])
for ad in self.android_devices]
try:
if not multithread_func(self.log, tasks):
abort_all_tests(self.log, "Unable to activate Fi account!")
except Exception as e:
self.log.error(e)
abort_all_tests(self.log, "Unable to activate Fi account!")
return True
@test_tracker_info(uuid="6bfbcc1d-e318-4964-bf36-5b82f086860d")
@TelephonyBaseTest.tel_test_wrap
def test_switch_to_tmobile_network(self):
"""Test switch to tmobile network.
Returns:
True if success.
False if failed.
"""
setattr(self.ad, "sim_card", "FiTMO")
return self.network_switch_test(CARRIER_TMO)
@test_tracker_info(uuid="4f27944d-f3c5-423d-b0c5-5c66dbb98376")
@TelephonyBaseTest.tel_test_wrap
def test_switch_to_sprint_network(self):
"""Test switch to sprint network.
Returns:
True if success.
False if failed.
"""
setattr(self.ad, "sim_card", "FiSPR")
return self.network_switch_test(CARRIER_SPT)
@test_tracker_info(uuid="5f30c9bd-b79e-4805-aa46-7855ed9023f0")
@TelephonyBaseTest.tel_test_wrap
def test_switch_to_uscc_network(self):
"""Test switch to uscc network.
Returns:
True if success.
False if failed.
"""
setattr(self.ad, "sim_card", "FiUSCC")
return self.network_switch_test(CARRIER_USCC)
@test_tracker_info(uuid="0b062751-d59d-420e-941e-3ffa02aea0d5")
@TelephonyBaseTest.tel_test_wrap
def test_switch_to_auto_network(self):
"""Test switch to auto network selection.
Returns:
True if success.
False if failed.
"""
return self.network_switch_test(CARRIER_AUTO)
@test_tracker_info(uuid="13c5f080-69bf-42fd-86ed-c67b1984c347")
@TelephonyBaseTest.tel_test_wrap
def test_switch_between_sim(self):
"""Test switch between physical sim and esim.
Returns:
True if success.
False if failed.
"""
for ad in self.android_devices:
self.switch_sim(ad)
@test_tracker_info(uuid="")
@TelephonyBaseTest.tel_test_wrap
def test_remove_google_account(self):
for ad in self.android_devices:
remove_google_account(ad)
""" Tests End """