• 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            operator_name = get_operator_name(ad.log, ad, sub_id)
398            ad.log.info("Set wfc mode to %s for sub ID %s.", wfc_mode, sub_id)
399            ad.root_adb()
400            if CARRIER_ATT == operator_name:
401                ad.adb.shell("setprop dbg.att.force_wfc_nv_enabled true")
402            ad.adb.shell("setprop dbg.force_wfc_activated true")
403            ad.droid.imsMmTelSetVoWiFiModeSetting(sub_id, wfc_mode)
404            mode = ad.droid.imsMmTelGetVoWiFiModeSetting(sub_id)
405            if mode != wfc_mode:
406                ad.log.error("WFC mode for sub ID %s is %s, not in %s",
407                    sub_id, mode, wfc_mode)
408                return False
409        except Exception as e:
410            ad.log.error(e)
411            return False
412        return True
413    else:
414        voice_sub_id_changed = False
415        if not sub_id:
416            sub_id = get_outgoing_voice_sub_id(ad)
417        else:
418            current_sub_id = get_incoming_voice_sub_id(ad)
419            if current_sub_id != sub_id:
420                set_incoming_voice_sub_id(ad, sub_id)
421                voice_sub_id_changed = True
422
423        # b/139641554
424        ad.terminate_all_sessions()
425        bring_up_sl4a(ad)
426
427        if wfc_mode != WFC_MODE_DISABLED and wfc_mode not in ad.telephony[
428            "subscription"][get_outgoing_voice_sub_id(ad)].get("wfc_modes", []):
429            ad.log.error("WFC mode %s is not supported", wfc_mode)
430            raise signals.TestSkip("WFC mode %s is not supported" % wfc_mode)
431        try:
432            ad.log.info("Set wfc mode to %s", wfc_mode)
433            if wfc_mode != WFC_MODE_DISABLED:
434                start_adb_tcpdump(ad, interface="wlan0", mask="all")
435            if not ad.droid.imsIsWfcEnabledByPlatform():
436                if wfc_mode == WFC_MODE_DISABLED:
437                    if voice_sub_id_changed:
438                        set_incoming_voice_sub_id(ad, current_sub_id)
439                    return True
440                else:
441                    ad.log.error("WFC not supported by platform.")
442                    if voice_sub_id_changed:
443                        set_incoming_voice_sub_id(ad, current_sub_id)
444                    return False
445            ad.droid.imsSetWfcMode(wfc_mode)
446            mode = ad.droid.imsGetWfcMode()
447            if voice_sub_id_changed:
448                set_incoming_voice_sub_id(ad, current_sub_id)
449            if mode != wfc_mode:
450                ad.log.error("WFC mode is %s, not in %s", mode, wfc_mode)
451                return False
452        except Exception as e:
453            ad.log.error(e)
454            if voice_sub_id_changed:
455                set_incoming_voice_sub_id(ad, current_sub_id)
456            return False
457        return True
458
459
460def set_ims_provisioning_for_subscription(ad, feature_flag, value, sub_id=None):
461    """ Sets Provisioning Values for Subscription Id
462
463    Args:
464        ad: Android device object.
465        sub_id: Subscription Id
466        feature_flag: voice or video
467        value: enable or disable
468    """
469    try:
470        if sub_id is None:
471            sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
472        ad.log.info("SubId %s - setprovisioning for %s to %s",
473                    sub_id, feature_flag, value)
474        result = ad.droid.provisioningSetProvisioningIntValue(sub_id,
475                    feature_flag, value)
476        if result == 0:
477            return True
478        return False
479    except Exception as e:
480        ad.log.error(e)
481        return False
482
483
484def get_ims_provisioning_for_subscription(ad, feature_flag, tech, sub_id=None):
485    """ Gets Provisioning Values for Subscription Id
486
487    Args:
488        ad: Android device object.
489        sub_id: Subscription Id
490        feature_flag: voice, video, ut, sms
491        tech: lte, iwlan
492    """
493    try:
494        if sub_id is None:
495            sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
496        result = ad.droid.provisioningGetProvisioningStatusForCapability(
497                    sub_id, feature_flag, tech)
498        ad.log.info("SubId %s - getprovisioning for %s on %s - %s",
499                    sub_id, feature_flag, tech, result)
500        return result
501    except Exception as e:
502        ad.log.error(e)
503        return False
504
505
506def activate_wfc_on_device(log, ad):
507    """ Activates WiFi calling on device.
508
509        Required for certain network operators.
510
511    Args:
512        log: Log object
513        ad: Android device object
514    """
515    activate_wfc_on_device_for_subscription(log, ad,
516                                            ad.droid.subscriptionGetDefaultSubId())
517
518
519def activate_wfc_on_device_for_subscription(log, ad, sub_id):
520    """ Activates WiFi calling on device for a subscription.
521
522    Args:
523        log: Log object
524        ad: Android device object
525        sub_id: Subscription id (integer)
526    """
527    if not sub_id or INVALID_SUB_ID == sub_id:
528        ad.log.error("Subscription id invalid")
529        return
530    operator_name = get_operator_name(log, ad, sub_id)
531    if operator_name in (CARRIER_VZW, CARRIER_ATT, CARRIER_BELL, CARRIER_ROGERS,
532                         CARRIER_TELUS, CARRIER_KOODO, CARRIER_VIDEOTRON, CARRIER_FRE):
533        ad.log.info("Activating WFC on operator : %s", operator_name)
534        if not ad.is_apk_installed("com.google.android.wfcactivation"):
535            ad.log.error("WFC Activation Failed, wfc activation apk not installed")
536            return
537        wfc_activate_cmd ="am start --ei EXTRA_LAUNCH_CARRIER_APP 0 --ei " \
538                    "android.telephony.extra.SUBSCRIPTION_INDEX {} -n ".format(sub_id)
539        if CARRIER_ATT == operator_name:
540            ad.adb.shell("setprop dbg.att.force_wfc_nv_enabled true")
541            wfc_activate_cmd = wfc_activate_cmd+\
542                               "\"com.google.android.wfcactivation/" \
543                               ".WfcActivationActivity\""
544        elif CARRIER_VZW == operator_name:
545            ad.adb.shell("setprop dbg.vzw.force_wfc_nv_enabled true")
546            wfc_activate_cmd = wfc_activate_cmd + \
547                               "\"com.google.android.wfcactivation/" \
548                               ".VzwEmergencyAddressActivity\""
549        else:
550            wfc_activate_cmd = wfc_activate_cmd+ \
551                               "\"com.google.android.wfcactivation/" \
552                               ".can.WfcActivationCanadaActivity\""
553        ad.adb.shell(wfc_activate_cmd)
554
555
556def is_ims_registered(log, ad, sub_id=None):
557    """Return True if IMS registered.
558
559    Args:
560        log: log object.
561        ad: android device.
562        sub_id: Optional. If not assigned the default sub ID of voice call will
563            be used.
564
565    Returns:
566        Return True if IMS registered.
567        Return False if IMS not registered.
568    """
569    if not sub_id:
570        return ad.droid.telephonyIsImsRegistered()
571    else:
572        return change_voice_subid_temporarily(
573            ad, sub_id, ad.droid.telephonyIsImsRegistered)
574
575
576def wait_for_ims_registered(log, ad, max_time=MAX_WAIT_TIME_WFC_ENABLED):
577    """Wait for android device to register on ims.
578
579    Args:
580        log: log object.
581        ad:  android device.
582        max_time: maximal wait time.
583
584    Returns:
585        Return True if device register ims successfully within max_time.
586        Return False if timeout.
587    """
588    return _wait_for_droid_in_state(log, ad, max_time, is_ims_registered)
589
590
591def is_volte_available(log, ad, sub_id=None):
592    """Return True if VoLTE is available.
593
594    Args:
595        log: log object.
596        ad: android device.
597        sub_id: Optional. If not assigned the default sub ID of voice call will
598            be used.
599
600    Returns:
601        Return True if VoLTE is available.
602        Return False if VoLTE is not available.
603    """
604    if not sub_id:
605        return ad.droid.telephonyIsVolteAvailable()
606    else:
607        return change_voice_subid_temporarily(
608            ad, sub_id, ad.droid.telephonyIsVolteAvailable)
609
610
611def is_volte_enabled(log, ad, sub_id=None):
612    """Return True if VoLTE feature bit is True.
613
614    Args:
615        log: log object.
616        ad: android device.
617        sub_id: Optional. If not assigned the default sub ID of voice call will
618            be used.
619
620    Returns:
621        Return True if VoLTE feature bit is True and IMS registered.
622        Return False if VoLTE feature bit is False or IMS not registered.
623    """
624    if not is_ims_registered(log, ad, sub_id):
625        ad.log.info("IMS is not registered for sub ID %s.", sub_id)
626        return False
627    if not is_volte_available(log, ad, sub_id):
628        ad.log.info("IMS is registered for sub ID %s, IsVolteCallingAvailable "
629            "is False", sub_id)
630        return False
631    else:
632        ad.log.info("IMS is registered for sub ID %s, IsVolteCallingAvailable "
633            "is True", sub_id)
634        return True
635
636
637def wait_for_volte_enabled(
638    log, ad, max_time=MAX_WAIT_TIME_VOLTE_ENABLED,sub_id=None):
639    """Wait for android device to report VoLTE enabled bit true.
640
641    Args:
642        log: log object.
643        ad:  android device.
644        max_time: maximal wait time.
645
646    Returns:
647        Return True if device report VoLTE enabled bit true within max_time.
648        Return False if timeout.
649    """
650    if not sub_id:
651        return _wait_for_droid_in_state(log, ad, max_time, is_volte_enabled)
652    else:
653        return _wait_for_droid_in_state_for_subscription(
654            log, ad, sub_id, max_time, is_volte_enabled)
655
656
657def toggle_video_calling(log, ad, new_state=None):
658    """Toggle enable/disable Video calling for default voice subscription.
659
660    Args:
661        ad: Android device object.
662        new_state: Video mode state to set to.
663            True for enable, False for disable.
664            If None, opposite of the current state.
665
666    Raises:
667        TelImsUtilsError if platform does not support Video calling.
668    """
669    if not ad.droid.imsIsVtEnabledByPlatform():
670        if new_state is not False:
671            raise TelImsUtilsError("VT not supported by platform.")
672        # if the user sets VT false and it's unavailable we just let it go
673        return False
674
675    current_state = ad.droid.imsIsVtEnabledByUser()
676    if new_state is None:
677        new_state = not current_state
678    if new_state != current_state:
679        ad.droid.imsSetVtSetting(new_state)
680    return True
681
682
683def toggle_video_calling_for_subscription(ad, new_state=None, sub_id=None):
684    """Toggle enable/disable Video calling for subscription.
685
686    Args:
687        ad: Android device object.
688        new_state: Video mode state to set to.
689            True for enable, False for disable.
690            If None, opposite of the current state.
691        sub_id: subscription Id
692    """
693    try:
694        if sub_id is None:
695            sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
696        current_state = ad.droid.imsMmTelIsVtSettingEnabled(sub_id)
697        if new_state is None:
698            new_state = not current_state
699        if new_state != current_state:
700            ad.log.info("SubId %s - Toggle VT from %s to %s", sub_id,
701                        current_state, new_state)
702            ad.droid.imsMmTelSetVtSettingEnabled(sub_id, new_state)
703    except Exception as e:
704        ad.log.error(e)
705        return False
706    return True
707
708
709def is_video_enabled(log, ad):
710    """Return True if Video Calling feature bit is True.
711
712    Args:
713        log: log object.
714        ad: android device.
715
716    Returns:
717        Return True if Video Calling feature bit is True and IMS registered.
718        Return False if Video Calling feature bit is False or IMS not registered.
719    """
720    video_status = ad.droid.telephonyIsVideoCallingAvailable()
721    if video_status is True and is_ims_registered(log, ad) is False:
722        ad.log.error(
723            "Error! Video Call is Available, but IMS is not registered.")
724        return False
725    return video_status
726
727
728def wait_for_video_enabled(log, ad, max_time=MAX_WAIT_TIME_VOLTE_ENABLED):
729    """Wait for android device to report Video Telephony enabled bit true.
730
731    Args:
732        log: log object.
733        ad:  android device.
734        max_time: maximal wait time.
735
736    Returns:
737        Return True if device report Video Telephony enabled bit true within max_time.
738        Return False if timeout.
739    """
740    return _wait_for_droid_in_state(log, ad, max_time, is_video_enabled)
741
742
743def is_wfc_enabled(log, ad):
744    """Return True if WiFi Calling feature bit is True.
745
746    Args:
747        log: log object.
748        ad: android device.
749
750    Returns:
751        Return True if WiFi Calling feature bit is True and IMS registered.
752        Return False if WiFi Calling feature bit is False or IMS not registered.
753    """
754    if not is_ims_registered(log, ad):
755        ad.log.info("IMS is not registered.")
756        return False
757    if not ad.droid.telephonyIsWifiCallingAvailable():
758        ad.log.info("IMS is registered, IsWifiCallingAvailable is False")
759        return False
760    else:
761        ad.log.info("IMS is registered, IsWifiCallingAvailable is True")
762        return True
763
764
765def wait_for_wfc_enabled(log, ad, max_time=MAX_WAIT_TIME_WFC_ENABLED):
766    """Wait for android device to report WiFi Calling enabled bit true.
767
768    Args:
769        log: log object.
770        ad:  android device.
771        max_time: maximal wait time.
772            Default value is MAX_WAIT_TIME_WFC_ENABLED.
773
774    Returns:
775        Return True if device report WiFi Calling enabled bit true within max_time.
776        Return False if timeout.
777    """
778    return _wait_for_droid_in_state(log, ad, max_time, is_wfc_enabled)
779
780
781def wait_for_wfc_disabled(log, ad, max_time=MAX_WAIT_TIME_WFC_DISABLED):
782    """Wait for android device to report WiFi Calling enabled bit false.
783
784    Args:
785        log: log object.
786        ad:  android device.
787        max_time: maximal wait time.
788            Default value is MAX_WAIT_TIME_WFC_DISABLED.
789
790    Returns:
791        Return True if device report WiFi Calling enabled bit false within max_time.
792        Return False if timeout.
793    """
794    return _wait_for_droid_in_state(
795        log, ad, max_time, lambda log, ad: not is_wfc_enabled(log, ad))
796