• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3#   Copyright 2022 - 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
17from future import standard_library
18standard_library.install_aliases()
19
20import json
21import logging
22import re
23import os
24import urllib.parse
25import time
26import acts.controllers.iperf_server as ipf
27import struct
28
29from acts import signals
30from queue import Empty
31from acts.asserts import abort_all
32from acts.controllers.adb_lib.error import AdbCommandError, AdbError
33from acts.controllers.android_device import list_adb_devices
34from acts.controllers.android_device import list_fastboot_devices
35
36from acts.libs.proc.job import TimeoutError
37from acts_contrib.test_utils.tel.loggers.protos.telephony_metric_pb2 import TelephonyVoiceTestResult
38from acts_contrib.test_utils.tel.tel_defines import CarrierConfigs
39from acts_contrib.test_utils.tel.tel_defines import AOSP_PREFIX
40from acts_contrib.test_utils.tel.tel_defines import CARD_POWER_DOWN
41from acts_contrib.test_utils.tel.tel_defines import CARD_POWER_UP
42from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_CONFERENCE
43from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_VOLTE
44from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_VOLTE_PROVISIONING
45from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_VOLTE_OVERRIDE_WFC_PROVISIONING
46from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_HIDE_ENHANCED_4G_LTE_BOOL
47from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_VT
48from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_WFC
49from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_WFC_MODE_CHANGE
50from acts_contrib.test_utils.tel.tel_defines import CARRIER_UNKNOWN
51from acts_contrib.test_utils.tel.tel_defines import COUNTRY_CODE_LIST
52from acts_contrib.test_utils.tel.tel_defines import DIALER_PACKAGE_NAME
53from acts_contrib.test_utils.tel.tel_defines import DATA_ROAMING_ENABLE
54from acts_contrib.test_utils.tel.tel_defines import DATA_ROAMING_DISABLE
55from acts_contrib.test_utils.tel.tel_defines import GEN_4G
56from acts_contrib.test_utils.tel.tel_defines import GEN_UNKNOWN
57from acts_contrib.test_utils.tel.tel_defines import INVALID_SIM_SLOT_INDEX
58from acts_contrib.test_utils.tel.tel_defines import INVALID_SUB_ID
59from acts_contrib.test_utils.tel.tel_defines import MAX_SCREEN_ON_TIME
60from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_AIRPLANEMODE_EVENT
61from acts_contrib.test_utils.tel.tel_defines import MESSAGE_PACKAGE_NAME
62from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA
63from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_VOICE
64from acts_contrib.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_7_DIGIT
65from acts_contrib.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_10_DIGIT
66from acts_contrib.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_11_DIGIT
67from acts_contrib.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_12_DIGIT
68from acts_contrib.test_utils.tel.tel_defines import RAT_UNKNOWN
69from acts_contrib.test_utils.tel.tel_defines import SERVICE_STATE_EMERGENCY_ONLY
70from acts_contrib.test_utils.tel.tel_defines import SERVICE_STATE_IN_SERVICE
71from acts_contrib.test_utils.tel.tel_defines import SERVICE_STATE_MAPPING
72from acts_contrib.test_utils.tel.tel_defines import SERVICE_STATE_OUT_OF_SERVICE
73from acts_contrib.test_utils.tel.tel_defines import SERVICE_STATE_POWER_OFF
74from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_ABSENT
75from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_LOADED
76from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_NOT_READY
77from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_PIN_REQUIRED
78from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_READY
79from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_UNKNOWN
80from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
81from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_STATE_CHECK
82from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_FOR_STATE_CHANGE
83from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_SYNC_DATE_TIME_FROM_NETWORK
84from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
85from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_ONLY
86from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
87from acts_contrib.test_utils.tel.tel_defines import EventActiveDataSubIdChanged
88from acts_contrib.test_utils.tel.tel_defines import EventDisplayInfoChanged
89from acts_contrib.test_utils.tel.tel_defines import EventServiceStateChanged
90from acts_contrib.test_utils.tel.tel_defines import NetworkCallbackContainer
91from acts_contrib.test_utils.tel.tel_defines import ServiceStateContainer
92from acts_contrib.test_utils.tel.tel_defines import DisplayInfoContainer
93from acts_contrib.test_utils.tel.tel_defines import OverrideNetworkContainer
94from acts_contrib.test_utils.tel.tel_logging_utils import disable_qxdm_logger
95from acts_contrib.test_utils.tel.tel_logging_utils import get_screen_shot_log
96from acts_contrib.test_utils.tel.tel_logging_utils import log_screen_shot
97from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_logger
98from acts_contrib.test_utils.tel.tel_lookup_tables import connection_type_from_type_string
99from acts_contrib.test_utils.tel.tel_lookup_tables import is_valid_rat
100from acts_contrib.test_utils.tel.tel_lookup_tables import get_allowable_network_preference
101from acts_contrib.test_utils.tel.tel_lookup_tables import get_voice_mail_count_check_function
102from acts_contrib.test_utils.tel.tel_lookup_tables import get_voice_mail_check_number
103from acts_contrib.test_utils.tel.tel_lookup_tables import network_preference_for_generation
104from acts_contrib.test_utils.tel.tel_lookup_tables import operator_name_from_network_name
105from acts_contrib.test_utils.tel.tel_lookup_tables import operator_name_from_plmn_id
106from acts_contrib.test_utils.tel.tel_lookup_tables import rat_family_from_rat
107from acts_contrib.test_utils.tel.tel_lookup_tables import rat_generation_from_rat
108from acts_contrib.test_utils.tel.tel_subscription_utils import get_slot_index_from_subid
109from acts_contrib.test_utils.tel.tel_subscription_utils import get_subid_by_adb
110from acts_contrib.test_utils.tel.tel_subscription_utils import get_subid_from_slot_index
111from acts_contrib.test_utils.tel.tel_subscription_utils import get_outgoing_voice_sub_id
112from acts_contrib.test_utils.tel.tel_subscription_utils import get_incoming_voice_sub_id
113from acts_contrib.test_utils.tel.tel_subscription_utils import set_incoming_voice_sub_id
114from acts.utils import adb_shell_ping
115from acts.utils import load_config
116from acts.logger import epoch_to_log_line_timestamp
117from acts.utils import get_current_epoch_time
118from acts.utils import exe_cmd
119
120log = logging
121STORY_LINE = "+19523521350"
122CallResult = TelephonyVoiceTestResult.CallResult.Value
123
124
125class TelResultWrapper(object):
126    """Test results wrapper for Telephony test utils.
127
128    In order to enable metrics reporting without refactoring
129    all of the test utils this class is used to keep the
130    current return boolean scheme in tact.
131    """
132
133    def __init__(self, result_value):
134        self._result_value = result_value
135
136    @property
137    def result_value(self):
138        return self._result_value
139
140    @result_value.setter
141    def result_value(self, result_value):
142        self._result_value = result_value
143
144    def __bool__(self):
145        return self._result_value == CallResult('SUCCESS')
146
147
148def abort_all_tests(log, msg):
149    log.error("Aborting all ongoing tests due to: %s.", msg)
150    abort_all(msg)
151
152
153def get_phone_number_by_adb(ad):
154    return phone_number_formatter(
155        ad.adb.shell("service call iphonesubinfo 13"))
156
157
158def get_iccid_by_adb(ad):
159    return ad.adb.shell("service call iphonesubinfo 11")
160
161
162def get_operator_by_adb(ad):
163    operator = ad.adb.getprop("gsm.sim.operator.alpha")
164    if "," in operator:
165        operator = operator.strip()[0]
166    return operator
167
168
169def get_plmn_by_adb(ad):
170    plmn_id = ad.adb.getprop("gsm.sim.operator.numeric")
171    if "," in plmn_id:
172        plmn_id = plmn_id.strip()[0]
173    return plmn_id
174
175
176def get_sub_id_by_adb(ad):
177    return ad.adb.shell("service call iphonesubinfo 5")
178
179
180def setup_droid_properties_by_adb(log, ad, sim_filename=None):
181
182    sim_data = None
183    if sim_filename:
184        try:
185            sim_data = load_config(sim_filename)
186        except Exception:
187            log.warning("Failed to load %s!", sim_filename)
188
189    sub_id = get_sub_id_by_adb(ad)
190    iccid = get_iccid_by_adb(ad)
191    ad.log.info("iccid = %s", iccid)
192    if sim_data.get(iccid) and sim_data[iccid].get("phone_num"):
193        phone_number = phone_number_formatter(sim_data[iccid]["phone_num"])
194    else:
195        phone_number = get_phone_number_by_adb(ad)
196        if not phone_number and hasattr(ad, phone_number):
197            phone_number = ad.phone_number
198    if not phone_number:
199        ad.log.error("Failed to find valid phone number for %s", iccid)
200        abort_all_tests(ad.log, "Failed to find valid phone number for %s")
201    sub_record = {
202        'phone_num': phone_number,
203        'iccid': get_iccid_by_adb(ad),
204        'sim_operator_name': get_operator_by_adb(ad),
205        'operator': operator_name_from_plmn_id(get_plmn_by_adb(ad))
206    }
207    device_props = {'subscription': {sub_id: sub_record}}
208    ad.log.info("subId %s SIM record: %s", sub_id, sub_record)
209    setattr(ad, 'telephony', device_props)
210
211
212def setup_droid_properties(log, ad, sim_filename=None):
213
214    if ad.skip_sl4a:
215        return setup_droid_properties_by_adb(
216            log, ad, sim_filename=sim_filename)
217    refresh_droid_config(log, ad)
218    sim_data = {}
219    if sim_filename:
220        try:
221            sim_data = load_config(sim_filename)
222        except Exception:
223            log.warning("Failed to load %s!", sim_filename)
224    if not ad.telephony["subscription"]:
225        abort_all_tests(ad.log, "No valid subscription")
226    ad.log.debug("Subscription DB %s", ad.telephony["subscription"])
227    result = True
228    active_sub_id = get_outgoing_voice_sub_id(ad)
229    for sub_id, sub_info in ad.telephony["subscription"].items():
230        ad.log.debug("Loop for Subid %s", sub_id)
231        sub_info["operator"] = get_operator_name(log, ad, sub_id)
232        iccid = sub_info["iccid"]
233        if not iccid:
234            ad.log.warning("Unable to find ICC-ID for subscriber %s", sub_id)
235            continue
236        if sub_info.get("phone_num"):
237            if iccid in sim_data and sim_data[iccid].get("phone_num"):
238                if not check_phone_number_match(sim_data[iccid]["phone_num"],
239                                                sub_info["phone_num"]):
240                    ad.log.warning(
241                        "phone_num %s in sim card data file for iccid %s"
242                        "  do not match phone_num %s from subscription",
243                        sim_data[iccid]["phone_num"], iccid,
244                        sub_info["phone_num"])
245                sub_info["phone_num"] = sim_data[iccid]["phone_num"]
246        else:
247            if iccid in sim_data and sim_data[iccid].get("phone_num"):
248                sub_info["phone_num"] = sim_data[iccid]["phone_num"]
249            elif sub_id == active_sub_id:
250                phone_number = get_phone_number_by_secret_code(
251                    ad, sub_info["sim_operator_name"])
252                if phone_number:
253                    sub_info["phone_num"] = phone_number
254                elif getattr(ad, "phone_num", None):
255                    sub_info["phone_num"] = ad.phone_number
256        if (not sub_info.get("phone_num")) and sub_id == active_sub_id:
257            ad.log.info("sub_id %s sub_info = %s", sub_id, sub_info)
258            ad.log.error(
259                "Unable to retrieve phone number for sub %s with iccid"
260                " %s from device or testbed config or sim card file %s",
261                sub_id, iccid, sim_filename)
262            result = False
263        if not hasattr(
264                ad, 'roaming'
265        ) and sub_info["sim_plmn"] != sub_info["network_plmn"] and sub_info["sim_operator_name"].strip(
266        ) not in sub_info["network_operator_name"].strip():
267            ad.log.info("roaming is not enabled, enable it")
268            setattr(ad, 'roaming', True)
269        ad.log.info("SubId %s info: %s", sub_id, sorted(sub_info.items()))
270    get_phone_capability(ad)
271    data_roaming = getattr(ad, 'roaming', False)
272    if get_cell_data_roaming_state_by_adb(ad) != data_roaming:
273        set_cell_data_roaming_state_by_adb(ad, data_roaming)
274        # Setup VoWiFi MDN for Verizon. b/33187374
275    if not result:
276        abort_all_tests(ad.log, "Failed to find valid phone number")
277
278    ad.log.debug("telephony = %s", ad.telephony)
279
280
281def refresh_droid_config(log, ad):
282    """ Update Android Device telephony records for each sub_id.
283
284    Args:
285        log: log object
286        ad: android device object
287
288    Returns:
289        None
290    """
291    if not getattr(ad, 'telephony', {}):
292        setattr(ad, 'telephony', {"subscription": {}})
293    droid = ad.droid
294    sub_info_list = droid.subscriptionGetAllSubInfoList()
295    ad.log.info("SubInfoList is %s", sub_info_list)
296    if not sub_info_list: return
297    active_sub_id = get_outgoing_voice_sub_id(ad)
298    for sub_info in sub_info_list:
299        sub_id = sub_info["subscriptionId"]
300        sim_slot = sub_info["simSlotIndex"]
301        if sub_info.get("carrierId"):
302            carrier_id = sub_info["carrierId"]
303        else:
304            carrier_id = -1
305        if sub_info.get("isOpportunistic"):
306            isopportunistic = sub_info["isOpportunistic"]
307        else:
308            isopportunistic = -1
309
310        if sim_slot != INVALID_SIM_SLOT_INDEX:
311            if sub_id not in ad.telephony["subscription"]:
312                ad.telephony["subscription"][sub_id] = {}
313            sub_record = ad.telephony["subscription"][sub_id]
314            if sub_info.get("iccId"):
315                sub_record["iccid"] = sub_info["iccId"]
316            else:
317                sub_record[
318                    "iccid"] = droid.telephonyGetSimSerialNumberForSubscription(
319                        sub_id)
320            sub_record["sim_slot"] = sim_slot
321            if sub_info.get("mcc"):
322                sub_record["mcc"] = sub_info["mcc"]
323            if sub_info.get("mnc"):
324                sub_record["mnc"] = sub_info["mnc"]
325            if sub_info.get("displayName"):
326                sub_record["display_name"] = sub_info["displayName"]
327            try:
328                sub_record[
329                    "phone_type"] = droid.telephonyGetPhoneTypeForSubscription(
330                        sub_id)
331            except:
332                if not sub_record.get("phone_type"):
333                    sub_record["phone_type"] = droid.telephonyGetPhoneType()
334            sub_record[
335                "sim_plmn"] = droid.telephonyGetSimOperatorForSubscription(
336                    sub_id)
337            sub_record[
338                "sim_operator_name"] = droid.telephonyGetSimOperatorNameForSubscription(
339                    sub_id)
340            sub_record[
341                "network_plmn"] = droid.telephonyGetNetworkOperatorForSubscription(
342                    sub_id)
343            sub_record[
344                "network_operator_name"] = droid.telephonyGetNetworkOperatorNameForSubscription(
345                    sub_id)
346            sub_record[
347                "sim_country"] = droid.telephonyGetSimCountryIsoForSubscription(
348                    sub_id)
349            if active_sub_id == sub_id:
350                try:
351                    sub_record[
352                        "carrier_id"] = ad.droid.telephonyGetSimCarrierId()
353                    sub_record[
354                        "carrier_id_name"] = ad.droid.telephonyGetSimCarrierIdName(
355                        )
356                except:
357                    ad.log.info("Carrier ID is not supported")
358            if carrier_id == 2340:
359                ad.log.info("SubId %s info: %s", sub_id, sorted(
360                    sub_record.items()))
361                continue
362            if carrier_id == 1989 and isopportunistic == "true":
363                ad.log.info("SubId %s info: %s", sub_id, sorted(
364                    sub_record.items()))
365                continue
366            if not sub_info.get("number"):
367                sub_info[
368                    "number"] = droid.telephonyGetLine1NumberForSubscription(
369                        sub_id)
370            if sub_info.get("number"):
371                if sub_record.get("phone_num"):
372                    # Use the phone number provided in sim info file by default
373                    # as the sub_info["number"] may not be formatted in a
374                    # dialable number
375                    if not check_phone_number_match(sub_info["number"],
376                                                    sub_record["phone_num"]):
377                        ad.log.info(
378                            "Subscriber phone number changed from %s to %s",
379                            sub_record["phone_num"], sub_info["number"])
380                        sub_record["phone_num"] = sub_info["number"]
381                else:
382                    sub_record["phone_num"] = phone_number_formatter(
383                        sub_info["number"])
384            ad.log.info("SubId %s info: %s", sub_id, sorted(
385                sub_record.items()))
386
387
388def get_phone_number_by_secret_code(ad, operator):
389    if "T-Mobile" in operator:
390        ad.droid.telecomDialNumber("#686#")
391        ad.send_keycode("ENTER")
392        for _ in range(12):
393            output = ad.search_logcat("mobile number")
394            if output:
395                result = re.findall(r"mobile number is (\S+)",
396                                    output[-1]["log_message"])
397                ad.send_keycode("BACK")
398                return result[0]
399            else:
400                time.sleep(5)
401    return ""
402
403
404def get_user_config_profile(ad):
405    return {
406        "Airplane Mode":
407        ad.droid.connectivityCheckAirplaneMode(),
408        "IMS Registered":
409        ad.droid.telephonyIsImsRegistered(),
410        "Preferred Network Type":
411        ad.droid.telephonyGetPreferredNetworkTypes(),
412        "VoLTE Platform Enabled":
413        ad.droid.imsIsEnhanced4gLteModeSettingEnabledByPlatform(),
414        "VoLTE Enabled":
415        ad.droid.imsIsEnhanced4gLteModeSettingEnabledByUser(),
416        "VoLTE Available":
417        ad.droid.telephonyIsVolteAvailable(),
418        "VT Available":
419        ad.droid.telephonyIsVideoCallingAvailable(),
420        "VT Enabled":
421        ad.droid.imsIsVtEnabledByUser(),
422        "VT Platform Enabled":
423        ad.droid.imsIsVtEnabledByPlatform(),
424        "WiFi State":
425        ad.droid.wifiCheckState(),
426        "WFC Available":
427        ad.droid.telephonyIsWifiCallingAvailable(),
428        "WFC Enabled":
429        ad.droid.imsIsWfcEnabledByUser(),
430        "WFC Platform Enabled":
431        ad.droid.imsIsWfcEnabledByPlatform(),
432        "WFC Mode":
433        ad.droid.imsGetWfcMode()
434    }
435
436
437def get_num_active_sims(log, ad):
438    """ Get the number of active SIM cards by counting slots
439
440    Args:
441        ad: android_device object.
442
443    Returns:
444        result: The number of loaded (physical) SIM cards
445    """
446    # using a dictionary as a cheap way to prevent double counting
447    # in the situation where multiple subscriptions are on the same SIM.
448    # yes, this is a corner corner case.
449    valid_sims = {}
450    subInfo = ad.droid.subscriptionGetAllSubInfoList()
451    for info in subInfo:
452        ssidx = info['simSlotIndex']
453        if ssidx == INVALID_SIM_SLOT_INDEX:
454            continue
455        valid_sims[ssidx] = True
456    return len(valid_sims.keys())
457
458
459def toggle_airplane_mode_by_adb(log, ad, new_state=None):
460    """ Toggle the state of airplane mode.
461
462    Args:
463        log: log handler.
464        ad: android_device object.
465        new_state: Airplane mode state to set to.
466            If None, opposite of the current state.
467        strict_checking: Whether to turn on strict checking that checks all features.
468
469    Returns:
470        result: True if operation succeed. False if error happens.
471    """
472    cur_state = bool(int(ad.adb.shell("settings get global airplane_mode_on")))
473    if new_state == cur_state:
474        ad.log.info("Airplane mode already in %s", new_state)
475        return True
476    elif new_state is None:
477        new_state = not cur_state
478    ad.log.info("Change airplane mode from %s to %s", cur_state, new_state)
479    try:
480        ad.adb.shell("settings put global airplane_mode_on %s" % int(new_state))
481        ad.adb.shell("am broadcast -a android.intent.action.AIRPLANE_MODE")
482    except Exception as e:
483        ad.log.error(e)
484        return False
485    changed_state = bool(int(ad.adb.shell("settings get global airplane_mode_on")))
486    return changed_state == new_state
487
488
489def toggle_airplane_mode(log, ad, new_state=None, strict_checking=True):
490    """ Toggle the state of airplane mode.
491
492    Args:
493        log: log handler.
494        ad: android_device object.
495        new_state: Airplane mode state to set to.
496            If None, opposite of the current state.
497        strict_checking: Whether to turn on strict checking that checks all features.
498
499    Returns:
500        result: True if operation succeed. False if error happens.
501    """
502    if ad.skip_sl4a:
503        return toggle_airplane_mode_by_adb(log, ad, new_state)
504    else:
505        return toggle_airplane_mode_msim(
506            log, ad, new_state, strict_checking=strict_checking)
507
508
509def get_telephony_signal_strength(ad):
510    #{'evdoEcio': -1, 'asuLevel': 28, 'lteSignalStrength': 14, 'gsmLevel': 0,
511    # 'cdmaAsuLevel': 99, 'evdoDbm': -120, 'gsmDbm': -1, 'cdmaEcio': -160,
512    # 'level': 2, 'lteLevel': 2, 'cdmaDbm': -120, 'dbm': -112, 'cdmaLevel': 0,
513    # 'lteAsuLevel': 28, 'gsmAsuLevel': 99, 'gsmBitErrorRate': 0,
514    # 'lteDbm': -112, 'gsmSignalStrength': 99}
515    try:
516        signal_strength = ad.droid.telephonyGetSignalStrength()
517        if not signal_strength:
518            signal_strength = {}
519    except Exception as e:
520        ad.log.error(e)
521        signal_strength = {}
522    return signal_strength
523
524
525def get_lte_rsrp(ad):
526    try:
527        if ad.adb.getprop("ro.build.version.release")[0] in ("9", "P"):
528            out = ad.adb.shell(
529                "dumpsys telephony.registry | grep -i signalstrength")
530            if out:
531                lte_rsrp = out.split()[9]
532                if lte_rsrp:
533                    ad.log.info("lte_rsrp: %s ", lte_rsrp)
534                    return lte_rsrp
535        else:
536            out = ad.adb.shell(
537            "dumpsys telephony.registry |grep -i primary=CellSignalStrengthLte")
538            if out:
539                lte_cell_info = out.split('mLte=')[1]
540                lte_rsrp = re.match(r'.*rsrp=(\S+).*', lte_cell_info).group(1)
541                if lte_rsrp:
542                    ad.log.info("lte_rsrp: %s ", lte_rsrp)
543                    return lte_rsrp
544    except Exception as e:
545        ad.log.error(e)
546    return None
547
548
549def break_internet_except_sl4a_port(ad, sl4a_port):
550    ad.log.info("Breaking internet using iptables rules")
551    ad.adb.shell("iptables -I INPUT 1 -p tcp --dport %s -j ACCEPT" % sl4a_port,
552                 ignore_status=True)
553    ad.adb.shell("iptables -I INPUT 2 -p tcp --sport %s -j ACCEPT" % sl4a_port,
554                 ignore_status=True)
555    ad.adb.shell("iptables -I INPUT 3 -j DROP", ignore_status=True)
556    ad.adb.shell("ip6tables -I INPUT -j DROP", ignore_status=True)
557    return True
558
559
560def resume_internet_with_sl4a_port(ad, sl4a_port):
561    ad.log.info("Bring internet back using iptables rules")
562    ad.adb.shell("iptables -D INPUT -p tcp --dport %s -j ACCEPT" % sl4a_port,
563                 ignore_status=True)
564    ad.adb.shell("iptables -D INPUT -p tcp --sport %s -j ACCEPT" % sl4a_port,
565                 ignore_status=True)
566    ad.adb.shell("iptables -D INPUT -j DROP", ignore_status=True)
567    ad.adb.shell("ip6tables -D INPUT -j DROP", ignore_status=True)
568    return True
569
570
571def test_data_browsing_success_using_sl4a(log, ad):
572    result = True
573    web_page_list = ['https://www.google.com', 'https://www.yahoo.com',
574                     'https://www.amazon.com', 'https://www.nike.com',
575                     'https://www.facebook.com']
576    for website in web_page_list:
577        if not verify_http_connection(log, ad, website, retry=0):
578            ad.log.error("Failed to browse %s successfully!", website)
579            result = False
580    return result
581
582
583def test_data_browsing_failure_using_sl4a(log, ad):
584    result = True
585    web_page_list = ['https://www.youtube.com', 'https://www.cnn.com',
586                     'https://www.att.com', 'https://www.nbc.com',
587                     'https://www.verizonwireless.com']
588    for website in web_page_list:
589        if not verify_http_connection(log, ad, website, retry=0,
590                                      expected_state=False):
591            ad.log.error("Browsing to %s worked!", website)
592            result = False
593    return result
594
595
596def is_expected_event(event_to_check, events_list):
597    """ check whether event is present in the event list
598
599    Args:
600        event_to_check: event to be checked.
601        events_list: list of events
602    Returns:
603        result: True if event present in the list. False if not.
604    """
605    for event in events_list:
606        if event in event_to_check['name']:
607            return True
608    return False
609
610
611def is_sim_ready(log, ad, sim_slot_id=None):
612    """ check whether SIM is ready.
613
614    Args:
615        ad: android_device object.
616        sim_slot_id: check the SIM status for sim_slot_id
617            This is optional. If this is None, check default SIM.
618
619    Returns:
620        result: True if all SIMs are ready. False if not.
621    """
622    if sim_slot_id is None:
623        status = ad.droid.telephonyGetSimState()
624    else:
625        status = ad.droid.telephonyGetSimStateForSlotId(sim_slot_id)
626    if status != SIM_STATE_READY:
627        ad.log.info("Sim state is %s, not ready", status)
628        return False
629    return True
630
631
632def is_sim_ready_by_adb(log, ad):
633    state = ad.adb.getprop("gsm.sim.state")
634    ad.log.info("gsm.sim.state = %s", state)
635    return state == SIM_STATE_READY or state == SIM_STATE_LOADED
636
637
638def wait_for_sim_ready_by_adb(log, ad, wait_time=90):
639    return _wait_for_droid_in_state(log, ad, wait_time, is_sim_ready_by_adb)
640
641
642def is_sims_ready_by_adb(log, ad):
643    states = list(ad.adb.getprop("gsm.sim.state").split(","))
644    ad.log.info("gsm.sim.state = %s", states)
645    for state in states:
646        if state != SIM_STATE_READY and state != SIM_STATE_LOADED:
647            return False
648    return True
649
650
651def wait_for_sims_ready_by_adb(log, ad, wait_time=90):
652    return _wait_for_droid_in_state(log, ad, wait_time, is_sims_ready_by_adb)
653
654
655def get_service_state_by_adb(log, ad):
656    output = ad.adb.shell("dumpsys telephony.registry | grep mServiceState")
657    if "mVoiceRegState" in output:
658        result = re.findall(r"mVoiceRegState=(\S+)\((\S+)\)", output)
659        if result:
660            if getattr(ad, 'dsds', False):
661                default_slot = getattr(ad, 'default_slot', 0)
662                ad.log.info("mVoiceRegState is %s %s", result[default_slot][0],
663                            result[default_slot][1])
664                return result[default_slot][1]
665            else:
666                ad.log.info("mVoiceRegState is %s %s", result[0][0],
667                            result[0][1])
668                return result[0][1]
669    else:
670        result = re.search(r"mServiceState=(\S+)", output)
671        if result:
672            ad.log.info("mServiceState=%s %s", result.group(1),
673                        SERVICE_STATE_MAPPING[result.group(1)])
674            return SERVICE_STATE_MAPPING[result.group(1)]
675
676
677def _is_expecting_event(event_recv_list):
678    """ check for more event is expected in event list
679
680    Args:
681        event_recv_list: list of events
682    Returns:
683        result: True if more events are expected. False if not.
684    """
685    for state in event_recv_list:
686        if state is False:
687            return True
688    return False
689
690
691def _set_event_list(event_recv_list, sub_id_list, sub_id, value):
692    """ set received event in expected event list
693
694    Args:
695        event_recv_list: list of received events
696        sub_id_list: subscription ID list
697        sub_id: subscription id of current event
698        value: True or False
699    Returns:
700        None.
701    """
702    for i in range(len(sub_id_list)):
703        if sub_id_list[i] == sub_id:
704            event_recv_list[i] = value
705
706
707def _wait_for_bluetooth_in_state(log, ad, state, max_wait):
708    # FIXME: These event names should be defined in a common location
709    _BLUETOOTH_STATE_ON_EVENT = 'BluetoothStateChangedOn'
710    _BLUETOOTH_STATE_OFF_EVENT = 'BluetoothStateChangedOff'
711    ad.ed.clear_events(_BLUETOOTH_STATE_ON_EVENT)
712    ad.ed.clear_events(_BLUETOOTH_STATE_OFF_EVENT)
713
714    ad.droid.bluetoothStartListeningForAdapterStateChange()
715    try:
716        bt_state = ad.droid.bluetoothCheckState()
717        if bt_state == state:
718            return True
719        if max_wait <= 0:
720            ad.log.error("Time out: bluetooth state still %s, expecting %s",
721                         bt_state, state)
722            return False
723
724        event = {
725            False: _BLUETOOTH_STATE_OFF_EVENT,
726            True: _BLUETOOTH_STATE_ON_EVENT
727        }[state]
728        event = ad.ed.pop_event(event, max_wait)
729        ad.log.info("Got event %s", event['name'])
730        return True
731    except Empty:
732        ad.log.error("Time out: bluetooth state still in %s, expecting %s",
733                     bt_state, state)
734        return False
735    finally:
736        ad.droid.bluetoothStopListeningForAdapterStateChange()
737
738
739# TODO: replace this with an event-based function
740def _wait_for_wifi_in_state(log, ad, state, max_wait):
741    return _wait_for_droid_in_state(log, ad, max_wait,
742        lambda log, ad, state: \
743                (True if ad.droid.wifiCheckState() == state else False),
744                state)
745
746
747def toggle_airplane_mode_msim(log, ad, new_state=None, strict_checking=True):
748    """ Toggle the state of airplane mode.
749
750    Args:
751        log: log handler.
752        ad: android_device object.
753        new_state: Airplane mode state to set to.
754            If None, opposite of the current state.
755        strict_checking: Whether to turn on strict checking that checks all features.
756
757    Returns:
758        result: True if operation succeed. False if error happens.
759    """
760
761    cur_state = ad.droid.connectivityCheckAirplaneMode()
762    if cur_state == new_state:
763        ad.log.info("Airplane mode already in %s", new_state)
764        return True
765    elif new_state is None:
766        new_state = not cur_state
767        ad.log.info("Toggle APM mode, from current tate %s to %s", cur_state,
768                    new_state)
769    sub_id_list = []
770    active_sub_info = ad.droid.subscriptionGetAllSubInfoList()
771    if active_sub_info:
772        for info in active_sub_info:
773            sub_id_list.append(info['subscriptionId'])
774
775    ad.ed.clear_all_events()
776    time.sleep(0.1)
777    service_state_list = []
778    if new_state:
779        service_state_list.append(SERVICE_STATE_POWER_OFF)
780        ad.log.info("Turn on airplane mode")
781
782    else:
783        # If either one of these 3 events show up, it should be OK.
784        # Normal SIM, phone in service
785        service_state_list.append(SERVICE_STATE_IN_SERVICE)
786        # NO SIM, or Dead SIM, or no Roaming coverage.
787        service_state_list.append(SERVICE_STATE_OUT_OF_SERVICE)
788        service_state_list.append(SERVICE_STATE_EMERGENCY_ONLY)
789        ad.log.info("Turn off airplane mode")
790
791    for sub_id in sub_id_list:
792        ad.droid.telephonyStartTrackingServiceStateChangeForSubscription(
793            sub_id)
794
795    timeout_time = time.time() + MAX_WAIT_TIME_AIRPLANEMODE_EVENT
796    ad.droid.connectivityToggleAirplaneMode(new_state)
797
798    try:
799        try:
800            event = ad.ed.wait_for_event(
801                EventServiceStateChanged,
802                is_event_match_for_list,
803                timeout=MAX_WAIT_TIME_AIRPLANEMODE_EVENT,
804                field=ServiceStateContainer.SERVICE_STATE,
805                value_list=service_state_list)
806            ad.log.info("Got event %s", event)
807        except Empty:
808            ad.log.warning("Did not get expected service state change to %s",
809                           service_state_list)
810        finally:
811            for sub_id in sub_id_list:
812                ad.droid.telephonyStopTrackingServiceStateChangeForSubscription(
813                    sub_id)
814    except Exception as e:
815        ad.log.error(e)
816
817    # APM on (new_state=True) will turn off bluetooth but may not turn it on
818    try:
819        if new_state and not _wait_for_bluetooth_in_state(
820                log, ad, False, timeout_time - time.time()):
821            ad.log.error(
822                "Failed waiting for bluetooth during airplane mode toggle")
823            if strict_checking: return False
824    except Exception as e:
825        ad.log.error("Failed to check bluetooth state due to %s", e)
826        if strict_checking:
827            raise
828
829    # APM on (new_state=True) will turn off wifi but may not turn it on
830    if new_state and not _wait_for_wifi_in_state(log, ad, False,
831                                                 timeout_time - time.time()):
832        ad.log.error("Failed waiting for wifi during airplane mode toggle on")
833        if strict_checking: return False
834
835    if ad.droid.connectivityCheckAirplaneMode() != new_state:
836        ad.log.error("Set airplane mode to %s failed", new_state)
837        return False
838    return True
839
840
841def wait_for_cbrs_data_active_sub_change_event(
842        ad,
843        event_tracking_started=False,
844        timeout=120):
845    """Wait for an data change event on specified subscription.
846
847    Args:
848        ad: android device object.
849        event_tracking_started: True if event tracking already state outside
850        timeout: time to wait for event
851
852    Returns:
853        True: if data change event is received.
854        False: if data change event is not received.
855    """
856    if not event_tracking_started:
857        ad.ed.clear_events(EventActiveDataSubIdChanged)
858        ad.droid.telephonyStartTrackingActiveDataChange()
859    try:
860        ad.ed.wait_for_event(
861            EventActiveDataSubIdChanged,
862            is_event_match,
863            timeout=timeout)
864        ad.log.info("Got event activedatasubidchanged")
865    except Empty:
866        ad.log.info("No event for data subid change")
867        return False
868    finally:
869        if not event_tracking_started:
870            ad.droid.telephonyStopTrackingActiveDataChange()
871    return True
872
873
874def is_current_data_on_cbrs(ad, cbrs_subid):
875    """Verifies if current data sub is on CBRS
876
877    Args:
878        ad: android device object.
879        cbrs_subid: sub_id against which we need to check
880
881    Returns:
882        True: if data is on cbrs
883        False: if data is not on cbrs
884    """
885    if cbrs_subid is None:
886        return False
887    current_data = ad.droid.subscriptionGetActiveDataSubscriptionId()
888    ad.log.info("Current Data subid %s cbrs_subid %s", current_data, cbrs_subid)
889    if current_data == cbrs_subid:
890        return True
891    else:
892        return False
893
894
895def get_current_override_network_type(ad, timeout=30):
896    """Returns current override network type
897
898    Args:
899        ad: android device object.
900        timeout: max time to wait for event
901
902    Returns:
903        value: current override type
904        -1: if no event received
905    """
906    override_value_list = [OverrideNetworkContainer.OVERRIDE_NETWORK_TYPE_NR_NSA,
907                           OverrideNetworkContainer.OVERRIDE_NETWORK_TYPE_NONE,
908                           OverrideNetworkContainer.OVERRIDE_NETWORK_TYPE_NR_MMWAVE,
909                           OverrideNetworkContainer.OVERRIDE_NETWORK_TYPE_LTE_CA,
910                           OverrideNetworkContainer.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO]
911    ad.ed.clear_events(EventDisplayInfoChanged)
912    ad.droid.telephonyStartTrackingDisplayInfoChange()
913    try:
914        event = ad.ed.wait_for_event(
915                    EventDisplayInfoChanged,
916                    is_event_match_for_list,
917                    timeout=timeout,
918                    field=DisplayInfoContainer.OVERRIDE,
919                    value_list=override_value_list)
920        override_type = event['data']['override']
921        ad.log.info("Current Override Type is %s", override_type)
922        return override_type
923    except Empty:
924        ad.log.info("No event for display info change")
925        return -1
926    finally:
927        ad.droid.telephonyStopTrackingDisplayInfoChange()
928    return -1
929
930
931def _phone_number_remove_prefix(number):
932    """Remove the country code and other prefix from the input phone number.
933    Currently only handle phone number with the following formats:
934        (US phone number format)
935        +1abcxxxyyyy
936        1abcxxxyyyy
937        abcxxxyyyy
938        abc xxx yyyy
939        abc.xxx.yyyy
940        abc-xxx-yyyy
941        (EEUK phone number format)
942        +44abcxxxyyyy
943        0abcxxxyyyy
944
945    Args:
946        number: input phone number
947
948    Returns:
949        Phone number without country code or prefix
950    """
951    if number is None:
952        return None, None
953    for country_code in COUNTRY_CODE_LIST:
954        if number.startswith(country_code):
955            return number[len(country_code):], country_code
956    if number[0] == "1" or number[0] == "0":
957        return number[1:], None
958    return number, None
959
960
961def check_phone_number_match(number1, number2):
962    """Check whether two input phone numbers match or not.
963
964    Compare the two input phone numbers.
965    If they match, return True; otherwise, return False.
966    Currently only handle phone number with the following formats:
967        (US phone number format)
968        +1abcxxxyyyy
969        1abcxxxyyyy
970        abcxxxyyyy
971        abc xxx yyyy
972        abc.xxx.yyyy
973        abc-xxx-yyyy
974        (EEUK phone number format)
975        +44abcxxxyyyy
976        0abcxxxyyyy
977
978        There are some scenarios we can not verify, one example is:
979            number1 = +15555555555, number2 = 5555555555
980            (number2 have no country code)
981
982    Args:
983        number1: 1st phone number to be compared.
984        number2: 2nd phone number to be compared.
985
986    Returns:
987        True if two phone numbers match. Otherwise False.
988    """
989    number1 = phone_number_formatter(number1)
990    number2 = phone_number_formatter(number2)
991    # Handle extra country code attachment when matching phone number
992    if number1[-7:] in number2 or number2[-7:] in number1:
993        return True
994    else:
995        logging.info("phone number1 %s and number2 %s does not match" %
996                     (number1, number2))
997        return False
998
999
1000def get_call_state_by_adb(ad):
1001    slot_index_of_default_voice_subid = get_slot_index_from_subid(ad,
1002        get_incoming_voice_sub_id(ad))
1003    output = ad.adb.shell("dumpsys telephony.registry | grep mCallState")
1004    if "mCallState" in output:
1005        call_state_list = re.findall("mCallState=(\d)", output)
1006        if call_state_list:
1007            return call_state_list[slot_index_of_default_voice_subid]
1008
1009
1010def check_call_state_connected_by_adb(ad):
1011    return "2" in get_call_state_by_adb(ad)
1012
1013
1014def check_call_state_idle_by_adb(ad):
1015    return "0" in get_call_state_by_adb(ad)
1016
1017
1018def check_call_state_ring_by_adb(ad):
1019    return "1" in get_call_state_by_adb(ad)
1020
1021
1022def get_incoming_call_number_by_adb(ad):
1023    output = ad.adb.shell(
1024        "dumpsys telephony.registry | grep mCallIncomingNumber")
1025    return re.search(r"mCallIncomingNumber=(.*)", output).group(1)
1026
1027
1028def dumpsys_all_call_info(ad):
1029    """ Get call information by dumpsys telecom. """
1030    output = ad.adb.shell("dumpsys telecom")
1031    calls = re.findall("Call TC@\d+: {(.*?)}", output, re.DOTALL)
1032    calls_info = []
1033    for call in calls:
1034        call_info = {}
1035        for attr in ("startTime", "endTime", "direction", "isInterrupted",
1036                     "callTechnologies", "callTerminationsReason",
1037                     "connectionService", "isVideoCall", "callProperties"):
1038            match = re.search(r"%s: (.*)" % attr, call)
1039            if match:
1040                if attr in ("startTime", "endTime"):
1041                    call_info[attr] = epoch_to_log_line_timestamp(
1042                        int(match.group(1)))
1043                else:
1044                    call_info[attr] = match.group(1)
1045        call_info["inCallServices"] = re.findall(r"name: (.*)", call)
1046        calls_info.append(call_info)
1047    ad.log.debug("calls_info = %s", calls_info)
1048    return calls_info
1049
1050
1051def dumpsys_carrier_config(ad):
1052    output = ad.adb.shell("dumpsys carrier_config").split("\n")
1053    output_phone_id_0 = []
1054    output_phone_id_1 = []
1055    current_output = []
1056    for line in output:
1057        if "Phone Id = 0" in line:
1058            current_output = output_phone_id_0
1059        elif "Phone Id = 1" in line:
1060            current_output = output_phone_id_1
1061        current_output.append(line.strip())
1062
1063    configs = {}
1064    if ad.adb.getprop("ro.build.version.release")[0] in ("9", "P"):
1065        phone_count = 1
1066        if "," in ad.adb.getprop("gsm.network.type"):
1067            phone_count = 2
1068    else:
1069        phone_count = ad.droid.telephonyGetPhoneCount()
1070
1071    slot_0_subid = get_subid_from_slot_index(ad.log, ad, 0)
1072    if slot_0_subid != INVALID_SUB_ID:
1073        configs[slot_0_subid] = {}
1074
1075    if phone_count == 2:
1076        slot_1_subid = get_subid_from_slot_index(ad.log, ad, 1)
1077        if slot_1_subid != INVALID_SUB_ID:
1078            configs[slot_1_subid] = {}
1079
1080    attrs = [attr for attr in dir(CarrierConfigs) if not attr.startswith("__")]
1081    for attr in attrs:
1082        attr_string = getattr(CarrierConfigs, attr)
1083        values = re.findall(
1084            r"%s = (\S+)" % attr_string, "\n".join(output_phone_id_0))
1085
1086        if slot_0_subid != INVALID_SUB_ID:
1087            if values:
1088                value = values[-1]
1089                if value == "true":
1090                    configs[slot_0_subid][attr_string] = True
1091                elif value == "false":
1092                    configs[slot_0_subid][attr_string] = False
1093                elif attr_string == CarrierConfigs.DEFAULT_WFC_IMS_MODE_INT:
1094                    if value == "0":
1095                        configs[slot_0_subid][attr_string] = WFC_MODE_WIFI_ONLY
1096                    elif value == "1":
1097                        configs[slot_0_subid][attr_string] = \
1098                            WFC_MODE_CELLULAR_PREFERRED
1099                    elif value == "2":
1100                        configs[slot_0_subid][attr_string] = \
1101                            WFC_MODE_WIFI_PREFERRED
1102                else:
1103                    try:
1104                        configs[slot_0_subid][attr_string] = int(value)
1105                    except Exception:
1106                        configs[slot_0_subid][attr_string] = value
1107            else:
1108                configs[slot_0_subid][attr_string] = None
1109
1110        if phone_count == 2:
1111            if slot_1_subid != INVALID_SUB_ID:
1112                values = re.findall(
1113                    r"%s = (\S+)" % attr_string, "\n".join(output_phone_id_1))
1114                if values:
1115                    value = values[-1]
1116                    if value == "true":
1117                        configs[slot_1_subid][attr_string] = True
1118                    elif value == "false":
1119                        configs[slot_1_subid][attr_string] = False
1120                    elif attr_string == CarrierConfigs.DEFAULT_WFC_IMS_MODE_INT:
1121                        if value == "0":
1122                            configs[slot_1_subid][attr_string] = \
1123                                WFC_MODE_WIFI_ONLY
1124                        elif value == "1":
1125                            configs[slot_1_subid][attr_string] = \
1126                                WFC_MODE_CELLULAR_PREFERRED
1127                        elif value == "2":
1128                            configs[slot_1_subid][attr_string] = \
1129                                WFC_MODE_WIFI_PREFERRED
1130                    else:
1131                        try:
1132                            configs[slot_1_subid][attr_string] = int(value)
1133                        except Exception:
1134                            configs[slot_1_subid][attr_string] = value
1135                else:
1136                    configs[slot_1_subid][attr_string] = None
1137    return configs
1138
1139
1140def get_phone_capability(ad):
1141    carrier_configs = dumpsys_carrier_config(ad)
1142    for sub_id in carrier_configs:
1143        capabilities = []
1144        if carrier_configs[sub_id][CarrierConfigs.VOLTE_AVAILABLE_BOOL]:
1145            capabilities.append(CAPABILITY_VOLTE)
1146        if carrier_configs[sub_id][CarrierConfigs.WFC_IMS_AVAILABLE_BOOL]:
1147            capabilities.append(CAPABILITY_WFC)
1148        if carrier_configs[sub_id][CarrierConfigs.EDITABLE_WFC_MODE_BOOL]:
1149            capabilities.append(CAPABILITY_WFC_MODE_CHANGE)
1150        if carrier_configs[sub_id][CarrierConfigs.SUPPORT_CONFERENCE_CALL_BOOL]:
1151            capabilities.append(CAPABILITY_CONFERENCE)
1152        if carrier_configs[sub_id][CarrierConfigs.VT_AVAILABLE_BOOL]:
1153            capabilities.append(CAPABILITY_VT)
1154        if carrier_configs[sub_id][CarrierConfigs.VOLTE_PROVISIONED_BOOL]:
1155            capabilities.append(CAPABILITY_VOLTE_PROVISIONING)
1156        if carrier_configs[sub_id][CarrierConfigs.VOLTE_OVERRIDE_WFC_BOOL]:
1157            capabilities.append(CAPABILITY_VOLTE_OVERRIDE_WFC_PROVISIONING)
1158        if carrier_configs[sub_id][CarrierConfigs.HIDE_ENHANCED_4G_LTE_BOOL]:
1159            capabilities.append(CAPABILITY_HIDE_ENHANCED_4G_LTE_BOOL)
1160
1161        ad.log.info("Capabilities of sub ID %s: %s", sub_id, capabilities)
1162        if not getattr(ad, 'telephony', {}):
1163            ad.telephony["subscription"] = {}
1164            ad.telephony["subscription"][sub_id] = {}
1165            setattr(
1166                ad.telephony["subscription"][sub_id],
1167                'capabilities', capabilities)
1168
1169        else:
1170            ad.telephony["subscription"][sub_id]["capabilities"] = capabilities
1171        if CAPABILITY_WFC not in capabilities:
1172            wfc_modes = []
1173        else:
1174            if carrier_configs[sub_id].get(
1175                CarrierConfigs.EDITABLE_WFC_MODE_BOOL, False):
1176                wfc_modes = [
1177                    WFC_MODE_CELLULAR_PREFERRED,
1178                    WFC_MODE_WIFI_PREFERRED]
1179            else:
1180                wfc_modes = [
1181                    carrier_configs[sub_id].get(
1182                        CarrierConfigs.DEFAULT_WFC_IMS_MODE_INT,
1183                        WFC_MODE_CELLULAR_PREFERRED)
1184                ]
1185        if carrier_configs[sub_id].get(
1186            CarrierConfigs.WFC_SUPPORTS_WIFI_ONLY_BOOL,
1187            False) and WFC_MODE_WIFI_ONLY not in wfc_modes:
1188            wfc_modes.append(WFC_MODE_WIFI_ONLY)
1189        ad.telephony["subscription"][sub_id]["wfc_modes"] = wfc_modes
1190        if wfc_modes:
1191            ad.log.info("Supported WFC modes for sub ID %s: %s", sub_id,
1192                wfc_modes)
1193
1194
1195def get_capability_for_subscription(ad, capability, subid):
1196    if capability in ad.telephony["subscription"][subid].get(
1197        "capabilities", []):
1198        ad.log.info('Capability "%s" is available for sub ID %s.',
1199            capability, subid)
1200        return True
1201    else:
1202        ad.log.info('Capability "%s" is NOT available for sub ID %s.',
1203            capability, subid)
1204        return False
1205
1206
1207def phone_number_formatter(input_string, formatter=None):
1208    """Get expected format of input phone number string.
1209
1210    Args:
1211        input_string: (string) input phone number.
1212            The input could be 10/11/12 digital, with or without " "/"-"/"."
1213        formatter: (int) expected format, this could be 7/10/11/12
1214            if formatter is 7: output string would be 7 digital number.
1215            if formatter is 10: output string would be 10 digital (standard) number.
1216            if formatter is 11: output string would be "1" + 10 digital number.
1217            if formatter is 12: output string would be "+1" + 10 digital number.
1218
1219    Returns:
1220        If no error happen, return phone number in expected format.
1221        Else, return None.
1222    """
1223    if not input_string:
1224        return ""
1225    # make sure input_string is 10 digital
1226    # Remove white spaces, dashes, dots
1227    input_string = input_string.replace(" ", "").replace("-", "").replace(
1228        ".", "")
1229
1230    # Remove a country code with '+' sign and add 0 for Japan/Korea Carriers.
1231    if (len(input_string) == 13
1232            and (input_string[0:3] == "+81" or input_string[0:3] == "+82")):
1233        input_string = "0" + input_string[3:]
1234        return input_string
1235
1236    if not formatter:
1237        return input_string
1238
1239    # Remove leading 0 for the phone with area code started with 0
1240    input_string = input_string.lstrip("0")
1241
1242    # Remove "1"  or "+1"from front
1243    if (len(input_string) == PHONE_NUMBER_STRING_FORMAT_11_DIGIT
1244            and input_string[0] == "1"):
1245        input_string = input_string[1:]
1246    elif (len(input_string) == PHONE_NUMBER_STRING_FORMAT_12_DIGIT
1247          and input_string[0:2] == "+1"):
1248        input_string = input_string[2:]
1249    elif (len(input_string) == PHONE_NUMBER_STRING_FORMAT_7_DIGIT
1250          and formatter == PHONE_NUMBER_STRING_FORMAT_7_DIGIT):
1251        return input_string
1252    elif len(input_string) != PHONE_NUMBER_STRING_FORMAT_10_DIGIT:
1253        return None
1254    # change input_string according to format
1255    if formatter == PHONE_NUMBER_STRING_FORMAT_12_DIGIT:
1256        input_string = "+1" + input_string
1257    elif formatter == PHONE_NUMBER_STRING_FORMAT_11_DIGIT:
1258        input_string = "1" + input_string
1259    elif formatter == PHONE_NUMBER_STRING_FORMAT_10_DIGIT:
1260        input_string = input_string
1261    elif formatter == PHONE_NUMBER_STRING_FORMAT_7_DIGIT:
1262        input_string = input_string[3:]
1263    else:
1264        return None
1265    return input_string
1266
1267
1268def get_internet_connection_type(log, ad):
1269    """Get current active connection type name.
1270
1271    Args:
1272        log: Log object.
1273        ad: Android Device Object.
1274    Returns:
1275        current active connection type name.
1276    """
1277    if not ad.droid.connectivityNetworkIsConnected():
1278        return 'none'
1279    return connection_type_from_type_string(
1280        ad.droid.connectivityNetworkGetActiveConnectionTypeName())
1281
1282
1283def verify_http_connection(log,
1284                           ad,
1285                           url="https://www.google.com",
1286                           retry=5,
1287                           retry_interval=15,
1288                           expected_state=True):
1289    """Make ping request and return status.
1290
1291    Args:
1292        log: log object
1293        ad: Android Device Object.
1294        url: Optional. The ping request will be made to this URL.
1295            Default Value is "http://www.google.com/".
1296
1297    """
1298    if not getattr(ad, "data_droid", None):
1299        ad.data_droid, ad.data_ed = ad.get_droid()
1300        ad.data_ed.start()
1301    else:
1302        try:
1303            if not ad.data_droid.is_live:
1304                ad.data_droid, ad.data_ed = ad.get_droid()
1305                ad.data_ed.start()
1306        except Exception:
1307            ad.log.info("Start new sl4a session for file download")
1308            ad.data_droid, ad.data_ed = ad.get_droid()
1309            ad.data_ed.start()
1310    for i in range(0, retry + 1):
1311        try:
1312            http_response = ad.data_droid.httpPing(url)
1313        except Exception as e:
1314            ad.log.info("httpPing with %s", e)
1315            http_response = None
1316        if (expected_state and http_response) or (not expected_state
1317                                                  and not http_response):
1318            ad.log.info("Http ping response for %s meet expected %s", url,
1319                        expected_state)
1320            return True
1321        if i < retry:
1322            time.sleep(retry_interval)
1323    ad.log.error("Http ping to %s is %s after %s second, expecting %s", url,
1324                 http_response, i * retry_interval, expected_state)
1325    return False
1326
1327
1328def _generate_file_directory_and_file_name(url, out_path):
1329    file_name = url.split("/")[-1]
1330    if not out_path:
1331        file_directory = "/sdcard/Download/"
1332    elif not out_path.endswith("/"):
1333        file_directory, file_name = os.path.split(out_path)
1334    else:
1335        file_directory = out_path
1336    return file_directory, file_name
1337
1338
1339def _check_file_existence(ad, file_path, expected_file_size=None):
1340    """Check file existance by file_path. If expected_file_size
1341       is provided, then also check if the file meet the file size requirement.
1342    """
1343    out = None
1344    try:
1345        out = ad.adb.shell('stat -c "%%s" %s' % file_path)
1346    except AdbError:
1347        pass
1348    # Handle some old version adb returns error message "No such" into std_out
1349    if out and "No such" not in out:
1350        if expected_file_size:
1351            file_size = int(out)
1352            if file_size >= expected_file_size:
1353                ad.log.info("File %s of size %s exists", file_path, file_size)
1354                return True
1355            else:
1356                ad.log.info("File %s is of size %s, does not meet expected %s",
1357                            file_path, file_size, expected_file_size)
1358                return False
1359        else:
1360            ad.log.info("File %s exists", file_path)
1361            return True
1362    else:
1363        ad.log.info("File %s does not exist.", file_path)
1364        return False
1365
1366
1367def verify_internet_connection_by_ping(log,
1368                                       ad,
1369                                       retries=1,
1370                                       expected_state=True,
1371                                       timeout=60):
1372    """Verify internet connection by ping test.
1373
1374    Args:
1375        log: log object
1376        ad: Android Device Object.
1377
1378    """
1379    begin_time = get_current_epoch_time()
1380    ip_addr = "54.230.144.105"
1381    for dest in ("www.google.com", "www.amazon.com", ip_addr):
1382        for i in range(retries):
1383            ad.log.info("Ping %s - attempt %d", dest, i + 1)
1384            result = adb_shell_ping(
1385                ad, count=5, timeout=timeout, loss_tolerance=40, dest_ip=dest)
1386            if result == expected_state:
1387                ad.log.info(
1388                    "Internet connection by pinging to %s is %s as expected",
1389                    dest, expected_state)
1390                if dest == ip_addr:
1391                    ad.log.warning("Suspect dns failure")
1392                    ad.log.info("DNS config: %s",
1393                                ad.adb.shell("getprop | grep dns").replace(
1394                                    "\n", " "))
1395                    return False
1396                return True
1397            else:
1398                ad.log.warning(
1399                    "Internet connection test by pinging %s is %s, expecting %s",
1400                    dest, result, expected_state)
1401                if get_current_epoch_time() - begin_time < timeout * 1000:
1402                    time.sleep(5)
1403    ad.log.error("Ping test doesn't meet expected %s", expected_state)
1404    return False
1405
1406
1407def verify_internet_connection(log, ad, retries=3, expected_state=True):
1408    """Verify internet connection by ping test and http connection.
1409
1410    Args:
1411        log: log object
1412        ad: Android Device Object.
1413
1414    """
1415    if ad.droid.connectivityNetworkIsConnected() != expected_state:
1416        ad.log.info("NetworkIsConnected = %s, expecting %s",
1417                    not expected_state, expected_state)
1418    if verify_internet_connection_by_ping(
1419            log, ad, retries=retries, expected_state=expected_state):
1420        return True
1421    for url in ("https://www.google.com", "https://www.amazon.com"):
1422        if verify_http_connection(
1423                log, ad, url=url, retry=retries,
1424                expected_state=expected_state):
1425            return True
1426    ad.log.info("DNS config: %s", " ".join(
1427        ad.adb.shell("getprop | grep dns").split()))
1428    ad.log.info("Interface info:\n%s", ad.adb.shell("ifconfig"))
1429    ad.log.info("NetworkAgentInfo: %s",
1430                ad.adb.shell("dumpsys connectivity | grep NetworkAgentInfo"))
1431    return False
1432
1433
1434def iperf_test_with_options(log,
1435                            ad,
1436                            iperf_server,
1437                            iperf_option,
1438                            timeout=180,
1439                            rate_dict=None,
1440                            blocking=True,
1441                            log_file_path=None):
1442    """iperf adb run helper.
1443
1444    Args:
1445        log: log object
1446        ad: Android Device Object.
1447        iperf_server: The iperf host url".
1448        iperf_option: The options to pass to iperf client
1449        timeout: timeout for file download to complete.
1450        rate_dict: dictionary that can be passed in to save data
1451        blocking: run iperf in blocking mode if True
1452        log_file_path: location to save logs
1453    Returns:
1454        True if iperf runs without throwing an exception
1455    """
1456    try:
1457        if log_file_path:
1458            ad.adb.shell("rm %s" % log_file_path, ignore_status=True)
1459        ad.log.info("Running adb iperf test with server %s", iperf_server)
1460        ad.log.info("iperf options are %s", iperf_option)
1461        if not blocking:
1462            ad.run_iperf_client_nb(
1463                iperf_server,
1464                iperf_option,
1465                timeout=timeout + 60,
1466                log_file_path=log_file_path)
1467            return True
1468        result, data = ad.run_iperf_client(
1469            iperf_server, iperf_option, timeout=timeout + 120)
1470        ad.log.info("iperf test result with server %s is %s", iperf_server,
1471                    result)
1472        if result:
1473            iperf_str = ''.join(data)
1474            iperf_result = ipf.IPerfResult(iperf_str, 'None')
1475            if "-u" in iperf_option:
1476                udp_rate = iperf_result.avg_rate
1477                if udp_rate is None:
1478                    ad.log.warning(
1479                        "UDP rate is none, IPerf server returned error: %s",
1480                        iperf_result.error)
1481                ad.log.info("iperf3 UDP DL speed is %.6s Mbps", (udp_rate/1000000))
1482            else:
1483                tx_rate = iperf_result.avg_send_rate
1484                rx_rate = iperf_result.avg_receive_rate
1485                if (tx_rate or rx_rate) is None:
1486                    ad.log.warning(
1487                        "A TCP rate is none, iperf server returned error: %s",
1488                        iperf_result.error)
1489                ad.log.info(
1490                    "iperf3 TCP - UL speed is %.6s Mbps, DL speed is %.6s Mbps",
1491                    (tx_rate/1000000), (rx_rate/1000000))
1492            if rate_dict is not None:
1493                rate_dict["Uplink"] = tx_rate
1494                rate_dict["Downlink"] = rx_rate
1495        return result
1496    except AdbError as e:
1497        ad.log.warning("Fail to run iperf test with exception %s", e)
1498        raise
1499
1500
1501def iperf_udp_test_by_adb(log,
1502                          ad,
1503                          iperf_server,
1504                          port_num=None,
1505                          reverse=False,
1506                          timeout=180,
1507                          limit_rate=None,
1508                          pacing_timer=None,
1509                          omit=10,
1510                          ipv6=False,
1511                          rate_dict=None,
1512                          blocking=True,
1513                          log_file_path=None,
1514                          retry=5):
1515    """Iperf test by adb using UDP.
1516
1517    Args:
1518        log: log object
1519        ad: Android Device Object.
1520        iperf_Server: The iperf host url".
1521        port_num: TCP/UDP server port
1522        reverse: whether to test download instead of upload
1523        timeout: timeout for file download to complete.
1524        limit_rate: iperf bandwidth option. None by default
1525        omit: the omit option provided in iperf command.
1526        ipv6: whether to run the test as ipv6
1527        rate_dict: dictionary that can be passed in to save data
1528        blocking: run iperf in blocking mode if True
1529        log_file_path: location to save logs
1530        retry: times of retry when the server is unavailable
1531    """
1532    iperf_option = "-u -i 1 -t %s -O %s -J" % (timeout, omit)
1533    if limit_rate:
1534        iperf_option += " -b %s" % limit_rate
1535    if pacing_timer:
1536        iperf_option += " --pacing-timer %s" % pacing_timer
1537    if ipv6:
1538        iperf_option += " -6"
1539    if reverse:
1540        iperf_option += " -R"
1541    for _ in range(retry):
1542        if port_num:
1543            iperf_option_final = iperf_option + " -p %s" % port_num
1544            port_num += 1
1545        else:
1546            iperf_option_final = iperf_option
1547        try:
1548            return iperf_test_with_options(log,
1549                                           ad,
1550                                           iperf_server,
1551                                           iperf_option_final,
1552                                           timeout,
1553                                           rate_dict,
1554                                           blocking,
1555                                           log_file_path)
1556        except (AdbCommandError, TimeoutError) as error:
1557            continue
1558        except AdbError:
1559            return False
1560
1561
1562def iperf_test_by_adb(log,
1563                      ad,
1564                      iperf_server,
1565                      port_num=None,
1566                      reverse=False,
1567                      timeout=180,
1568                      limit_rate=None,
1569                      omit=10,
1570                      ipv6=False,
1571                      rate_dict=None,
1572                      blocking=True,
1573                      log_file_path=None,
1574                      retry=5):
1575    """Iperf test by adb using TCP.
1576
1577    Args:
1578        log: log object
1579        ad: Android Device Object.
1580        iperf_server: The iperf host url".
1581        port_num: TCP/UDP server port
1582        reverse: whether to test download instead of upload
1583        timeout: timeout for file download to complete.
1584        limit_rate: iperf bandwidth option. None by default
1585        omit: the omit option provided in iperf command.
1586        ipv6: whether to run the test as ipv6
1587        rate_dict: dictionary that can be passed in to save data
1588        blocking: run iperf in blocking mode if True
1589        log_file_path: location to save logs
1590        retry: times of retry when the server is unavailable
1591    """
1592    iperf_option = "-t %s -O %s -J" % (timeout, omit)
1593    if limit_rate:
1594        iperf_option += " -b %s" % limit_rate
1595    if ipv6:
1596        iperf_option += " -6"
1597    if reverse:
1598        iperf_option += " -R"
1599    for _ in range(retry):
1600        if port_num:
1601            iperf_option_final = iperf_option + " -p %s" % port_num
1602            port_num += 1
1603        else:
1604            iperf_option_final = iperf_option
1605        try:
1606            return iperf_test_with_options(log,
1607                                           ad,
1608                                           iperf_server,
1609                                           iperf_option_final,
1610                                           timeout,
1611                                           rate_dict=rate_dict,
1612                                           blocking=blocking,
1613                                           log_file_path=log_file_path)
1614        except (AdbCommandError, TimeoutError) as error:
1615            continue
1616        except AdbError:
1617            return False
1618
1619
1620def trigger_modem_crash(ad, timeout=120):
1621    cmd = "echo restart > /sys/kernel/debug/msm_subsys/modem"
1622    ad.log.info("Triggering Modem Crash from kernel using adb command %s", cmd)
1623    ad.adb.shell(cmd)
1624    time.sleep(timeout)
1625    return True
1626
1627
1628def trigger_modem_crash_by_modem(ad, timeout=120):
1629    begin_time = get_device_epoch_time(ad)
1630    ad.adb.shell(
1631        "setprop persist.vendor.sys.modem.diag.mdlog false",
1632        ignore_status=True)
1633    # Legacy pixels use persist.sys.modem.diag.mdlog.
1634    ad.adb.shell(
1635        "setprop persist.sys.modem.diag.mdlog false", ignore_status=True)
1636    disable_qxdm_logger(ad)
1637    cmd = ('am instrument -w -e request "4b 25 03 00" '
1638           '"com.google.mdstest/com.google.mdstest.instrument.'
1639           'ModemCommandInstrumentation"')
1640    ad.log.info("Crash modem by %s", cmd)
1641    ad.adb.shell(cmd, ignore_status=True)
1642    time.sleep(timeout)  # sleep time for sl4a stability
1643    reasons = ad.search_logcat("modem subsystem failure reason", begin_time)
1644    if reasons:
1645        ad.log.info("Modem crash is triggered successfully")
1646        ad.log.info(reasons[-1]["log_message"])
1647        return True
1648    else:
1649        ad.log.warning("There is no modem subsystem failure reason logcat")
1650        return False
1651
1652
1653def phone_switch_to_msim_mode(ad, retries=3, timeout=60):
1654    result = False
1655    if not ad.is_apk_installed("com.google.mdstest"):
1656        raise signals.TestAbortClass("mdstest is not installed")
1657    mode = ad.droid.telephonyGetPhoneCount()
1658    if mode == 2:
1659        ad.log.info("Device already in MSIM mode")
1660        return True
1661    for i in range(retries):
1662        ad.adb.shell(
1663        "setprop persist.vendor.sys.modem.diag.mdlog false", ignore_status=True)
1664        ad.adb.shell(
1665        "setprop persist.sys.modem.diag.mdlog false", ignore_status=True)
1666        disable_qxdm_logger(ad)
1667        cmd = ('am instrument -w -e request "WriteEFS" -e item '
1668               '"/google/pixel_multisim_config" -e data  "02 00 00 00" '
1669               '"com.google.mdstest/com.google.mdstest.instrument.'
1670               'ModemConfigInstrumentation"')
1671        ad.log.info("Switch to MSIM mode by using %s", cmd)
1672        ad.adb.shell(cmd, ignore_status=True)
1673        time.sleep(timeout)
1674        ad.adb.shell("setprop persist.radio.multisim.config dsds")
1675        reboot_device(ad)
1676        # Verify if device is really in msim mode
1677        mode = ad.droid.telephonyGetPhoneCount()
1678        if mode == 2:
1679            ad.log.info("Device correctly switched to MSIM mode")
1680            result = True
1681            if "Sprint" in ad.adb.getprop("gsm.sim.operator.alpha"):
1682                cmd = ('am instrument -w -e request "WriteEFS" -e item '
1683                       '"/google/pixel_dsds_imei_mapping_slot_record" -e data "03"'
1684                       ' "com.google.mdstest/com.google.mdstest.instrument.'
1685                       'ModemConfigInstrumentation"')
1686                ad.log.info("Switch Sprint to IMEI1 slot using %s", cmd)
1687                ad.adb.shell(cmd, ignore_status=True)
1688                time.sleep(timeout)
1689                reboot_device(ad)
1690            break
1691        else:
1692            ad.log.warning("Attempt %d - failed to switch to MSIM", (i + 1))
1693    return result
1694
1695
1696def phone_switch_to_ssim_mode(ad, retries=3, timeout=30):
1697    result = False
1698    if not ad.is_apk_installed("com.google.mdstest"):
1699        raise signals.TestAbortClass("mdstest is not installed")
1700    mode = ad.droid.telephonyGetPhoneCount()
1701    if mode == 1:
1702        ad.log.info("Device already in SSIM mode")
1703        return True
1704    for i in range(retries):
1705        ad.adb.shell(
1706        "setprop persist.vendor.sys.modem.diag.mdlog false", ignore_status=True)
1707        ad.adb.shell(
1708        "setprop persist.sys.modem.diag.mdlog false", ignore_status=True)
1709        disable_qxdm_logger(ad)
1710        cmds = ('am instrument -w -e request "WriteEFS" -e item '
1711                '"/google/pixel_multisim_config" -e data  "01 00 00 00" '
1712                '"com.google.mdstest/com.google.mdstest.instrument.'
1713                'ModemConfigInstrumentation"',
1714                'am instrument -w -e request "WriteEFS" -e item "/nv/item_files'
1715                '/modem/uim/uimdrv/uim_extended_slot_mapping_config" -e data '
1716                '"00 01 02 01" "com.google.mdstest/com.google.mdstest.'
1717                'instrument.ModemConfigInstrumentation"')
1718        for cmd in cmds:
1719            ad.log.info("Switch to SSIM mode by using %s", cmd)
1720            ad.adb.shell(cmd, ignore_status=True)
1721            time.sleep(timeout)
1722        ad.adb.shell("setprop persist.radio.multisim.config ssss")
1723        reboot_device(ad)
1724        # Verify if device is really in ssim mode
1725        mode = ad.droid.telephonyGetPhoneCount()
1726        if mode == 1:
1727            ad.log.info("Device correctly switched to SSIM mode")
1728            result = True
1729            break
1730        else:
1731            ad.log.warning("Attempt %d - failed to switch to SSIM", (i + 1))
1732    return result
1733
1734
1735def lock_lte_band_by_mds(ad, band):
1736    disable_qxdm_logger(ad)
1737    ad.log.info("Write band %s locking to efs file", band)
1738    if band == "4":
1739        item_string = (
1740            "4B 13 26 00 08 00 00 00 40 00 08 00 0B 00 08 00 00 00 00 00 00 00 "
1741            "2F 6E 76 2F 69 74 65 6D 5F 66 69 6C 65 73 2F 6D 6F 64 65 6D 2F 6D "
1742            "6D 6F 64 65 2F 6C 74 65 5F 62 61 6E 64 70 72 65 66 00")
1743    elif band == "13":
1744        item_string = (
1745            "4B 13 26 00 08 00 00 00 40 00 08 00 0A 00 00 10 00 00 00 00 00 00 "
1746            "2F 6E 76 2F 69 74 65 6D 5F 66 69 6C 65 73 2F 6D 6F 64 65 6D 2F 6D "
1747            "6D 6F 64 65 2F 6C 74 65 5F 62 61 6E 64 70 72 65 66 00")
1748    else:
1749        ad.log.error("Band %s is not supported", band)
1750        return False
1751    cmd = ('am instrument -w -e request "%s" com.google.mdstest/com.google.'
1752           'mdstest.instrument.ModemCommandInstrumentation')
1753    for _ in range(3):
1754        if "SUCCESS" in ad.adb.shell(cmd % item_string, ignore_status=True):
1755            break
1756    else:
1757        ad.log.error("Fail to write band by %s" % (cmd % item_string))
1758        return False
1759
1760    # EFS Sync
1761    item_string = "4B 13 30 00 2A 00 2F 00"
1762
1763    for _ in range(3):
1764        if "SUCCESS" in ad.adb.shell(cmd % item_string, ignore_status=True):
1765            break
1766    else:
1767        ad.log.error("Fail to sync efs by %s" % (cmd % item_string))
1768        return False
1769    time.sleep(5)
1770    reboot_device(ad)
1771
1772
1773def get_cell_data_roaming_state_by_adb(ad):
1774    """Get Cell Data Roaming state. True for enabled, False for disabled"""
1775    state_mapping = {"1": True, "0": False}
1776    return state_mapping[ad.adb.shell("settings get global data_roaming")]
1777
1778
1779def set_cell_data_roaming_state_by_adb(ad, state):
1780    """Set Cell Data Roaming state."""
1781    state_mapping = {True: "1", False: "0"}
1782    ad.log.info("Set data roaming to %s", state)
1783    ad.adb.shell("settings put global data_roaming %s" % state_mapping[state])
1784
1785
1786def toggle_cell_data_roaming(ad, state):
1787    """Enable cell data roaming for default data subscription.
1788
1789    Wait for the data roaming status to be DATA_STATE_CONNECTED
1790        or DATA_STATE_DISCONNECTED.
1791
1792    Args:
1793        log: Log object.
1794        ad: Android Device Object.
1795        state: True or False for enable or disable cell data roaming.
1796
1797    Returns:
1798        True if success.
1799        False if failed.
1800    """
1801    state_int = {True: DATA_ROAMING_ENABLE, False: DATA_ROAMING_DISABLE}[state]
1802    action_str = {True: "Enable", False: "Disable"}[state]
1803    if ad.droid.connectivityCheckDataRoamingMode() == state:
1804        ad.log.info("Data roaming is already in state %s", state)
1805        return True
1806    if not ad.droid.connectivitySetDataRoaming(state_int):
1807        ad.error.info("Fail to config data roaming into state %s", state)
1808        return False
1809    if ad.droid.connectivityCheckDataRoamingMode() == state:
1810        ad.log.info("Data roaming is configured into state %s", state)
1811        return True
1812    else:
1813        ad.log.error("Data roaming is not configured into state %s", state)
1814        return False
1815
1816
1817def verify_incall_state(log, ads, expected_status):
1818    """Verify phones in incall state or not.
1819
1820    Verify if all phones in the array <ads> are in <expected_status>.
1821
1822    Args:
1823        log: Log object.
1824        ads: Array of Android Device Object. All droid in this array will be tested.
1825        expected_status: If True, verify all Phones in incall state.
1826            If False, verify all Phones not in incall state.
1827
1828    """
1829    result = True
1830    for ad in ads:
1831        if ad.droid.telecomIsInCall() is not expected_status:
1832            ad.log.error("InCall status:%s, expected:%s",
1833                         ad.droid.telecomIsInCall(), expected_status)
1834            result = False
1835    return result
1836
1837
1838def verify_active_call_number(log, ad, expected_number):
1839    """Verify the number of current active call.
1840
1841    Verify if the number of current active call in <ad> is
1842        equal to <expected_number>.
1843
1844    Args:
1845        ad: Android Device Object.
1846        expected_number: Expected active call number.
1847    """
1848    calls = ad.droid.telecomCallGetCallIds()
1849    if calls is None:
1850        actual_number = 0
1851    else:
1852        actual_number = len(calls)
1853    if actual_number != expected_number:
1854        ad.log.error("Active Call number is %s, expecting", actual_number,
1855                     expected_number)
1856        return False
1857    return True
1858
1859
1860def num_active_calls(log, ad):
1861    """Get the count of current active calls.
1862
1863    Args:
1864        log: Log object.
1865        ad: Android Device Object.
1866
1867    Returns:
1868        Count of current active calls.
1869    """
1870    calls = ad.droid.telecomCallGetCallIds()
1871    return len(calls) if calls else 0
1872
1873
1874def get_carrier_provisioning_for_subscription(ad, feature_flag,
1875                                              tech, sub_id=None):
1876    """ Gets Provisioning Values for Subscription Id
1877
1878    Args:
1879        ad: Android device object.
1880        sub_id: Subscription Id
1881        feature_flag: voice, video, ut, sms
1882        tech: wlan, wwan
1883
1884    """
1885    try:
1886        if sub_id is None:
1887            sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
1888        result = ad.droid.imsMmTelIsSupported(sub_id, feature_flag, tech)
1889        ad.log.info("SubId %s - imsMmTelIsSupported for %s on %s - %s",
1890                    sub_id, feature_flag, tech, result)
1891        return result
1892    except Exception as e:
1893        ad.log.error(e)
1894        return False
1895
1896
1897def _wait_for_droid_in_state(log, ad, max_time, state_check_func, *args,
1898                             **kwargs):
1899    while max_time >= 0:
1900        if state_check_func(log, ad, *args, **kwargs):
1901            return True
1902
1903        time.sleep(WAIT_TIME_BETWEEN_STATE_CHECK)
1904        max_time -= WAIT_TIME_BETWEEN_STATE_CHECK
1905
1906    return False
1907
1908
1909def _wait_for_droid_in_state_for_subscription(
1910        log, ad, sub_id, max_time, state_check_func, *args, **kwargs):
1911    while max_time >= 0:
1912        if state_check_func(log, ad, sub_id, *args, **kwargs):
1913            return True
1914
1915        time.sleep(WAIT_TIME_BETWEEN_STATE_CHECK)
1916        max_time -= WAIT_TIME_BETWEEN_STATE_CHECK
1917
1918    return False
1919
1920
1921def _wait_for_droids_in_state(log, ads, max_time, state_check_func, *args,
1922                              **kwargs):
1923    while max_time > 0:
1924        success = True
1925        for ad in ads:
1926            if not state_check_func(log, ad, *args, **kwargs):
1927                success = False
1928                break
1929        if success:
1930            return True
1931
1932        time.sleep(WAIT_TIME_BETWEEN_STATE_CHECK)
1933        max_time -= WAIT_TIME_BETWEEN_STATE_CHECK
1934
1935    return False
1936
1937
1938def _is_attached(log, ad, voice_or_data):
1939    return _is_attached_for_subscription(
1940        log, ad, ad.droid.subscriptionGetDefaultSubId(), voice_or_data)
1941
1942
1943def _is_attached_for_subscription(log, ad, sub_id, voice_or_data):
1944    rat = get_network_rat_for_subscription(log, ad, sub_id, voice_or_data)
1945    ad.log.info("Sub_id %s network RAT is %s for %s", sub_id, rat,
1946                voice_or_data)
1947    return rat != RAT_UNKNOWN
1948
1949
1950def is_voice_attached(log, ad):
1951    return _is_attached_for_subscription(
1952        log, ad, ad.droid.subscriptionGetDefaultSubId(), NETWORK_SERVICE_VOICE)
1953
1954
1955def wait_for_data_attach(log, ad, max_time):
1956    """Wait for android device to attach on data.
1957
1958    Args:
1959        log: log object.
1960        ad:  android device.
1961        max_time: maximal wait time.
1962
1963    Returns:
1964        Return True if device attach data within max_time.
1965        Return False if timeout.
1966    """
1967    return _wait_for_droid_in_state(log, ad, max_time, _is_attached,
1968                                    NETWORK_SERVICE_DATA)
1969
1970
1971def wait_for_data_attach_for_subscription(log, ad, sub_id, max_time):
1972    """Wait for android device to attach on data in subscription id.
1973
1974    Args:
1975        log: log object.
1976        ad:  android device.
1977        sub_id: subscription id.
1978        max_time: maximal wait time.
1979
1980    Returns:
1981        Return True if device attach data within max_time.
1982        Return False if timeout.
1983    """
1984    return _wait_for_droid_in_state_for_subscription(
1985        log, ad, sub_id, max_time, _is_attached_for_subscription,
1986        NETWORK_SERVICE_DATA)
1987
1988
1989def get_phone_number(log, ad):
1990    """Get phone number for default subscription
1991
1992    Args:
1993        log: log object.
1994        ad: Android device object.
1995
1996    Returns:
1997        Phone number.
1998    """
1999    return get_phone_number_for_subscription(log, ad,
2000                                             get_outgoing_voice_sub_id(ad))
2001
2002
2003def get_phone_number_for_subscription(log, ad, subid):
2004    """Get phone number for subscription
2005
2006    Args:
2007        log: log object.
2008        ad: Android device object.
2009        subid: subscription id.
2010
2011    Returns:
2012        Phone number.
2013    """
2014    number = None
2015    try:
2016        number = ad.telephony['subscription'][subid]['phone_num']
2017    except KeyError:
2018        number = ad.droid.telephonyGetLine1NumberForSubscription(subid)
2019    return number
2020
2021
2022def set_phone_number(log, ad, phone_num):
2023    """Set phone number for default subscription
2024
2025    Args:
2026        log: log object.
2027        ad: Android device object.
2028        phone_num: phone number string.
2029
2030    Returns:
2031        True if success.
2032    """
2033    return set_phone_number_for_subscription(log, ad,
2034                                             get_outgoing_voice_sub_id(ad),
2035                                             phone_num)
2036
2037
2038def set_phone_number_for_subscription(log, ad, subid, phone_num):
2039    """Set phone number for subscription
2040
2041    Args:
2042        log: log object.
2043        ad: Android device object.
2044        subid: subscription id.
2045        phone_num: phone number string.
2046
2047    Returns:
2048        True if success.
2049    """
2050    try:
2051        ad.telephony['subscription'][subid]['phone_num'] = phone_num
2052    except Exception:
2053        return False
2054    return True
2055
2056
2057def get_operator_name(log, ad, subId=None):
2058    """Get operator name (e.g. vzw, tmo) of droid.
2059
2060    Args:
2061        ad: Android device object.
2062        sub_id: subscription ID
2063            Optional, default is None
2064
2065    Returns:
2066        Operator name.
2067    """
2068    try:
2069        if subId is not None:
2070            result = operator_name_from_plmn_id(
2071                ad.droid.telephonyGetNetworkOperatorForSubscription(subId))
2072        else:
2073            result = operator_name_from_plmn_id(
2074                ad.droid.telephonyGetNetworkOperator())
2075    except KeyError:
2076        try:
2077            if subId is not None:
2078                result = ad.droid.telephonyGetNetworkOperatorNameForSubscription(
2079                    subId)
2080            else:
2081                result = ad.droid.telephonyGetNetworkOperatorName()
2082            result = operator_name_from_network_name(result)
2083        except Exception:
2084            result = CARRIER_UNKNOWN
2085    ad.log.info("Operator Name is %s", result)
2086    return result
2087
2088
2089def get_model_name(ad):
2090    """Get android device model name
2091
2092    Args:
2093        ad: Android device object
2094
2095    Returns:
2096        model name string
2097    """
2098    # TODO: Create translate table.
2099    model = ad.model
2100    if (model.startswith(AOSP_PREFIX)):
2101        model = model[len(AOSP_PREFIX):]
2102    return model
2103
2104
2105def is_droid_in_rat_family(log, ad, rat_family, voice_or_data=None):
2106    return is_droid_in_rat_family_for_subscription(
2107        log, ad, ad.droid.subscriptionGetDefaultSubId(), rat_family,
2108        voice_or_data)
2109
2110
2111def is_droid_in_rat_family_for_subscription(log,
2112                                            ad,
2113                                            sub_id,
2114                                            rat_family,
2115                                            voice_or_data=None):
2116    return is_droid_in_rat_family_list_for_subscription(
2117        log, ad, sub_id, [rat_family], voice_or_data)
2118
2119
2120def is_droid_in_rat_familiy_list(log, ad, rat_family_list, voice_or_data=None):
2121    return is_droid_in_rat_family_list_for_subscription(
2122        log, ad, ad.droid.subscriptionGetDefaultSubId(), rat_family_list,
2123        voice_or_data)
2124
2125
2126def is_droid_in_rat_family_list_for_subscription(log,
2127                                                 ad,
2128                                                 sub_id,
2129                                                 rat_family_list,
2130                                                 voice_or_data=None):
2131    service_list = [NETWORK_SERVICE_DATA, NETWORK_SERVICE_VOICE]
2132    if voice_or_data:
2133        service_list = [voice_or_data]
2134
2135    for service in service_list:
2136        nw_rat = get_network_rat_for_subscription(log, ad, sub_id, service)
2137        if nw_rat == RAT_UNKNOWN or not is_valid_rat(nw_rat):
2138            continue
2139        if rat_family_from_rat(nw_rat) in rat_family_list:
2140            return True
2141    return False
2142
2143
2144def is_droid_in_network_generation(log, ad, nw_gen, voice_or_data):
2145    """Checks if a droid in expected network generation ("2g", "3g" or "4g").
2146
2147    Args:
2148        log: log object.
2149        ad: android device.
2150        nw_gen: expected generation "4g", "3g", "2g".
2151        voice_or_data: check voice network generation or data network generation
2152            This parameter is optional. If voice_or_data is None, then if
2153            either voice or data in expected generation, function will return True.
2154
2155    Returns:
2156        True if droid in expected network generation. Otherwise False.
2157    """
2158    return is_droid_in_network_generation_for_subscription(
2159        log, ad, ad.droid.subscriptionGetDefaultSubId(), nw_gen, voice_or_data)
2160
2161
2162def is_droid_in_network_generation_for_subscription(log, ad, sub_id, nw_gen,
2163                                                    voice_or_data):
2164    """Checks if a droid in expected network generation ("2g", "3g" or "4g").
2165
2166    Args:
2167        log: log object.
2168        ad: android device.
2169        nw_gen: expected generation "4g", "3g", "2g".
2170        voice_or_data: check voice network generation or data network generation
2171            This parameter is optional. If voice_or_data is None, then if
2172            either voice or data in expected generation, function will return True.
2173
2174    Returns:
2175        True if droid in expected network generation. Otherwise False.
2176    """
2177    service_list = [NETWORK_SERVICE_DATA, NETWORK_SERVICE_VOICE]
2178
2179    if voice_or_data:
2180        service_list = [voice_or_data]
2181
2182    for service in service_list:
2183        nw_rat = get_network_rat_for_subscription(log, ad, sub_id, service)
2184        ad.log.info("%s network rat is %s", service, nw_rat)
2185        if nw_rat == RAT_UNKNOWN or not is_valid_rat(nw_rat):
2186            continue
2187
2188        if rat_generation_from_rat(nw_rat) == nw_gen:
2189            ad.log.info("%s network rat %s is expected %s", service, nw_rat,
2190                        nw_gen)
2191            return True
2192        else:
2193            ad.log.info("%s network rat %s is %s, does not meet expected %s",
2194                        service, nw_rat, rat_generation_from_rat(nw_rat),
2195                        nw_gen)
2196            return False
2197
2198    return False
2199
2200
2201def get_network_rat(log, ad, voice_or_data):
2202    """Get current network type (Voice network type, or data network type)
2203       for default subscription id
2204
2205    Args:
2206        ad: Android Device Object
2207        voice_or_data: Input parameter indicating to get voice network type or
2208            data network type.
2209
2210    Returns:
2211        Current voice/data network type.
2212    """
2213    return get_network_rat_for_subscription(
2214        log, ad, ad.droid.subscriptionGetDefaultSubId(), voice_or_data)
2215
2216
2217def get_network_rat_for_subscription(log, ad, sub_id, voice_or_data):
2218    """Get current network type (Voice network type, or data network type)
2219       for specified subscription id
2220
2221    Args:
2222        ad: Android Device Object
2223        sub_id: subscription ID
2224        voice_or_data: Input parameter indicating to get voice network type or
2225            data network type.
2226
2227    Returns:
2228        Current voice/data network type.
2229    """
2230    if voice_or_data == NETWORK_SERVICE_VOICE:
2231        ret_val = ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription(
2232            sub_id)
2233    elif voice_or_data == NETWORK_SERVICE_DATA:
2234        ret_val = ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription(
2235            sub_id)
2236    else:
2237        ret_val = ad.droid.telephonyGetNetworkTypeForSubscription(sub_id)
2238
2239    if ret_val is None:
2240        log.error("get_network_rat(): Unexpected null return value")
2241        return RAT_UNKNOWN
2242    else:
2243        return ret_val
2244
2245
2246def get_network_gen(log, ad, voice_or_data):
2247    """Get current network generation string (Voice network type, or data network type)
2248
2249    Args:
2250        ad: Android Device Object
2251        voice_or_data: Input parameter indicating to get voice network generation
2252            or data network generation.
2253
2254    Returns:
2255        Current voice/data network generation.
2256    """
2257    return get_network_gen_for_subscription(
2258        log, ad, ad.droid.subscriptionGetDefaultSubId(), voice_or_data)
2259
2260
2261def get_network_gen_for_subscription(log, ad, sub_id, voice_or_data):
2262    """Get current network generation string (Voice network type, or data network type)
2263
2264    Args:
2265        ad: Android Device Object
2266        voice_or_data: Input parameter indicating to get voice network generation
2267            or data network generation.
2268
2269    Returns:
2270        Current voice/data network generation.
2271    """
2272    try:
2273        return rat_generation_from_rat(
2274            get_network_rat_for_subscription(log, ad, sub_id, voice_or_data))
2275    except KeyError as e:
2276        ad.log.error("KeyError %s", e)
2277        return GEN_UNKNOWN
2278
2279
2280def check_voice_mail_count(log, ad, voice_mail_count_before,
2281                           voice_mail_count_after):
2282    """function to check if voice mail count is correct after leaving a new voice message.
2283    """
2284    return get_voice_mail_count_check_function(get_operator_name(log, ad))(
2285        voice_mail_count_before, voice_mail_count_after)
2286
2287
2288def get_voice_mail_number(log, ad):
2289    """function to get the voice mail number
2290    """
2291    voice_mail_number = get_voice_mail_check_number(get_operator_name(log, ad))
2292    if voice_mail_number is None:
2293        return get_phone_number(log, ad)
2294    return voice_mail_number
2295
2296
2297def reset_preferred_network_type_to_allowable_range(log, ad):
2298    """If preferred network type is not in allowable range, reset to GEN_4G
2299    preferred network type.
2300
2301    Args:
2302        log: log object
2303        ad: android device object
2304
2305    Returns:
2306        None
2307    """
2308    for sub_id, sub_info in ad.telephony["subscription"].items():
2309        current_preference = \
2310            ad.droid.telephonyGetPreferredNetworkTypesForSubscription(sub_id)
2311        ad.log.debug("sub_id network preference is %s", current_preference)
2312        try:
2313            if current_preference not in get_allowable_network_preference(
2314                    sub_info["operator"], sub_info["phone_type"]):
2315                network_preference = network_preference_for_generation(
2316                    GEN_4G, sub_info["operator"], sub_info["phone_type"])
2317                ad.droid.telephonySetPreferredNetworkTypesForSubscription(
2318                    network_preference, sub_id)
2319        except KeyError:
2320            pass
2321
2322
2323def set_phone_screen_on(log, ad, screen_on_time=MAX_SCREEN_ON_TIME):
2324    """Set phone screen on time.
2325
2326    Args:
2327        log: Log object.
2328        ad: Android device object.
2329        screen_on_time: screen on time.
2330            This is optional, default value is MAX_SCREEN_ON_TIME.
2331    Returns:
2332        True if set successfully.
2333    """
2334    ad.droid.setScreenTimeout(screen_on_time)
2335    return screen_on_time == ad.droid.getScreenTimeout()
2336
2337
2338def set_phone_silent_mode(log, ad, silent_mode=True):
2339    """Set phone silent mode.
2340
2341    Args:
2342        log: Log object.
2343        ad: Android device object.
2344        silent_mode: set phone silent or not.
2345            This is optional, default value is True (silent mode on).
2346    Returns:
2347        True if set successfully.
2348    """
2349    ad.droid.toggleRingerSilentMode(silent_mode)
2350    ad.droid.setMediaVolume(0)
2351    ad.droid.setVoiceCallVolume(0)
2352    ad.droid.setAlarmVolume(0)
2353    ad.adb.ensure_root()
2354    ad.adb.shell("setprop ro.audio.silent 1", ignore_status=True)
2355    ad.adb.shell("cmd notification set_dnd on", ignore_status=True)
2356    return silent_mode == ad.droid.checkRingerSilentMode()
2357
2358
2359def set_preferred_network_mode_pref(log,
2360                                    ad,
2361                                    sub_id,
2362                                    network_preference,
2363                                    timeout=WAIT_TIME_ANDROID_STATE_SETTLING):
2364    """Set Preferred Network Mode for Sub_id
2365    Args:
2366        log: Log object.
2367        ad: Android device object.
2368        sub_id: Subscription ID.
2369        network_preference: Network Mode Type
2370    """
2371    begin_time = get_device_epoch_time(ad)
2372    if ad.droid.telephonyGetPreferredNetworkTypesForSubscription(
2373            sub_id) == network_preference:
2374        ad.log.info("Current ModePref for Sub %s is in %s", sub_id,
2375                    network_preference)
2376        return True
2377    ad.log.info("Setting ModePref to %s for Sub %s", network_preference,
2378                sub_id)
2379    while timeout >= 0:
2380        if ad.droid.telephonySetPreferredNetworkTypesForSubscription(
2381                network_preference, sub_id):
2382            return True
2383        time.sleep(WAIT_TIME_BETWEEN_STATE_CHECK)
2384        timeout = timeout - WAIT_TIME_BETWEEN_STATE_CHECK
2385    error_msg = "Failed to set sub_id %s PreferredNetworkType to %s" % (
2386        sub_id, network_preference)
2387    search_results = ad.search_logcat(
2388        "REQUEST_SET_PREFERRED_NETWORK_TYPE error", begin_time=begin_time)
2389    if search_results:
2390        log_message = search_results[-1]["log_message"]
2391        if "DEVICE_IN_USE" in log_message:
2392            error_msg = "%s due to DEVICE_IN_USE" % error_msg
2393        else:
2394            error_msg = "%s due to %s" % (error_msg, log_message)
2395    ad.log.error(error_msg)
2396    return False
2397
2398
2399def set_call_state_listen_level(log, ad, value, sub_id):
2400    """Set call state listen level for subscription id.
2401
2402    Args:
2403        log: Log object.
2404        ad: Android device object.
2405        value: True or False
2406        sub_id :Subscription ID.
2407
2408    Returns:
2409        True or False
2410    """
2411    if sub_id == INVALID_SUB_ID:
2412        log.error("Invalid Subscription ID")
2413        return False
2414    ad.droid.telephonyAdjustPreciseCallStateListenLevelForSubscription(
2415        "Foreground", value, sub_id)
2416    ad.droid.telephonyAdjustPreciseCallStateListenLevelForSubscription(
2417        "Ringing", value, sub_id)
2418    ad.droid.telephonyAdjustPreciseCallStateListenLevelForSubscription(
2419        "Background", value, sub_id)
2420    return True
2421
2422
2423def is_event_match(event, field, value):
2424    """Return if <field> in "event" match <value> or not.
2425
2426    Args:
2427        event: event to test. This event need to have <field>.
2428        field: field to match.
2429        value: value to match.
2430
2431    Returns:
2432        True if <field> in "event" match <value>.
2433        False otherwise.
2434    """
2435    return is_event_match_for_list(event, field, [value])
2436
2437
2438def is_event_match_for_list(event, field, value_list):
2439    """Return if <field> in "event" match any one of the value
2440        in "value_list" or not.
2441
2442    Args:
2443        event: event to test. This event need to have <field>.
2444        field: field to match.
2445        value_list: a list of value to match.
2446
2447    Returns:
2448        True if <field> in "event" match one of the value in "value_list".
2449        False otherwise.
2450    """
2451    try:
2452        value_in_event = event['data'][field]
2453    except KeyError:
2454        return False
2455    for value in value_list:
2456        if value_in_event == value:
2457            return True
2458    return False
2459
2460
2461def is_network_call_back_event_match(event, network_callback_id,
2462                                     network_callback_event):
2463    try:
2464        return (
2465            (network_callback_id == event['data'][NetworkCallbackContainer.ID])
2466            and (network_callback_event == event['data']
2467                 [NetworkCallbackContainer.NETWORK_CALLBACK_EVENT]))
2468    except KeyError:
2469        return False
2470
2471
2472def is_build_id(log, ad, build_id):
2473    """Return if ad's build id is the same as input parameter build_id.
2474
2475    Args:
2476        log: log object.
2477        ad: android device object.
2478        build_id: android build id.
2479
2480    Returns:
2481        True if ad's build id is the same as input parameter build_id.
2482        False otherwise.
2483    """
2484    actual_bid = ad.droid.getBuildID()
2485
2486    ad.log.info("BUILD DISPLAY: %s", ad.droid.getBuildDisplay())
2487    #In case we want to log more stuff/more granularity...
2488    #log.info("{} BUILD ID:{} ".format(ad.serial, ad.droid.getBuildID()))
2489    #log.info("{} BUILD FINGERPRINT: {} "
2490    # .format(ad.serial), ad.droid.getBuildFingerprint())
2491    #log.info("{} BUILD TYPE: {} "
2492    # .format(ad.serial), ad.droid.getBuildType())
2493    #log.info("{} BUILD NUMBER: {} "
2494    # .format(ad.serial), ad.droid.getBuildNumber())
2495    if actual_bid.upper() != build_id.upper():
2496        ad.log.error("%s: Incorrect Build ID", ad.model)
2497        return False
2498    return True
2499
2500
2501def is_uri_equivalent(uri1, uri2):
2502    """Check whether two input uris match or not.
2503
2504    Compare Uris.
2505        If Uris are tel URI, it will only take the digit part
2506        and compare as phone number.
2507        Else, it will just do string compare.
2508
2509    Args:
2510        uri1: 1st uri to be compared.
2511        uri2: 2nd uri to be compared.
2512
2513    Returns:
2514        True if two uris match. Otherwise False.
2515    """
2516
2517    #If either is None/empty we return false
2518    if not uri1 or not uri2:
2519        return False
2520
2521    try:
2522        if uri1.startswith('tel:') and uri2.startswith('tel:'):
2523            uri1_number = get_number_from_tel_uri(uri1)
2524            uri2_number = get_number_from_tel_uri(uri2)
2525            return check_phone_number_match(uri1_number, uri2_number)
2526        else:
2527            return uri1 == uri2
2528    except AttributeError as e:
2529        return False
2530
2531
2532def get_call_uri(ad, call_id):
2533    """Get call's uri field.
2534
2535    Get Uri for call_id in ad.
2536
2537    Args:
2538        ad: android device object.
2539        call_id: the call id to get Uri from.
2540
2541    Returns:
2542        call's Uri if call is active and have uri field. None otherwise.
2543    """
2544    try:
2545        call_detail = ad.droid.telecomCallGetDetails(call_id)
2546        return call_detail["Handle"]["Uri"]
2547    except:
2548        return None
2549
2550
2551def get_number_from_tel_uri(uri):
2552    """Get Uri number from tel uri
2553
2554    Args:
2555        uri: input uri
2556
2557    Returns:
2558        If input uri is tel uri, return the number part.
2559        else return None.
2560    """
2561    if uri.startswith('tel:'):
2562        uri_number = ''.join(
2563            i for i in urllib.parse.unquote(uri) if i.isdigit())
2564        return uri_number
2565    else:
2566        return None
2567
2568
2569def install_carriersettings_apk(ad, carriersettingsapk, skip_setup_wizard=True):
2570    """ Carrier Setting Installation Steps
2571
2572    Pull sl4a apk from device. Terminate all sl4a sessions,
2573    Reboot the device to bootloader, wipe the device by fastboot.
2574    Reboot the device. wait for device to complete booting
2575    """
2576    status = True
2577    if carriersettingsapk is None:
2578        ad.log.warning("CarrierSettingsApk is not provided, aborting")
2579        return False
2580    ad.log.info("Push carriersettings apk to the Android device.")
2581    android_apk_path = "/product/priv-app/CarrierSettings/CarrierSettings.apk"
2582    ad.adb.push("%s %s" % (carriersettingsapk, android_apk_path))
2583    ad.stop_services()
2584
2585    attempts = 3
2586    for i in range(1, attempts + 1):
2587        try:
2588            if ad.serial in list_adb_devices():
2589                ad.log.info("Reboot to bootloader")
2590                ad.adb.reboot("bootloader", ignore_status=True)
2591                time.sleep(30)
2592            if ad.serial in list_fastboot_devices():
2593                ad.log.info("Reboot in fastboot")
2594                ad.fastboot.reboot()
2595            ad.wait_for_boot_completion()
2596            ad.root_adb()
2597            if ad.is_sl4a_installed():
2598                break
2599            time.sleep(10)
2600            break
2601        except Exception as e:
2602            ad.log.warning(e)
2603            if i == attempts:
2604                abort_all_tests(log, str(e))
2605            time.sleep(5)
2606    try:
2607        ad.start_adb_logcat()
2608    except:
2609        ad.log.error("Failed to start adb logcat!")
2610    if skip_setup_wizard:
2611        ad.exit_setup_wizard()
2612    return status
2613
2614
2615def bring_up_sl4a(ad, attemps=3):
2616    for i in range(attemps):
2617        try:
2618            droid, ed = ad.get_droid()
2619            ed.start()
2620            ad.log.info("Brought up new sl4a session")
2621            break
2622        except Exception as e:
2623            if i < attemps - 1:
2624                ad.log.info(e)
2625                time.sleep(10)
2626            else:
2627                ad.log.error(e)
2628                raise
2629
2630
2631def reboot_device(ad, recover_sim_state=True):
2632    sim_state = is_sim_ready(ad.log, ad)
2633    ad.reboot()
2634    if ad.qxdm_log:
2635        start_qxdm_logger(ad)
2636    ad.unlock_screen()
2637    if recover_sim_state:
2638        if not unlock_sim(ad):
2639            ad.log.error("Unable to unlock SIM")
2640            return False
2641        if sim_state and not _wait_for_droid_in_state(
2642                log, ad, MAX_WAIT_TIME_FOR_STATE_CHANGE, is_sim_ready):
2643            ad.log.error("Sim state didn't reach pre-reboot ready state")
2644            return False
2645    return True
2646
2647
2648def unlocking_device(ad, device_password=None):
2649    """First unlock device attempt, required after reboot"""
2650    ad.unlock_screen(device_password)
2651    time.sleep(2)
2652    ad.adb.wait_for_device(timeout=180)
2653    if not ad.is_waiting_for_unlock_pin():
2654        return True
2655    else:
2656        ad.unlock_screen(device_password)
2657        time.sleep(2)
2658        ad.adb.wait_for_device(timeout=180)
2659        if ad.wait_for_window_ready():
2660            return True
2661    ad.log.error("Unable to unlock to user window")
2662    return False
2663
2664
2665def refresh_sl4a_session(ad):
2666    try:
2667        ad.droid.logI("Checking SL4A connection")
2668        ad.log.debug("Existing sl4a session is active")
2669        return True
2670    except Exception as e:
2671        ad.log.warning("Existing sl4a session is NOT active: %s", e)
2672    try:
2673        ad.terminate_all_sessions()
2674    except Exception as e:
2675        ad.log.info("terminate_all_sessions with error %s", e)
2676    ad.ensure_screen_on()
2677    ad.log.info("Open new sl4a connection")
2678    bring_up_sl4a(ad)
2679
2680
2681def get_sim_state(ad):
2682    try:
2683        state = ad.droid.telephonyGetSimState()
2684    except Exception as e:
2685        ad.log.error(e)
2686        state = ad.adb.getprop("gsm.sim.state")
2687    return state
2688
2689
2690def is_sim_locked(ad):
2691    return get_sim_state(ad) == SIM_STATE_PIN_REQUIRED
2692
2693
2694def is_sim_lock_enabled(ad):
2695    # TODO: add sl4a fascade to check if sim is locked
2696    return getattr(ad, "is_sim_locked", False)
2697
2698
2699def unlock_sim(ad):
2700    #The puk and pin can be provided in testbed config file.
2701    #"AndroidDevice": [{"serial": "84B5T15A29018214",
2702    #                   "adb_logcat_param": "-b all",
2703    #                   "puk": "12345678",
2704    #                   "puk_pin": "1234"}]
2705    if not is_sim_locked(ad):
2706        return True
2707    else:
2708        ad.is_sim_locked = True
2709    puk_pin = getattr(ad, "puk_pin", "1111")
2710    try:
2711        if not hasattr(ad, 'puk'):
2712            ad.log.info("Enter SIM pin code")
2713            ad.droid.telephonySupplyPin(puk_pin)
2714        else:
2715            ad.log.info("Enter PUK code and pin")
2716            ad.droid.telephonySupplyPuk(ad.puk, puk_pin)
2717    except:
2718        # if sl4a is not available, use adb command
2719        ad.unlock_screen(puk_pin)
2720        if is_sim_locked(ad):
2721            ad.unlock_screen(puk_pin)
2722    time.sleep(30)
2723    return not is_sim_locked(ad)
2724
2725
2726def send_dialer_secret_code(ad, secret_code):
2727    """Send dialer secret code.
2728
2729    ad: android device controller
2730    secret_code: the secret code to be sent to dialer. the string between
2731                 code prefix *#*# and code postfix #*#*. *#*#<xxx>#*#*
2732    """
2733    action = 'android.provider.Telephony.SECRET_CODE'
2734    uri = 'android_secret_code://%s' % secret_code
2735    intent = ad.droid.makeIntent(
2736        action,
2737        uri,
2738        None,  # type
2739        None,  # extras
2740        None,  # categories,
2741        None,  # packagename,
2742        None,  # classname,
2743        0x01000000)  # flags
2744    ad.log.info('Issuing dialer secret dialer code: %s', secret_code)
2745    ad.droid.sendBroadcastIntent(intent)
2746
2747
2748def enable_radio_log_on(ad):
2749    if ad.adb.getprop("persist.vendor.radio.adb_log_on") != "1":
2750        ad.log.info("Enable radio adb_log_on and reboot")
2751        adb_disable_verity(ad)
2752        ad.adb.shell("setprop persist.vendor.radio.adb_log_on 1")
2753        reboot_device(ad)
2754
2755
2756def adb_disable_verity(ad):
2757    if ad.adb.getprop("ro.boot.veritymode") == "enforcing":
2758        ad.adb.disable_verity()
2759        reboot_device(ad)
2760        ad.adb.remount()
2761
2762
2763def recover_build_id(ad):
2764    build_fingerprint = ad.adb.getprop(
2765        "ro.vendor.build.fingerprint") or ad.adb.getprop(
2766            "ro.build.fingerprint")
2767    if not build_fingerprint:
2768        return
2769    build_id = build_fingerprint.split("/")[3]
2770    if ad.adb.getprop("ro.build.id") != build_id:
2771        build_id_override(ad, build_id)
2772
2773
2774def enable_privacy_usage_diagnostics(ad):
2775    try:
2776        ad.ensure_screen_on()
2777        ad.send_keycode('HOME')
2778    # open the UI page on which we need to enable the setting
2779        cmd = ('am start -n com.google.android.gms/com.google.android.gms.'
2780               'usagereporting.settings.UsageReportingActivity')
2781        ad.adb.shell(cmd)
2782    # perform the toggle
2783        ad.send_keycode('TAB')
2784        ad.send_keycode('ENTER')
2785    except Exception:
2786        ad.log.info("Unable to toggle Usage and Diagnostics")
2787
2788
2789def build_id_override(ad, new_build_id=None, postfix=None):
2790    build_fingerprint = ad.adb.getprop(
2791        "ro.build.fingerprint") or ad.adb.getprop(
2792            "ro.vendor.build.fingerprint")
2793    if build_fingerprint:
2794        build_id = build_fingerprint.split("/")[3]
2795    else:
2796        build_id = None
2797    existing_build_id = ad.adb.getprop("ro.build.id")
2798    if postfix is not None and postfix in build_id:
2799        ad.log.info("Build id already contains %s", postfix)
2800        return
2801    if not new_build_id:
2802        if postfix and build_id:
2803            new_build_id = "%s.%s" % (build_id, postfix)
2804    if not new_build_id or existing_build_id == new_build_id:
2805        return
2806    ad.log.info("Override build id %s with %s", existing_build_id,
2807                new_build_id)
2808    enable_privacy_usage_diagnostics(ad)
2809    adb_disable_verity(ad)
2810    ad.adb.remount()
2811    if "backup.prop" not in ad.adb.shell("ls /sdcard/"):
2812        ad.adb.shell("cp /system/build.prop /sdcard/backup.prop")
2813    ad.adb.shell("cat /system/build.prop | grep -v ro.build.id > /sdcard/test.prop")
2814    ad.adb.shell("echo ro.build.id=%s >> /sdcard/test.prop" % new_build_id)
2815    ad.adb.shell("cp /sdcard/test.prop /system/build.prop")
2816    reboot_device(ad)
2817    ad.log.info("ro.build.id = %s", ad.adb.getprop("ro.build.id"))
2818
2819
2820def enable_connectivity_metrics(ad):
2821    cmds = [
2822        "pm enable com.android.connectivity.metrics",
2823        "am startservice -a com.google.android.gms.usagereporting.OPTIN_UR",
2824        "am broadcast -a com.google.gservices.intent.action.GSERVICES_OVERRIDE"
2825        " -e usagestats:connectivity_metrics:enable_data_collection 1",
2826        "am broadcast -a com.google.gservices.intent.action.GSERVICES_OVERRIDE"
2827        " -e usagestats:connectivity_metrics:telephony_snapshot_period_millis 180000"
2828        # By default it turn on all modules
2829        #"am broadcast -a com.google.gservices.intent.action.GSERVICES_OVERRIDE"
2830        #" -e usagestats:connectivity_metrics:data_collection_bitmap 62"
2831    ]
2832    for cmd in cmds:
2833        ad.adb.shell(cmd, ignore_status=True)
2834
2835
2836def force_connectivity_metrics_upload(ad):
2837    cmd = "cmd jobscheduler run --force com.android.connectivity.metrics %s"
2838    for job_id in [2, 3, 5, 4, 1, 6]:
2839        ad.adb.shell(cmd % job_id, ignore_status=True)
2840
2841
2842def system_file_push(ad, src_file_path, dst_file_path):
2843    """Push system file on a device.
2844
2845    Push system file need to change some system setting and remount.
2846    """
2847    cmd = "%s %s" % (src_file_path, dst_file_path)
2848    out = ad.adb.push(cmd, timeout=300, ignore_status=True)
2849    skip_sl4a = True if "sl4a.apk" in src_file_path else False
2850    if "Read-only file system" in out:
2851        ad.log.info("Change read-only file system")
2852        adb_disable_verity(ad)
2853        out = ad.adb.push(cmd, timeout=300, ignore_status=True)
2854        if "Read-only file system" in out:
2855            ad.reboot(skip_sl4a)
2856            out = ad.adb.push(cmd, timeout=300, ignore_status=True)
2857            if "error" in out:
2858                ad.log.error("%s failed with %s", cmd, out)
2859                return False
2860            else:
2861                ad.log.info("push %s succeed")
2862                if skip_sl4a: ad.reboot(skip_sl4a)
2863                return True
2864        else:
2865            return True
2866    elif "error" in out:
2867        return False
2868    else:
2869        return True
2870
2871
2872def set_preferred_apn_by_adb(ad, pref_apn_name):
2873    """Select Pref APN
2874       Set Preferred APN on UI using content query/insert
2875       It needs apn name as arg, and it will match with plmn id
2876    """
2877    try:
2878        plmn_id = get_plmn_by_adb(ad)
2879        out = ad.adb.shell("content query --uri content://telephony/carriers "
2880                           "--where \"apn='%s' and numeric='%s'\"" %
2881                           (pref_apn_name, plmn_id))
2882        if "No result found" in out:
2883            ad.log.warning("Cannot find APN %s on device", pref_apn_name)
2884            return False
2885        else:
2886            apn_id = re.search(r'_id=(\d+)', out).group(1)
2887            ad.log.info("APN ID is %s", apn_id)
2888            ad.adb.shell("content insert --uri content:"
2889                         "//telephony/carriers/preferapn --bind apn_id:i:%s" %
2890                         (apn_id))
2891            out = ad.adb.shell("content query --uri "
2892                               "content://telephony/carriers/preferapn")
2893            if "No result found" in out:
2894                ad.log.error("Failed to set prefer APN %s", pref_apn_name)
2895                return False
2896            elif apn_id == re.search(r'_id=(\d+)', out).group(1):
2897                ad.log.info("Preferred APN set to %s", pref_apn_name)
2898                return True
2899    except Exception as e:
2900        ad.log.error("Exception while setting pref apn %s", e)
2901        return True
2902
2903
2904def check_apm_mode_on_by_serial(ad, serial_id):
2905    try:
2906        apm_check_cmd = "|".join(("adb -s %s shell dumpsys wifi" % serial_id,
2907                                  "grep -i airplanemodeon", "cut -f2 -d ' '"))
2908        output = exe_cmd(apm_check_cmd)
2909        if output.decode("utf-8").split("\n")[0] == "true":
2910            return True
2911        else:
2912            return False
2913    except Exception as e:
2914        ad.log.warning("Exception during check apm mode on %s", e)
2915        return True
2916
2917
2918def set_apm_mode_on_by_serial(ad, serial_id):
2919    try:
2920        cmd1 = "adb -s %s shell settings put global airplane_mode_on 1" % serial_id
2921        cmd2 = "adb -s %s shell am broadcast -a android.intent.action.AIRPLANE_MODE" % serial_id
2922        exe_cmd(cmd1)
2923        exe_cmd(cmd2)
2924    except Exception as e:
2925        ad.log.warning("Exception during set apm mode on %s", e)
2926        return True
2927
2928
2929def print_radio_info(ad, extra_msg=""):
2930    for prop in ("gsm.version.baseband", "persist.radio.ver_info",
2931                 "persist.radio.cnv.ver_info"):
2932        output = ad.adb.getprop(prop)
2933        ad.log.info("%s%s = %s", extra_msg, prop, output)
2934
2935
2936def wait_for_state(state_check_func,
2937                   state,
2938                   max_wait_time=MAX_WAIT_TIME_FOR_STATE_CHANGE,
2939                   checking_interval=WAIT_TIME_BETWEEN_STATE_CHECK,
2940                   *args,
2941                   **kwargs):
2942    while max_wait_time >= 0:
2943        if state_check_func(*args, **kwargs) == state:
2944            return True
2945        time.sleep(checking_interval)
2946        max_wait_time -= checking_interval
2947    return False
2948
2949
2950def power_off_sim_by_adb(ad, sim_slot_id,
2951                         timeout=MAX_WAIT_TIME_FOR_STATE_CHANGE):
2952    """Disable pSIM/eSIM SUB by adb command.
2953
2954    Args:
2955        ad: android device object.
2956        sim_slot_id: slot 0 or slot 1.
2957        timeout: wait time for state change.
2958
2959    Returns:
2960        True if success, False otherwise.
2961    """
2962    release_version =  int(ad.adb.getprop("ro.build.version.release"))
2963    if sim_slot_id == 0 and release_version < 12:
2964        ad.log.error(
2965            "The disable pSIM SUB command only support for Android S or higher "
2966            "version, abort test.")
2967        raise signals.TestSkip(
2968            "The disable pSIM SUB command only support for Android S or higher "
2969            "version, abort test.")
2970    try:
2971        if sim_slot_id:
2972            ad.adb.shell("am broadcast -a android.telephony.euicc.action."
2973                "TEST_PROFILE -n com.google.android.euicc/com.android.euicc."
2974                "receiver.ProfileTestReceiver --es 'operation' 'switch' --ei "
2975                "'subscriptionId' -1")
2976        else:
2977            sub_id = get_subid_by_adb(ad, sim_slot_id)
2978            # The command only support for Android S. (b/159605922)
2979            ad.adb.shell(
2980                "cmd phone disable-physical-subscription %d" % sub_id)
2981    except Exception as e:
2982        ad.log.error(e)
2983        return False
2984    while timeout > 0:
2985        if get_subid_by_adb(ad, sim_slot_id) == INVALID_SUB_ID:
2986            return True
2987        timeout = timeout - WAIT_TIME_BETWEEN_STATE_CHECK
2988        time.sleep(WAIT_TIME_BETWEEN_STATE_CHECK)
2989    sim_state = ad.adb.getprop("gsm.sim.state").split(",")
2990    ad.log.warning("Fail to power off SIM slot %d, sim_state=%s",
2991        sim_slot_id, sim_state[sim_slot_id])
2992    return False
2993
2994
2995def power_on_sim_by_adb(ad, sim_slot_id,
2996                         timeout=MAX_WAIT_TIME_FOR_STATE_CHANGE):
2997    """Enable pSIM/eSIM SUB by adb command.
2998
2999    Args:
3000        ad: android device object.
3001        sim_slot_id: slot 0 or slot 1.
3002        timeout: wait time for state change.
3003
3004    Returns:
3005        True if success, False otherwise.
3006    """
3007    release_version =  int(ad.adb.getprop("ro.build.version.release"))
3008    if sim_slot_id == 0 and release_version < 12:
3009        ad.log.error(
3010            "The enable pSIM SUB command only support for Android S or higher "
3011            "version, abort test.")
3012        raise signals.TestSkip(
3013            "The enable pSIM SUB command only support for Android S or higher "
3014            "version, abort test.")
3015    try:
3016        output = ad.adb.shell(
3017            "dumpsys isub | grep addSubInfoRecord | grep slotIndex=%d" %
3018            sim_slot_id)
3019        pattern = re.compile(r"subId=(\d+)")
3020        sub_id = pattern.findall(output)
3021        sub_id = int(sub_id[-1]) if sub_id else INVALID_SUB_ID
3022        if sim_slot_id:
3023            ad.adb.shell("am broadcast -a android.telephony.euicc.action."
3024                "TEST_PROFILE -n com.google.android.euicc/com.android.euicc."
3025                "receiver.ProfileTestReceiver --es 'operation' 'switch' --ei "
3026                "'subscriptionId' %d" % sub_id)
3027        else:
3028            # The command only support for Android S or higher. (b/159605922)
3029            ad.adb.shell(
3030                "cmd phone enable-physical-subscription %d" % sub_id)
3031    except Exception as e:
3032        ad.log.error(e)
3033        return False
3034    while timeout > 0:
3035        if get_subid_by_adb(ad, sim_slot_id) != INVALID_SUB_ID:
3036            return True
3037        timeout = timeout - WAIT_TIME_BETWEEN_STATE_CHECK
3038        time.sleep(WAIT_TIME_BETWEEN_STATE_CHECK)
3039    sim_state = ad.adb.getprop("gsm.sim.state").split(",")
3040    ad.log.warning("Fail to power on SIM slot %d, sim_state=%s",
3041        sim_slot_id, sim_state[sim_slot_id])
3042    return False
3043
3044
3045def power_off_sim(ad, sim_slot_id=None,
3046                  timeout=MAX_WAIT_TIME_FOR_STATE_CHANGE):
3047    try:
3048        if sim_slot_id is None:
3049            ad.droid.telephonySetSimPowerState(CARD_POWER_DOWN)
3050            verify_func = ad.droid.telephonyGetSimState
3051            verify_args = []
3052        else:
3053            ad.droid.telephonySetSimStateForSlotId(sim_slot_id,
3054                                                   CARD_POWER_DOWN)
3055            verify_func = ad.droid.telephonyGetSimStateForSlotId
3056            verify_args = [sim_slot_id]
3057    except Exception as e:
3058        ad.log.error(e)
3059        return False
3060    while timeout > 0:
3061        sim_state = verify_func(*verify_args)
3062        if sim_state in (
3063            SIM_STATE_UNKNOWN, SIM_STATE_ABSENT, SIM_STATE_NOT_READY):
3064            ad.log.info("SIM slot is powered off, SIM state is %s", sim_state)
3065            return True
3066        timeout = timeout - WAIT_TIME_BETWEEN_STATE_CHECK
3067        time.sleep(WAIT_TIME_BETWEEN_STATE_CHECK)
3068    ad.log.warning("Fail to power off SIM slot, sim_state=%s",
3069                   verify_func(*verify_args))
3070    return False
3071
3072
3073def power_on_sim(ad, sim_slot_id=None):
3074    try:
3075        if sim_slot_id is None:
3076            ad.droid.telephonySetSimPowerState(CARD_POWER_UP)
3077            verify_func = ad.droid.telephonyGetSimState
3078            verify_args = []
3079        else:
3080            ad.droid.telephonySetSimStateForSlotId(sim_slot_id, CARD_POWER_UP)
3081            verify_func = ad.droid.telephonyGetSimStateForSlotId
3082            verify_args = [sim_slot_id]
3083    except Exception as e:
3084        ad.log.error(e)
3085        return False
3086    if wait_for_state(verify_func, SIM_STATE_READY,
3087                      MAX_WAIT_TIME_FOR_STATE_CHANGE,
3088                      WAIT_TIME_BETWEEN_STATE_CHECK, *verify_args):
3089        ad.log.info("SIM slot is powered on, SIM state is READY")
3090        return True
3091    elif verify_func(*verify_args) == SIM_STATE_PIN_REQUIRED:
3092        ad.log.info("SIM is pin locked")
3093        return True
3094    else:
3095        ad.log.error("Fail to power on SIM slot")
3096        return False
3097
3098
3099def get_device_epoch_time(ad):
3100    return int(1000 * float(ad.adb.shell("date +%s.%N")))
3101
3102
3103def synchronize_device_time(ad):
3104    ad.adb.shell("put global auto_time 0", ignore_status=True)
3105    try:
3106        ad.adb.droid.setTime(get_current_epoch_time())
3107    except Exception:
3108        try:
3109            ad.adb.shell("date `date +%m%d%H%M%G.%S`")
3110        except Exception:
3111            pass
3112    try:
3113        ad.adb.shell(
3114            "am broadcast -a android.intent.action.TIME_SET",
3115            ignore_status=True)
3116    except Exception:
3117        pass
3118
3119
3120def revert_default_telephony_setting(ad):
3121    toggle_airplane_mode_by_adb(ad.log, ad, True)
3122    default_data_roaming = int(
3123        ad.adb.getprop("ro.com.android.dataroaming") == 'true')
3124    default_network_preference = int(
3125        ad.adb.getprop("ro.telephony.default_network"))
3126    ad.log.info("Default data roaming %s, network preference %s",
3127                default_data_roaming, default_network_preference)
3128    new_data_roaming = abs(default_data_roaming - 1)
3129    new_network_preference = abs(default_network_preference - 1)
3130    ad.log.info(
3131        "Set data roaming = %s, mobile data = 0, network preference = %s",
3132        new_data_roaming, new_network_preference)
3133    ad.adb.shell("settings put global mobile_data 0")
3134    ad.adb.shell("settings put global data_roaming %s" % new_data_roaming)
3135    ad.adb.shell("settings put global preferred_network_mode %s" %
3136                 new_network_preference)
3137
3138
3139def verify_default_telephony_setting(ad):
3140    ad.log.info("carrier_config: %s", dumpsys_carrier_config(ad))
3141    default_data_roaming = int(
3142        ad.adb.getprop("ro.com.android.dataroaming") == 'true')
3143    default_network_preference = int(
3144        ad.adb.getprop("ro.telephony.default_network"))
3145    ad.log.info("Default data roaming %s, network preference %s",
3146                default_data_roaming, default_network_preference)
3147    data_roaming = int(ad.adb.shell("settings get global data_roaming"))
3148    mobile_data = int(ad.adb.shell("settings get global mobile_data"))
3149    network_preference = int(
3150        ad.adb.shell("settings get global preferred_network_mode"))
3151    airplane_mode = int(ad.adb.shell("settings get global airplane_mode_on"))
3152    result = True
3153    ad.log.info("data_roaming = %s, mobile_data = %s, "
3154                "network_perference = %s, airplane_mode = %s", data_roaming,
3155                mobile_data, network_preference, airplane_mode)
3156    if airplane_mode:
3157        ad.log.error("Airplane mode is on")
3158        result = False
3159    if data_roaming != default_data_roaming:
3160        ad.log.error("Data roaming is %s, expecting %s", data_roaming,
3161                     default_data_roaming)
3162        result = False
3163    if not mobile_data:
3164        ad.log.error("Mobile data is off")
3165        result = False
3166    if network_preference != default_network_preference:
3167        ad.log.error("preferred_network_mode is %s, expecting %s",
3168                     network_preference, default_network_preference)
3169        result = False
3170    return result
3171
3172
3173def get_carrier_id_version(ad):
3174    out = ad.adb.shell("dumpsys activity service TelephonyDebugService | " \
3175                       "grep -i carrier_list_version")
3176    if out and ":" in out:
3177        version = out.split(':')[1].lstrip()
3178    else:
3179        version = "0"
3180    ad.log.debug("Carrier Config Version is %s", version)
3181    return version
3182
3183
3184def get_carrier_config_version(ad):
3185    out = ad.adb.shell("dumpsys carrier_config | grep version_string")
3186    if out and "-" in out:
3187        version = out.split('-')[1]
3188    else:
3189        version = "0"
3190    ad.log.debug("Carrier Config Version is %s", version)
3191    return version
3192
3193
3194def get_er_db_id_version(ad):
3195    out = ad.adb.shell("dumpsys activity service TelephonyDebugService | \
3196                        grep -i \"Database Version\"")
3197    if out and ":" in out:
3198        version = out.split(':', 2)[2].lstrip()
3199    else:
3200        version = "0"
3201    ad.log.debug("Emergency database Version is %s", version)
3202    return version
3203
3204def get_database_content(ad):
3205    out = ad.adb.shell("dumpsys activity service TelephonyDebugService | \
3206                        egrep -i \EmergencyNumber:Number-54321")
3207    if out:
3208        return True
3209    result = ad.adb.shell(r"dumpsys activity service TelephonyDebugService | \
3210                egrep -i \updateOtaEmergencyNumberListDatabaseAndNotify")
3211    ad.log.error("Emergency Number is incorrect. %s ", result)
3212    return False
3213
3214
3215def add_whitelisted_account(ad, user_account,user_password, retries=3):
3216    if not ad.is_apk_installed("com.google.android.tradefed.account"):
3217        ad.log.error("GoogleAccountUtil is not installed")
3218        return False
3219    for _ in range(retries):
3220        ad.ensure_screen_on()
3221        output = ad.adb.shell(
3222            'am instrument -w -e account "%s@gmail.com" -e password '
3223            '"%s" -e sync true -e wait-for-checkin false '
3224            'com.google.android.tradefed.account/.AddAccount' %
3225            (user_account, user_password))
3226        if "result=SUCCESS" in output:
3227            ad.log.info("Google account is added successfully")
3228            return True
3229    ad.log.error("Failed to add google account - %s", output)
3230    return False
3231
3232def install_apk(ad, apk_path, app_package_name):
3233    """Install assigned apk to specific device.
3234
3235    Args:
3236        ad: android device object
3237        apk_path: The path of apk (please refer to the "Resources" section in
3238            go/mhbe-resources for supported file stores.)
3239        app_package_name: package name of the application
3240
3241    Returns:
3242        True if success, False if fail.
3243    """
3244    ad.log.info("Install %s from %s", app_package_name, apk_path)
3245    ad.adb.install("-r -g %s" % apk_path, timeout=300, ignore_status=True)
3246    time.sleep(3)
3247    if not ad.is_apk_installed(app_package_name):
3248        ad.log.info("%s is not installed.", app_package_name)
3249        return False
3250    if ad.get_apk_version(app_package_name):
3251        ad.log.info("Current version of %s: %s", app_package_name,
3252                    ad.get_apk_version(app_package_name))
3253    return True
3254
3255def install_dialer_apk(ad, dialer_util):
3256    """Install dialer.apk to specific device.
3257
3258    Args:
3259        ad: android device object.
3260        dialer_util: path of dialer.apk
3261
3262    Returns:
3263        True if success, False if fail.
3264    """
3265    ad.log.info("Install dialer_util %s", dialer_util)
3266    ad.adb.install("-r -g %s" % dialer_util, timeout=300, ignore_status=True)
3267    time.sleep(3)
3268    if not ad.is_apk_installed(DIALER_PACKAGE_NAME):
3269        ad.log.info("%s is not installed", DIALER_PACKAGE_NAME)
3270        return False
3271    if ad.get_apk_version(DIALER_PACKAGE_NAME):
3272        ad.log.info("Current version of %s: %s", DIALER_PACKAGE_NAME,
3273                    ad.get_apk_version(DIALER_PACKAGE_NAME))
3274    return True
3275
3276
3277def install_message_apk(ad, message_util):
3278    """Install message.apk to specific device.
3279
3280    Args:
3281        ad: android device object.
3282        message_util: path of message.apk
3283
3284    Returns:
3285        True if success, False if fail.
3286    """
3287    ad.log.info("Install message_util %s", message_util)
3288    ad.adb.install("-r -g %s" % message_util, timeout=300, ignore_status=True)
3289    time.sleep(3)
3290    if not ad.is_apk_installed(MESSAGE_PACKAGE_NAME):
3291        ad.log.info("%s is not installed", MESSAGE_PACKAGE_NAME)
3292        return False
3293    if ad.get_apk_version(MESSAGE_PACKAGE_NAME):
3294        ad.log.info("Current version of %s: %s", MESSAGE_PACKAGE_NAME,
3295                    ad.get_apk_version(MESSAGE_PACKAGE_NAME))
3296    return True
3297
3298
3299def install_googleaccountutil_apk(ad, account_util):
3300    ad.log.info("Install account_util %s", account_util)
3301    ad.ensure_screen_on()
3302    ad.adb.install("-r %s" % account_util, timeout=300, ignore_status=True)
3303    time.sleep(3)
3304    if not ad.is_apk_installed("com.google.android.tradefed.account"):
3305        ad.log.info("com.google.android.tradefed.account is not installed")
3306        return False
3307    return True
3308
3309
3310def install_googlefi_apk(ad, fi_util):
3311    ad.log.info("Install fi_util %s", fi_util)
3312    ad.ensure_screen_on()
3313    ad.adb.install("-r -g --user 0 %s" % fi_util,
3314                   timeout=300, ignore_status=True)
3315    time.sleep(3)
3316    if not check_fi_apk_installed(ad):
3317        return False
3318    return True
3319
3320
3321def check_fi_apk_installed(ad):
3322    if not ad.is_apk_installed("com.google.android.apps.tycho"):
3323        ad.log.warning("com.google.android.apps.tycho is not installed")
3324        return False
3325    return True
3326
3327
3328def add_google_account(ad, retries=3):
3329    if not ad.is_apk_installed("com.google.android.tradefed.account"):
3330        ad.log.error("GoogleAccountUtil is not installed")
3331        return False
3332    for _ in range(retries):
3333        ad.ensure_screen_on()
3334        output = ad.adb.shell(
3335            'am instrument -w -e account "%s@gmail.com" -e password '
3336            '"%s" -e sync true -e wait-for-checkin false '
3337            'com.google.android.tradefed.account/.AddAccount' %
3338            (ad.user_account, ad.user_password))
3339        if "result=SUCCESS" in output:
3340            ad.log.info("Google account is added successfully")
3341            return True
3342    ad.log.error("Failed to add google account - %s", output)
3343    return False
3344
3345
3346def remove_google_account(ad, retries=3):
3347    if not ad.is_apk_installed("com.google.android.tradefed.account"):
3348        ad.log.error("GoogleAccountUtil is not installed")
3349        return False
3350    for _ in range(retries):
3351        ad.ensure_screen_on()
3352        output = ad.adb.shell(
3353            'am instrument -w '
3354            'com.google.android.tradefed.account/.RemoveAccounts')
3355        if "result=SUCCESS" in output:
3356            ad.log.info("google account is removed successfully")
3357            return True
3358    ad.log.error("Fail to remove google account due to %s", output)
3359    return False
3360
3361
3362def my_current_screen_content(ad, content):
3363    ad.adb.shell("uiautomator dump --window=WINDOW")
3364    out = ad.adb.shell("cat /sdcard/window_dump.xml | grep -E '%s'" % content)
3365    if not out:
3366        ad.log.warning("NOT FOUND - %s", content)
3367        return False
3368    return True
3369
3370
3371def activate_esim_using_suw(ad):
3372    _START_SUW = ('am start -a android.intent.action.MAIN -n '
3373                  'com.google.android.setupwizard/.SetupWizardTestActivity')
3374    _STOP_SUW = ('am start -a com.android.setupwizard.EXIT')
3375
3376    toggle_airplane_mode(ad.log, ad, new_state=False, strict_checking=False)
3377    ad.adb.shell("settings put system screen_off_timeout 1800000")
3378    ad.ensure_screen_on()
3379    ad.send_keycode("MENU")
3380    ad.send_keycode("HOME")
3381    for _ in range(3):
3382        ad.log.info("Attempt %d - activating eSIM", (_ + 1))
3383        ad.adb.shell(_START_SUW)
3384        time.sleep(10)
3385        log_screen_shot(ad, "start_suw")
3386        for _ in range(4):
3387            ad.send_keycode("TAB")
3388            time.sleep(0.5)
3389        ad.send_keycode("ENTER")
3390        time.sleep(15)
3391        log_screen_shot(ad, "activate_esim")
3392        get_screen_shot_log(ad)
3393        ad.adb.shell(_STOP_SUW)
3394        time.sleep(5)
3395        current_sim = get_sim_state(ad)
3396        ad.log.info("Current SIM status is %s", current_sim)
3397        if current_sim not in (SIM_STATE_ABSENT, SIM_STATE_UNKNOWN):
3398            break
3399    return True
3400
3401
3402def activate_google_fi_account(ad, retries=10):
3403    _FI_APK = "com.google.android.apps.tycho"
3404    _FI_ACTIVATE_CMD = ('am start -c android.intent.category.DEFAULT -n '
3405                        'com.google.android.apps.tycho/.AccountDetailsActivity --ez '
3406                        'in_setup_wizard false --ez force_show_account_chooser '
3407                        'false')
3408    toggle_airplane_mode(ad.log, ad, new_state=False, strict_checking=False)
3409    ad.adb.shell("settings put system screen_off_timeout 1800000")
3410    page_match_dict = {
3411       "SelectAccount" : "Choose an account to use",
3412       "Setup" : "Activate Google Fi to use your device for calls",
3413       "Switch" : "Switch to the Google Fi mobile network",
3414       "WiFi" : "Fi to download your SIM",
3415       "Connect" : "Connect to the Google Fi mobile network",
3416       "Move" : "Move number",
3417       "Data" : "first turn on mobile data",
3418       "Activate" : "This takes a minute or two, sometimes longer",
3419       "Welcome" : "Welcome to Google Fi",
3420       "Account" : "Your current cycle ends in"
3421    }
3422    page_list = ["Account", "Setup", "WiFi", "Switch", "Connect",
3423                 "Activate", "Move", "Welcome", "Data"]
3424    for _ in range(retries):
3425        ad.force_stop_apk(_FI_APK)
3426        ad.ensure_screen_on()
3427        ad.send_keycode("MENU")
3428        ad.send_keycode("HOME")
3429        ad.adb.shell(_FI_ACTIVATE_CMD)
3430        time.sleep(15)
3431        for page in page_list:
3432            if my_current_screen_content(ad, page_match_dict[page]):
3433                ad.log.info("Ready for Step %s", page)
3434                log_screen_shot(ad, "fi_activation_step_%s" % page)
3435                if page in ("Setup", "Switch", "Connect", "WiFi"):
3436                    ad.send_keycode("TAB")
3437                    ad.send_keycode("TAB")
3438                    ad.send_keycode("ENTER")
3439                    time.sleep(30)
3440                elif page == "Move" or page == "SelectAccount":
3441                    ad.send_keycode("TAB")
3442                    ad.send_keycode("ENTER")
3443                    time.sleep(5)
3444                elif page == "Welcome":
3445                    ad.send_keycode("TAB")
3446                    ad.send_keycode("TAB")
3447                    ad.send_keycode("TAB")
3448                    ad.send_keycode("ENTER")
3449                    ad.log.info("Activation SUCCESS using Fi App")
3450                    time.sleep(5)
3451                    ad.send_keycode("TAB")
3452                    ad.send_keycode("TAB")
3453                    ad.send_keycode("ENTER")
3454                    return True
3455                elif page == "Activate":
3456                    time.sleep(60)
3457                    if my_current_screen_content(ad, page_match_dict[page]):
3458                        time.sleep(60)
3459                elif page == "Account":
3460                    return True
3461                elif page == "Data":
3462                    ad.log.error("Mobile Data is turned OFF by default")
3463                    ad.send_keycode("TAB")
3464                    ad.send_keycode("TAB")
3465                    ad.send_keycode("ENTER")
3466            else:
3467                ad.log.info("NOT FOUND - Page %s", page)
3468                log_screen_shot(ad, "fi_activation_step_%s_failure" % page)
3469                get_screen_shot_log(ad)
3470    return False
3471
3472
3473def check_google_fi_activated(ad, retries=20):
3474    if check_fi_apk_installed(ad):
3475        _FI_APK = "com.google.android.apps.tycho"
3476        _FI_LAUNCH_CMD = ("am start -n %s/%s.AccountDetailsActivity" \
3477                          % (_FI_APK, _FI_APK))
3478        toggle_airplane_mode(ad.log, ad, new_state=False, strict_checking=False)
3479        ad.adb.shell("settings put system screen_off_timeout 1800000")
3480        ad.force_stop_apk(_FI_APK)
3481        ad.ensure_screen_on()
3482        ad.send_keycode("HOME")
3483        ad.adb.shell(_FI_LAUNCH_CMD)
3484        time.sleep(10)
3485        if not my_current_screen_content(ad, "Your current cycle ends in"):
3486            ad.log.warning("Fi is not activated")
3487            return False
3488        ad.send_keycode("HOME")
3489        return True
3490    else:
3491        ad.log.info("Fi Apk is not yet installed")
3492        return False
3493
3494
3495def cleanup_configupdater(ad):
3496    cmds = ('rm -rf /data/data/com.google.android.configupdater/shared_prefs',
3497            'rm /data/misc/carrierid/carrier_list.pb',
3498            'setprop persist.telephony.test.carrierid.ota true',
3499            'rm /data/user_de/0/com.android.providers.telephony/shared_prefs'
3500            '/CarrierIdProvider.xml')
3501    for cmd in cmds:
3502        ad.log.info("Cleanup ConfigUpdater - %s", cmd)
3503        ad.adb.shell(cmd, ignore_status=True)
3504
3505
3506def pull_carrier_id_files(ad, carrier_id_path):
3507    os.makedirs(carrier_id_path, exist_ok=True)
3508    ad.log.info("Pull CarrierId Files")
3509    cmds = ('/data/data/com.google.android.configupdater/shared_prefs/',
3510            '/data/misc/carrierid/',
3511            '/data/user_de/0/com.android.providers.telephony/shared_prefs/',
3512            '/data/data/com.android.providers.downloads/databases/downloads.db')
3513    for cmd in cmds:
3514        cmd = cmd + " %s" % carrier_id_path
3515        ad.adb.pull(cmd, timeout=30, ignore_status=True)
3516
3517
3518def bring_up_connectivity_monitor(ad):
3519    monitor_apk = None
3520    for apk in ("com.google.telephonymonitor",
3521                "com.google.android.connectivitymonitor"):
3522        if ad.is_apk_installed(apk):
3523            ad.log.info("apk %s is installed", apk)
3524            monitor_apk = apk
3525            break
3526    if not monitor_apk:
3527        ad.log.info("ConnectivityMonitor|TelephonyMonitor is not installed")
3528        return False
3529    toggle_connectivity_monitor_setting(ad, True)
3530
3531    if not ad.is_apk_running(monitor_apk):
3532        ad.log.info("%s is not running", monitor_apk)
3533        # Reboot
3534        ad.log.info("reboot to bring up %s", monitor_apk)
3535        reboot_device(ad)
3536        for i in range(30):
3537            if ad.is_apk_running(monitor_apk):
3538                ad.log.info("%s is running after reboot", monitor_apk)
3539                return True
3540            else:
3541                ad.log.info(
3542                    "%s is not running after reboot. Wait and check again",
3543                    monitor_apk)
3544                time.sleep(30)
3545        ad.log.error("%s is not running after reboot", monitor_apk)
3546        return False
3547    else:
3548        ad.log.info("%s is running", monitor_apk)
3549        return True
3550
3551
3552def get_host_ip_address(ad):
3553    cmd = "|".join(("ifconfig", "grep eno1 -A1", "grep inet", "awk '{$1=$1};1'", "cut -d ' ' -f 2"))
3554    destination_ip = exe_cmd(cmd)
3555    destination_ip = (destination_ip.decode("utf-8")).split("\n")[0]
3556    ad.log.info("Host IP is %s", destination_ip)
3557    return destination_ip
3558
3559
3560def load_scone_cat_simulate_data(ad, simulate_data, sub_id=None):
3561    """ Load radio simulate data
3562    ad: android device controller
3563    simulate_data: JSON object of simulate data
3564    sub_id: RIL sub id, should be 0 or 1
3565    """
3566    ad.log.info("load_scone_cat_simulate_data")
3567
3568    #Check RIL sub id
3569    if sub_id is None or sub_id > 1:
3570        ad.log.error("The value of RIL sub_id should be 0 or 1")
3571        return False
3572
3573    action = "com.google.android.apps.scone.cat.action.SetSimulateData"
3574
3575    #add sub id
3576    simulate_data["SubId"] = sub_id
3577    try:
3578        #dump json
3579        extra = json.dumps(simulate_data)
3580        ad.log.info("send simulate_data=[%s]" % extra)
3581        #send data
3582        ad.adb.shell("am broadcast -a " + action + " --es simulate_data '" + extra + "'")
3583    except Exception as e:
3584        ad.log.error("Exception error to send CAT: %s", e)
3585        return False
3586
3587    return True
3588
3589
3590def load_scone_cat_data_from_file(ad, simulate_file_path, sub_id=None):
3591    """ Load radio simulate data
3592    ad: android device controller
3593    simulate_file_path: JSON file of simulate data
3594    sub_id: RIL sub id, should be 0 or 1
3595    """
3596    ad.log.info("load_radio_simulate_data_from_file from %s" % simulate_file_path)
3597    radio_simulate_data = {}
3598
3599    #Check RIL sub id
3600    if sub_id is None or sub_id > 1:
3601        ad.log.error("The value of RIL sub_id should be 0 or 1")
3602        raise ValueError
3603
3604    with open(simulate_file_path, 'r') as f:
3605        try:
3606            radio_simulate_data = json.load(f)
3607        except Exception as e:
3608            ad.log.error("Exception error to load %s: %s", f, e)
3609            return False
3610
3611    for item in radio_simulate_data:
3612        result = load_scone_cat_simulate_data(ad, item, sub_id)
3613        if result == False:
3614            ad.log.error("Load CAT command fail")
3615            return False
3616        time.sleep(0.1)
3617
3618    return True
3619
3620
3621def toggle_connectivity_monitor_setting(ad, state=True):
3622    monitor_setting = ad.adb.getprop("persist.radio.enable_tel_mon")
3623    ad.log.info("radio.enable_tel_mon setting is %s", monitor_setting)
3624    current_state = True if monitor_setting == "user_enabled" else False
3625    if current_state == state:
3626        return True
3627    elif state is None:
3628        state = not current_state
3629    expected_monitor_setting = "user_enabled" if state else "disabled"
3630    cmd = "setprop persist.radio.enable_tel_mon %s" % expected_monitor_setting
3631    ad.log.info("Toggle connectivity monitor by %s", cmd)
3632    ad.adb.shell(
3633        "am start -n com.android.settings/.DevelopmentSettings",
3634        ignore_status=True)
3635    ad.adb.shell(cmd)
3636    monitor_setting = ad.adb.getprop("persist.radio.enable_tel_mon")
3637    ad.log.info("radio.enable_tel_mon setting is %s", monitor_setting)
3638    return monitor_setting == expected_monitor_setting
3639
3640
3641def get_rx_tx_power_levels(log, ad):
3642    """ Obtains Rx and Tx power levels from the MDS application.
3643
3644    The method requires the MDS app to be installed in the DUT.
3645
3646    Args:
3647        log: logger object
3648        ad: an android device
3649
3650    Return:
3651        A tuple where the first element is an array array with the RSRP value
3652        in Rx chain, and the second element is the transmitted power in dBm.
3653        Values for invalid Rx / Tx chains are set to None.
3654    """
3655    cmd = ('am instrument -w -e request "80 00 e8 03 00 08 00 00 00" -e '
3656           'response wait "com.google.mdstest/com.google.mdstest.instrument.'
3657           'ModemCommandInstrumentation"')
3658    output = ad.adb.shell(cmd)
3659
3660    if 'result=SUCCESS' not in output:
3661        raise RuntimeError('Could not obtain Tx/Rx power levels from MDS. Is '
3662                           'the MDS app installed?')
3663
3664    response = re.search(r"(?<=response=).+", output)
3665
3666    if not response:
3667        raise RuntimeError('Invalid response from the MDS app:\n' + output)
3668
3669    # Obtain a list of bytes in hex format from the response string
3670    response_hex = response.group(0).split(' ')
3671
3672    def get_bool(pos):
3673        """ Obtain a boolean variable from the byte array. """
3674        return response_hex[pos] == '01'
3675
3676    def get_int32(pos):
3677        """ Obtain an int from the byte array. Bytes are printed in
3678        little endian format."""
3679        return struct.unpack(
3680            '<i', bytearray.fromhex(''.join(response_hex[pos:pos + 4])))[0]
3681
3682    rx_power = []
3683    RX_CHAINS = 4
3684
3685    for i in range(RX_CHAINS):
3686        # Calculate starting position for the Rx chain data structure
3687        start = 12 + i * 22
3688
3689        # The first byte in the data structure indicates if the rx chain is
3690        # valid.
3691        if get_bool(start):
3692            rx_power.append(get_int32(start + 2) / 10)
3693        else:
3694            rx_power.append(None)
3695
3696    # Calculate the position for the tx chain data structure
3697    tx_pos = 12 + RX_CHAINS * 22
3698
3699    tx_valid = get_bool(tx_pos)
3700    if tx_valid:
3701        tx_power = get_int32(tx_pos + 2) / -10
3702    else:
3703        tx_power = None
3704
3705    return rx_power, tx_power
3706
3707
3708def set_time_sync_from_network(ad, action):
3709    if (action == 'enable'):
3710        ad.log.info('Enabling sync time from network.')
3711        ad.adb.shell('settings put global auto_time 1')
3712
3713    elif (action == 'disable'):
3714        ad.log.info('Disabling sync time from network.')
3715        ad.adb.shell('settings put global auto_time 0')
3716
3717    time.sleep(WAIT_TIME_SYNC_DATE_TIME_FROM_NETWORK)
3718
3719
3720def datetime_handle(ad, action, set_datetime_value='', get_year=False):
3721    get_value = ''
3722    if (action == 'get'):
3723        if (get_year):
3724            datetime_string = ad.adb.shell('date')
3725            datetime_list = datetime_string.split()
3726            try:
3727                get_value = datetime_list[5]
3728            except Exception as e:
3729                ad.log.error("Fail to get year from datetime: %s. " \
3730                                "Exception error: %s", datetime_list
3731                                , str(e))
3732                raise signals.TestSkip("Fail to get year from datetime" \
3733                                    ", the format is changed. Skip the test.")
3734        else:
3735            get_value = ad.adb.shell('date')
3736
3737    elif (action == 'set'):
3738        ad.adb.shell('date %s' % set_datetime_value)
3739        time.sleep(WAIT_TIME_SYNC_DATE_TIME_FROM_NETWORK)
3740        ad.adb.shell('am broadcast -a android.intent.action.TIME_SET')
3741
3742    return get_value
3743
3744
3745def change_voice_subid_temporarily(ad, sub_id, state_check_func, params=None):
3746    result = False
3747    voice_sub_id_changed = False
3748    current_sub_id = get_incoming_voice_sub_id(ad)
3749    if current_sub_id != sub_id:
3750        set_incoming_voice_sub_id(ad, sub_id)
3751        voice_sub_id_changed = True
3752
3753    if not params:
3754        if state_check_func():
3755            result = True
3756    else:
3757        if state_check_func(*params):
3758            result = True
3759
3760    if voice_sub_id_changed:
3761        set_incoming_voice_sub_id(ad, current_sub_id)
3762
3763    return result
3764
3765
3766def check_voice_network_type(ads, voice_init=True):
3767    """
3768    Args:
3769        ad: Android device object
3770        voice_init: check voice network type before initiate call
3771    Return:
3772        voice_network_list: Network Type for all android devices
3773    """
3774    voice_network_list = []
3775    for ad in ads:
3776        voice_network_list.append(ad.droid.telephonyGetCurrentVoiceNetworkType())
3777        if voice_init:
3778            ad.log.debug("Voice Network Type Before Call is %s",
3779                            ad.droid.telephonyGetCurrentVoiceNetworkType())
3780        else:
3781            ad.log.debug("Voice Network Type During Call is %s",
3782                            ad.droid.telephonyGetCurrentVoiceNetworkType())
3783    return voice_network_list
3784
3785
3786def cycle_airplane_mode(ad):
3787    """Turn on APM and then off."""
3788    # APM toggle
3789    if not toggle_airplane_mode(ad.log, ad, True):
3790        ad.log.info("Failed to turn on airplane mode.")
3791        return False
3792    if not toggle_airplane_mode(ad.log, ad, False):
3793        ad.log.info("Failed to turn off airplane mode.")
3794        return False
3795    return True