• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3#   Copyright 2021 - 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
17import time
18
19from acts import signals
20from acts_contrib.test_utils.tel.tel_subscription_utils import get_incoming_voice_sub_id
21from acts_contrib.test_utils.tel.tel_subscription_utils import get_outgoing_voice_sub_id
22from acts_contrib.test_utils.tel.tel_subscription_utils import set_incoming_voice_sub_id
23from acts_contrib.test_utils.tel.tel_defines import CARRIER_FRE
24from acts_contrib.test_utils.tel.tel_defines import INVALID_SUB_ID
25from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_FOR_STATE_CHANGE
26from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_VOLTE_ENABLED
27from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_WFC_DISABLED
28from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_WFC_ENABLED
29from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_STATE_CHECK
30from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_DISABLED
31from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
32from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_ONLY
33from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
34from acts_contrib.test_utils.tel.tel_defines import CARRIER_VZW, CARRIER_ATT, \
35    CARRIER_BELL, CARRIER_ROGERS, CARRIER_KOODO, CARRIER_VIDEOTRON, CARRIER_TELUS
36from acts_contrib.test_utils.tel.tel_logging_utils import start_adb_tcpdump
37from acts_contrib.test_utils.tel.tel_test_utils import _wait_for_droid_in_state
38from acts_contrib.test_utils.tel.tel_test_utils import _wait_for_droid_in_state_for_subscription
39from acts_contrib.test_utils.tel.tel_test_utils import bring_up_sl4a
40from acts_contrib.test_utils.tel.tel_test_utils import change_voice_subid_temporarily
41from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name
42from acts_contrib.test_utils.tel.tel_test_utils import wait_for_state
43
44
45class TelImsUtilsError(Exception):
46    pass
47
48
49def show_enhanced_4g_lte(ad, sub_id):
50    result = True
51    capabilities = ad.telephony["subscription"][sub_id].get("capabilities", [])
52    if capabilities:
53        if "hide_enhanced_4g_lte" in capabilities:
54            result = False
55            ad.log.info(
56                '"Enhanced 4G LTE MODE" is hidden for sub ID %s.', sub_id)
57            show_enhanced_4g_lte_mode = getattr(
58                ad, "show_enhanced_4g_lte_mode", False)
59            if show_enhanced_4g_lte_mode in ["true", "True"]:
60                current_voice_sub_id = get_outgoing_voice_sub_id(ad)
61                if sub_id != current_voice_sub_id:
62                    set_incoming_voice_sub_id(ad, sub_id)
63
64                ad.log.info(
65                    'Show "Enhanced 4G LTE MODE" forcibly for sub ID %s.',
66                    sub_id)
67                ad.adb.shell(
68                    "am broadcast \
69                        -a com.google.android.carrier.action.LOCAL_OVERRIDE \
70                        -n com.google.android.carrier/.ConfigOverridingReceiver \
71                        --ez hide_enhanced_4g_lte_bool false")
72                ad.telephony["subscription"][sub_id]["capabilities"].remove(
73                    "hide_enhanced_4g_lte")
74
75                if sub_id != current_voice_sub_id:
76                    set_incoming_voice_sub_id(ad, current_voice_sub_id)
77
78                result = True
79    return result
80
81
82def toggle_volte(log, ad, new_state=None):
83    """Toggle enable/disable VoLTE for default voice subscription.
84
85    Args:
86        ad: Android device object.
87        new_state: VoLTE mode state to set to.
88            True for enable, False for disable.
89            If None, opposite of the current state.
90
91    Raises:
92        TelImsUtilsError if platform does not support VoLTE.
93    """
94    return toggle_volte_for_subscription(
95        log, ad, get_outgoing_voice_sub_id(ad), new_state)
96
97
98def toggle_volte_for_subscription(log, ad, sub_id, new_state=None):
99    """Toggle enable/disable VoLTE for specified voice subscription.
100
101    Args:
102        ad: Android device object.
103        sub_id: Optional. If not assigned the default sub ID for voice call will
104            be used.
105        new_state: VoLTE mode state to set to.
106            True for enable, False for disable.
107            If None, opposite of the current state.
108    """
109    if not show_enhanced_4g_lte(ad, sub_id):
110        return False
111
112    current_state = None
113    result = True
114
115    if sub_id is None:
116        sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
117
118    try:
119        current_state = ad.droid.imsMmTelIsAdvancedCallingEnabled(sub_id)
120    except Exception as e:
121        ad.log.warning(e)
122
123    if current_state is not None:
124        if new_state is None:
125            new_state = not current_state
126        if new_state != current_state:
127            ad.log.info(
128                "Toggle Enhanced 4G LTE Mode from %s to %s on sub_id %s",
129                current_state, new_state, sub_id)
130            ad.droid.imsMmTelSetAdvancedCallingEnabled(sub_id, new_state)
131        check_state = ad.droid.imsMmTelIsAdvancedCallingEnabled(sub_id)
132        if check_state != new_state:
133            ad.log.error("Failed to toggle Enhanced 4G LTE Mode to %s, still \
134                set to %s on sub_id %s", new_state, check_state, sub_id)
135            result = False
136        return result
137    else:
138        # TODO: b/26293960 No framework API available to set IMS by SubId.
139        voice_sub_id_changed = False
140        current_sub_id = get_incoming_voice_sub_id(ad)
141        if current_sub_id != sub_id:
142            set_incoming_voice_sub_id(ad, sub_id)
143            voice_sub_id_changed = True
144
145        # b/139641554
146        ad.terminate_all_sessions()
147        bring_up_sl4a(ad)
148
149        if not ad.droid.imsIsEnhanced4gLteModeSettingEnabledByPlatform():
150            ad.log.info(
151                "Enhanced 4G Lte Mode Setting is not enabled by platform for \
152                    sub ID %s.", sub_id)
153            return False
154
155        current_state = ad.droid.imsIsEnhanced4gLteModeSettingEnabledByUser()
156        ad.log.info("Current state of Enhanced 4G Lte Mode Setting for sub \
157            ID %s: %s", sub_id, current_state)
158        ad.log.info("New desired state of Enhanced 4G Lte Mode Setting for sub \
159            ID %s: %s", sub_id, new_state)
160
161        if new_state is None:
162            new_state = not current_state
163        if new_state != current_state:
164            ad.log.info(
165                "Toggle Enhanced 4G LTE Mode from %s to %s for sub ID %s.",
166                current_state, new_state, sub_id)
167            ad.droid.imsSetEnhanced4gMode(new_state)
168            time.sleep(5)
169
170        check_state = ad.droid.imsIsEnhanced4gLteModeSettingEnabledByUser()
171        if check_state != new_state:
172            ad.log.error("Failed to toggle Enhanced 4G LTE Mode to %s, \
173                still set to %s on sub_id %s", new_state, check_state, sub_id)
174            result = False
175
176        if voice_sub_id_changed:
177            set_incoming_voice_sub_id(ad, current_sub_id)
178
179        return result
180
181
182def toggle_wfc(log, ad, new_state=None):
183    """ Toggle WFC enable/disable
184
185    Args:
186        log: Log object
187        ad: Android device object.
188        new_state: WFC state to set to.
189            True for enable, False for disable.
190            If None, opposite of the current state.
191    """
192    return toggle_wfc_for_subscription(
193        log, ad, new_state, get_outgoing_voice_sub_id(ad))
194
195
196def toggle_wfc_for_subscription(log, ad, new_state=None, sub_id=None):
197    """ Toggle WFC enable/disable for specified voice subscription.
198
199    Args:
200        ad: Android device object.
201        sub_id: Optional. If not assigned the default sub ID for voice call will
202            be used.
203        new_state: WFC state to set to.
204            True for enable, False for disable.
205            If None, opposite of the current state.
206    """
207    current_state = None
208    result = True
209
210    if sub_id is None:
211        sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
212
213    try:
214        current_state = ad.droid.imsMmTelIsVoWiFiSettingEnabled(sub_id)
215    except Exception as e:
216        ad.log.warning(e)
217
218    if current_state is not None:
219        if new_state is None:
220            new_state = not current_state
221        if new_state != current_state:
222            ad.log.info(
223                "Toggle Wi-Fi calling from %s to %s on sub_id %s",
224                current_state, new_state, sub_id)
225            ad.droid.imsMmTelSetVoWiFiSettingEnabled(sub_id, new_state)
226        check_state = ad.droid.imsMmTelIsVoWiFiSettingEnabled(sub_id)
227        if check_state != new_state:
228            ad.log.error("Failed to toggle Wi-Fi calling to %s, \
229                still set to %s on sub_id %s", new_state, check_state, sub_id)
230            result = False
231        return result
232    else:
233        voice_sub_id_changed = False
234        if not sub_id:
235            sub_id = get_outgoing_voice_sub_id(ad)
236        else:
237            current_sub_id = get_incoming_voice_sub_id(ad)
238            if current_sub_id != sub_id:
239                set_incoming_voice_sub_id(ad, sub_id)
240                voice_sub_id_changed = True
241
242        # b/139641554
243        ad.terminate_all_sessions()
244        bring_up_sl4a(ad)
245
246        if not ad.droid.imsIsWfcEnabledByPlatform():
247            ad.log.info("WFC is not enabled by platform for sub ID %s.", sub_id)
248            return False
249
250        current_state = ad.droid.imsIsWfcEnabledByUser()
251        ad.log.info("Current state of WFC Setting for sub ID %s: %s",
252            sub_id, current_state)
253        ad.log.info("New desired state of WFC Setting for sub ID %s: %s",
254            sub_id, new_state)
255
256        if new_state is None:
257            new_state = not current_state
258        if new_state != current_state:
259            ad.log.info("Toggle WFC user enabled from %s to %s for sub ID %s",
260                current_state, new_state, sub_id)
261            ad.droid.imsSetWfcSetting(new_state)
262
263        if voice_sub_id_changed:
264            set_incoming_voice_sub_id(ad, current_sub_id)
265
266        return True
267
268
269def is_enhanced_4g_lte_mode_setting_enabled(ad, sub_id, enabled_by="platform"):
270    voice_sub_id_changed = False
271    current_sub_id = get_incoming_voice_sub_id(ad)
272    if current_sub_id != sub_id:
273        set_incoming_voice_sub_id(ad, sub_id)
274        voice_sub_id_changed = True
275    if enabled_by == "platform":
276        res = ad.droid.imsIsEnhanced4gLteModeSettingEnabledByPlatform()
277    else:
278        res = ad.droid.imsIsEnhanced4gLteModeSettingEnabledByUser()
279    if not res:
280        ad.log.info("Enhanced 4G Lte Mode Setting is NOT enabled by %s for sub \
281            ID %s.", enabled_by, sub_id)
282        if voice_sub_id_changed:
283            set_incoming_voice_sub_id(ad, current_sub_id)
284        return False
285    if voice_sub_id_changed:
286        set_incoming_voice_sub_id(ad, current_sub_id)
287    ad.log.info("Enhanced 4G Lte Mode Setting is enabled by %s for sub ID %s.",
288        enabled_by, sub_id)
289    return True
290
291
292def set_enhanced_4g_mode(ad, sub_id, state):
293    voice_sub_id_changed = False
294    current_sub_id = get_incoming_voice_sub_id(ad)
295    if current_sub_id != sub_id:
296        set_incoming_voice_sub_id(ad, sub_id)
297        voice_sub_id_changed = True
298
299    ad.droid.imsSetEnhanced4gMode(state)
300    time.sleep(5)
301
302    if voice_sub_id_changed:
303        set_incoming_voice_sub_id(ad, current_sub_id)
304
305
306def wait_for_enhanced_4g_lte_setting(log,
307                                     ad,
308                                     sub_id,
309                                     max_time=MAX_WAIT_TIME_FOR_STATE_CHANGE):
310    """Wait for android device to enable enhance 4G LTE setting.
311
312    Args:
313        log: log object.
314        ad:  android device.
315        max_time: maximal wait time.
316
317    Returns:
318        Return True if device report VoLTE enabled bit true within max_time.
319        Return False if timeout.
320    """
321    return wait_for_state(
322        is_enhanced_4g_lte_mode_setting_enabled,
323        True,
324        max_time,
325        WAIT_TIME_BETWEEN_STATE_CHECK,
326        ad,
327        sub_id,
328        enabled_by="platform")
329
330
331def set_wfc_mode(log, ad, wfc_mode):
332    """Set WFC enable/disable and mode.
333
334    Args:
335        log: Log object
336        ad: Android device object.
337        wfc_mode: WFC mode to set to.
338            Valid mode includes: WFC_MODE_WIFI_ONLY, WFC_MODE_CELLULAR_PREFERRED,
339            WFC_MODE_WIFI_PREFERRED, WFC_MODE_DISABLED.
340
341    Returns:
342        True if success. False if ad does not support WFC or error happened.
343    """
344    return set_wfc_mode_for_subscription(
345        ad, wfc_mode, get_outgoing_voice_sub_id(ad))
346
347
348def set_wfc_mode_for_subscription(ad, wfc_mode, sub_id=None):
349    """Set WFC enable/disable and mode subscription based
350
351    Args:
352        ad: Android device object.
353        wfc_mode: WFC mode to set to.
354            Valid mode includes: WFC_MODE_WIFI_ONLY, WFC_MODE_CELLULAR_PREFERRED,
355            WFC_MODE_WIFI_PREFERRED.
356        sub_id: subscription Id
357
358    Returns:
359        True if success. False if ad does not support WFC or error happened.
360    """
361    if wfc_mode not in [
362        WFC_MODE_WIFI_ONLY,
363        WFC_MODE_CELLULAR_PREFERRED,
364        WFC_MODE_WIFI_PREFERRED,
365        WFC_MODE_DISABLED]:
366
367        ad.log.error("Given WFC mode (%s) is not correct.", wfc_mode)
368        return False
369
370    current_mode = None
371    result = True
372
373    if sub_id is None:
374        sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
375
376    try:
377        current_mode = ad.droid.imsMmTelGetVoWiFiModeSetting(sub_id)
378        ad.log.info("Current WFC mode of sub ID %s: %s", sub_id, current_mode)
379    except Exception as e:
380        ad.log.warning(e)
381
382    if current_mode is not None:
383        try:
384            if not ad.droid.imsMmTelIsVoWiFiSettingEnabled(sub_id):
385                if wfc_mode is WFC_MODE_DISABLED:
386                    ad.log.info("WFC is already disabled.")
387                    return True
388                ad.log.info(
389                    "WFC is disabled for sub ID %s. Enabling WFC...", sub_id)
390                ad.droid.imsMmTelSetVoWiFiSettingEnabled(sub_id, True)
391
392            if wfc_mode is WFC_MODE_DISABLED:
393                ad.log.info(
394                    "WFC is enabled for sub ID %s. Disabling WFC...", sub_id)
395                ad.droid.imsMmTelSetVoWiFiSettingEnabled(sub_id, False)
396                return True
397
398            ad.log.info("Set wfc mode to %s for sub ID %s.", wfc_mode, sub_id)
399            ad.droid.imsMmTelSetVoWiFiModeSetting(sub_id, wfc_mode)
400            mode = ad.droid.imsMmTelGetVoWiFiModeSetting(sub_id)
401            if mode != wfc_mode:
402                ad.log.error("WFC mode for sub ID %s is %s, not in %s",
403                    sub_id, mode, wfc_mode)
404                return False
405        except Exception as e:
406            ad.log.error(e)
407            return False
408        return True
409    else:
410        voice_sub_id_changed = False
411        if not sub_id:
412            sub_id = get_outgoing_voice_sub_id(ad)
413        else:
414            current_sub_id = get_incoming_voice_sub_id(ad)
415            if current_sub_id != sub_id:
416                set_incoming_voice_sub_id(ad, sub_id)
417                voice_sub_id_changed = True
418
419        # b/139641554
420        ad.terminate_all_sessions()
421        bring_up_sl4a(ad)
422
423        if wfc_mode != WFC_MODE_DISABLED and wfc_mode not in ad.telephony[
424            "subscription"][get_outgoing_voice_sub_id(ad)].get("wfc_modes", []):
425            ad.log.error("WFC mode %s is not supported", wfc_mode)
426            raise signals.TestSkip("WFC mode %s is not supported" % wfc_mode)
427        try:
428            ad.log.info("Set wfc mode to %s", wfc_mode)
429            if wfc_mode != WFC_MODE_DISABLED:
430                start_adb_tcpdump(ad, interface="wlan0", mask="all")
431            if not ad.droid.imsIsWfcEnabledByPlatform():
432                if wfc_mode == WFC_MODE_DISABLED:
433                    if voice_sub_id_changed:
434                        set_incoming_voice_sub_id(ad, current_sub_id)
435                    return True
436                else:
437                    ad.log.error("WFC not supported by platform.")
438                    if voice_sub_id_changed:
439                        set_incoming_voice_sub_id(ad, current_sub_id)
440                    return False
441            ad.droid.imsSetWfcMode(wfc_mode)
442            mode = ad.droid.imsGetWfcMode()
443            if voice_sub_id_changed:
444                set_incoming_voice_sub_id(ad, current_sub_id)
445            if mode != wfc_mode:
446                ad.log.error("WFC mode is %s, not in %s", mode, wfc_mode)
447                return False
448        except Exception as e:
449            ad.log.error(e)
450            if voice_sub_id_changed:
451                set_incoming_voice_sub_id(ad, current_sub_id)
452            return False
453        return True
454
455
456def set_ims_provisioning_for_subscription(ad, feature_flag, value, sub_id=None):
457    """ Sets Provisioning Values for Subscription Id
458
459    Args:
460        ad: Android device object.
461        sub_id: Subscription Id
462        feature_flag: voice or video
463        value: enable or disable
464    """
465    try:
466        if sub_id is None:
467            sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
468        ad.log.info("SubId %s - setprovisioning for %s to %s",
469                    sub_id, feature_flag, value)
470        result = ad.droid.provisioningSetProvisioningIntValue(sub_id,
471                    feature_flag, value)
472        if result == 0:
473            return True
474        return False
475    except Exception as e:
476        ad.log.error(e)
477        return False
478
479
480def get_ims_provisioning_for_subscription(ad, feature_flag, tech, sub_id=None):
481    """ Gets Provisioning Values for Subscription Id
482
483    Args:
484        ad: Android device object.
485        sub_id: Subscription Id
486        feature_flag: voice, video, ut, sms
487        tech: lte, iwlan
488    """
489    try:
490        if sub_id is None:
491            sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
492        result = ad.droid.provisioningGetProvisioningStatusForCapability(
493                    sub_id, feature_flag, tech)
494        ad.log.info("SubId %s - getprovisioning for %s on %s - %s",
495                    sub_id, feature_flag, tech, result)
496        return result
497    except Exception as e:
498        ad.log.error(e)
499        return False
500
501
502def activate_wfc_on_device(log, ad):
503    """ Activates WiFi calling on device.
504
505        Required for certain network operators.
506
507    Args:
508        log: Log object
509        ad: Android device object
510    """
511    activate_wfc_on_device_for_subscription(log, ad,
512                                            ad.droid.subscriptionGetDefaultSubId())
513
514
515def activate_wfc_on_device_for_subscription(log, ad, sub_id):
516    """ Activates WiFi calling on device for a subscription.
517
518    Args:
519        log: Log object
520        ad: Android device object
521        sub_id: Subscription id (integer)
522    """
523    if not sub_id or INVALID_SUB_ID == sub_id:
524        ad.log.error("Subscription id invalid")
525        return
526    operator_name = get_operator_name(log, ad, sub_id)
527    if operator_name in (CARRIER_VZW, CARRIER_ATT, CARRIER_BELL, CARRIER_ROGERS,
528                         CARRIER_TELUS, CARRIER_KOODO, CARRIER_VIDEOTRON, CARRIER_FRE):
529        ad.log.info("Activating WFC on operator : %s", operator_name)
530        if not ad.is_apk_installed("com.google.android.wfcactivation"):
531            ad.log.error("WFC Activation Failed, wfc activation apk not installed")
532            return
533        wfc_activate_cmd ="am start --ei EXTRA_LAUNCH_CARRIER_APP 0 --ei " \
534                    "android.telephony.extra.SUBSCRIPTION_INDEX {} -n ".format(sub_id)
535        if CARRIER_ATT == operator_name:
536            ad.adb.shell("setprop dbg.att.force_wfc_nv_enabled true")
537            wfc_activate_cmd = wfc_activate_cmd+\
538                               "\"com.google.android.wfcactivation/" \
539                               ".WfcActivationActivity\""
540        elif CARRIER_VZW == operator_name:
541            ad.adb.shell("setprop dbg.vzw.force_wfc_nv_enabled true")
542            wfc_activate_cmd = wfc_activate_cmd + \
543                               "\"com.google.android.wfcactivation/" \
544                               ".VzwEmergencyAddressActivity\""
545        else:
546            wfc_activate_cmd = wfc_activate_cmd+ \
547                               "\"com.google.android.wfcactivation/" \
548                               ".can.WfcActivationCanadaActivity\""
549        ad.adb.shell(wfc_activate_cmd)
550
551
552def is_ims_registered(log, ad, sub_id=None):
553    """Return True if IMS registered.
554
555    Args:
556        log: log object.
557        ad: android device.
558        sub_id: Optional. If not assigned the default sub ID of voice call will
559            be used.
560
561    Returns:
562        Return True if IMS registered.
563        Return False if IMS not registered.
564    """
565    if not sub_id:
566        return ad.droid.telephonyIsImsRegistered()
567    else:
568        return change_voice_subid_temporarily(
569            ad, sub_id, ad.droid.telephonyIsImsRegistered)
570
571
572def wait_for_ims_registered(log, ad, max_time=MAX_WAIT_TIME_WFC_ENABLED):
573    """Wait for android device to register on ims.
574
575    Args:
576        log: log object.
577        ad:  android device.
578        max_time: maximal wait time.
579
580    Returns:
581        Return True if device register ims successfully within max_time.
582        Return False if timeout.
583    """
584    return _wait_for_droid_in_state(log, ad, max_time, is_ims_registered)
585
586
587def is_volte_available(log, ad, sub_id=None):
588    """Return True if VoLTE is available.
589
590    Args:
591        log: log object.
592        ad: android device.
593        sub_id: Optional. If not assigned the default sub ID of voice call will
594            be used.
595
596    Returns:
597        Return True if VoLTE is available.
598        Return False if VoLTE is not available.
599    """
600    if not sub_id:
601        return ad.droid.telephonyIsVolteAvailable()
602    else:
603        return change_voice_subid_temporarily(
604            ad, sub_id, ad.droid.telephonyIsVolteAvailable)
605
606
607def is_volte_enabled(log, ad, sub_id=None):
608    """Return True if VoLTE feature bit is True.
609
610    Args:
611        log: log object.
612        ad: android device.
613        sub_id: Optional. If not assigned the default sub ID of voice call will
614            be used.
615
616    Returns:
617        Return True if VoLTE feature bit is True and IMS registered.
618        Return False if VoLTE feature bit is False or IMS not registered.
619    """
620    if not is_ims_registered(log, ad, sub_id):
621        ad.log.info("IMS is not registered for sub ID %s.", sub_id)
622        return False
623    if not is_volte_available(log, ad, sub_id):
624        ad.log.info("IMS is registered for sub ID %s, IsVolteCallingAvailable "
625            "is False", sub_id)
626        return False
627    else:
628        ad.log.info("IMS is registered for sub ID %s, IsVolteCallingAvailable "
629            "is True", sub_id)
630        return True
631
632
633def wait_for_volte_enabled(
634    log, ad, max_time=MAX_WAIT_TIME_VOLTE_ENABLED,sub_id=None):
635    """Wait for android device to report VoLTE enabled bit true.
636
637    Args:
638        log: log object.
639        ad:  android device.
640        max_time: maximal wait time.
641
642    Returns:
643        Return True if device report VoLTE enabled bit true within max_time.
644        Return False if timeout.
645    """
646    if not sub_id:
647        return _wait_for_droid_in_state(log, ad, max_time, is_volte_enabled)
648    else:
649        return _wait_for_droid_in_state_for_subscription(
650            log, ad, sub_id, max_time, is_volte_enabled)
651
652
653def toggle_video_calling(log, ad, new_state=None):
654    """Toggle enable/disable Video calling for default voice subscription.
655
656    Args:
657        ad: Android device object.
658        new_state: Video mode state to set to.
659            True for enable, False for disable.
660            If None, opposite of the current state.
661
662    Raises:
663        TelImsUtilsError if platform does not support Video calling.
664    """
665    if not ad.droid.imsIsVtEnabledByPlatform():
666        if new_state is not False:
667            raise TelImsUtilsError("VT not supported by platform.")
668        # if the user sets VT false and it's unavailable we just let it go
669        return False
670
671    current_state = ad.droid.imsIsVtEnabledByUser()
672    if new_state is None:
673        new_state = not current_state
674    if new_state != current_state:
675        ad.droid.imsSetVtSetting(new_state)
676    return True
677
678
679def toggle_video_calling_for_subscription(ad, new_state=None, sub_id=None):
680    """Toggle enable/disable Video calling for subscription.
681
682    Args:
683        ad: Android device object.
684        new_state: Video mode state to set to.
685            True for enable, False for disable.
686            If None, opposite of the current state.
687        sub_id: subscription Id
688    """
689    try:
690        if sub_id is None:
691            sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
692        current_state = ad.droid.imsMmTelIsVtSettingEnabled(sub_id)
693        if new_state is None:
694            new_state = not current_state
695        if new_state != current_state:
696            ad.log.info("SubId %s - Toggle VT from %s to %s", sub_id,
697                        current_state, new_state)
698            ad.droid.imsMmTelSetVtSettingEnabled(sub_id, new_state)
699    except Exception as e:
700        ad.log.error(e)
701        return False
702    return True
703
704
705def is_video_enabled(log, ad):
706    """Return True if Video Calling feature bit is True.
707
708    Args:
709        log: log object.
710        ad: android device.
711
712    Returns:
713        Return True if Video Calling feature bit is True and IMS registered.
714        Return False if Video Calling feature bit is False or IMS not registered.
715    """
716    video_status = ad.droid.telephonyIsVideoCallingAvailable()
717    if video_status is True and is_ims_registered(log, ad) is False:
718        ad.log.error(
719            "Error! Video Call is Available, but IMS is not registered.")
720        return False
721    return video_status
722
723
724def wait_for_video_enabled(log, ad, max_time=MAX_WAIT_TIME_VOLTE_ENABLED):
725    """Wait for android device to report Video Telephony enabled bit true.
726
727    Args:
728        log: log object.
729        ad:  android device.
730        max_time: maximal wait time.
731
732    Returns:
733        Return True if device report Video Telephony enabled bit true within max_time.
734        Return False if timeout.
735    """
736    return _wait_for_droid_in_state(log, ad, max_time, is_video_enabled)
737
738
739def is_wfc_enabled(log, ad):
740    """Return True if WiFi Calling feature bit is True.
741
742    Args:
743        log: log object.
744        ad: android device.
745
746    Returns:
747        Return True if WiFi Calling feature bit is True and IMS registered.
748        Return False if WiFi Calling feature bit is False or IMS not registered.
749    """
750    if not is_ims_registered(log, ad):
751        ad.log.info("IMS is not registered.")
752        return False
753    if not ad.droid.telephonyIsWifiCallingAvailable():
754        ad.log.info("IMS is registered, IsWifiCallingAvailable is False")
755        return False
756    else:
757        ad.log.info("IMS is registered, IsWifiCallingAvailable is True")
758        return True
759
760
761def wait_for_wfc_enabled(log, ad, max_time=MAX_WAIT_TIME_WFC_ENABLED):
762    """Wait for android device to report WiFi Calling enabled bit true.
763
764    Args:
765        log: log object.
766        ad:  android device.
767        max_time: maximal wait time.
768            Default value is MAX_WAIT_TIME_WFC_ENABLED.
769
770    Returns:
771        Return True if device report WiFi Calling enabled bit true within max_time.
772        Return False if timeout.
773    """
774    return _wait_for_droid_in_state(log, ad, max_time, is_wfc_enabled)
775
776
777def wait_for_wfc_disabled(log, ad, max_time=MAX_WAIT_TIME_WFC_DISABLED):
778    """Wait for android device to report WiFi Calling enabled bit false.
779
780    Args:
781        log: log object.
782        ad:  android device.
783        max_time: maximal wait time.
784            Default value is MAX_WAIT_TIME_WFC_DISABLED.
785
786    Returns:
787        Return True if device report WiFi Calling enabled bit false within max_time.
788        Return False if timeout.
789    """
790    return _wait_for_droid_in_state(
791        log, ad, max_time, lambda log, ad: not is_wfc_enabled(log, ad))