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
18from datetime import datetime
19
20from acts.test_decorators import test_tracker_info
21from acts_contrib.test_utils.tel.loggers.telephony_metric_logger import TelephonyMetricLogger
22from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
23from acts_contrib.test_utils.tel.tel_data_utils import airplane_mode_test
24from acts_contrib.test_utils.tel.tel_data_utils import reboot_test
25from acts_contrib.test_utils.tel.tel_data_utils import wait_for_network_service
26from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
27from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
28from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_WIFI_CONNECTION
29from acts_contrib.test_utils.tel.tel_ims_utils import set_wfc_mode
30from acts_contrib.test_utils.tel.tel_logging_utils import start_pixellogger_always_on_logging
31from acts_contrib.test_utils.tel.tel_logging_utils import wait_for_log
32from acts_contrib.test_utils.tel.tel_parse_utils import print_nested_dict
33from acts_contrib.test_utils.tel.tel_parse_utils import parse_ims_reg
34from acts_contrib.test_utils.tel.tel_parse_utils import ON_IMS_MM_TEL_CONNECTED_4G_SLOT0
35from acts_contrib.test_utils.tel.tel_parse_utils import ON_IMS_MM_TEL_CONNECTED_4G_SLOT1
36from acts_contrib.test_utils.tel.tel_parse_utils import ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT0
37from acts_contrib.test_utils.tel.tel_parse_utils import ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT1
38from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_iwlan
39from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_iwlan_for_subscription
40from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte_for_subscription
41from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_idle_volte
42from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_idle_iwlan
43from acts_contrib.test_utils.tel.tel_subscription_utils import get_slot_index_from_voice_sub_id
44from acts_contrib.test_utils.tel.tel_subscription_utils import get_all_sub_id
45from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
46from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
47from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call
48from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_volte
49from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_iwlan
50from acts_contrib.test_utils.tel.tel_voice_utils import two_phone_call_short_seq
51from acts_contrib.test_utils.tel.tel_wifi_utils import check_is_wifi_connected
52from acts.utils import get_current_epoch_time
53
54SETUP_PHONE_FAIL = 'SETUP_PHONE_FAIL'
55VERIFY_NETWORK_FAIL = 'VERIFY_NETWORK_FAIL'
56VERIFY_INTERNET_FAIL = 'VERIFY_INTERNET_FAIL'
57TOGGLE_OFF_APM_FAIL = 'TOGGLE_OFF_APM_FAIL'
58
59CALCULATE_EVERY_N_CYCLES = 10
60
61
62def test_result(result_list, cycle, min_fail=0, failrate=0):
63    failure_count = len(list(filter(lambda x: (x != True), result_list)))
64    if failure_count >= min_fail:
65        if failure_count >= cycle * failrate:
66            return False
67    return True
68
69def wait_for_wifi_disconnected(ad, wifi_ssid):
70    """Wait until Wifi is disconnected.
71
72    Args:
73        ad: Android object
74        wifi_ssid: to specify the Wifi AP which should be disconnected.
75
76    Returns:
77        True if Wifi is disconnected before time-out. Otherwise False.
78    """
79    wait_time = 0
80    while wait_time < MAX_WAIT_TIME_WIFI_CONNECTION:
81        if check_is_wifi_connected(ad.log, ad, wifi_ssid):
82            ad.droid.wifiToggleState(False)
83            time.sleep(3)
84            wait_time = wait_time + 3
85        else:
86            ad.log.info('Wifi is disconnected.')
87            return True
88
89    if check_is_wifi_connected(ad.log, ad, wifi_ssid):
90        ad.log.error('Wifi still is connected to %s.', wifi_ssid)
91        return False
92    else:
93        ad.log.info('Wifi is disconnected.')
94        return True
95
96class TelLiveRilImsKpiTest(TelephonyBaseTest):
97    def setup_class(self):
98        TelephonyBaseTest.setup_class(self)
99        start_pixellogger_always_on_logging(self.android_devices[0])
100        self.tel_logger = TelephonyMetricLogger.for_test_case()
101        self.user_params["telephony_auto_rerun"] = 0
102        self.reboot_4g_test_cycle = self.user_params.get(
103            'reboot_4g_test_cycle', 1)
104        self.reboot_iwlan_test_cycle = self.user_params.get(
105            'reboot_iwlan_test_cycle', 1)
106        self.cycle_apm_4g_test_cycle = self.user_params.get(
107            'cycle_apm_4g_test_cycle', 1)
108        self.cycle_wifi_in_apm_mode_test_cycle = self.user_params.get(
109            'cycle_wifi_in_apm_mode_test_cycle', 1)
110        self.ims_handover_4g_to_iwlan_with_voice_call_wfc_wifi_preferred_test_cycle = self.user_params.get(
111            'ims_handover_4g_to_iwlan_with_voice_call_wfc_wifi_preferred_test_cycle', 1)
112        self.ims_handover_4g_to_iwlan_wfc_wifi_preferred_test_cycle = self.user_params.get(
113            'ims_handover_4g_to_iwlan_wfc_wifi_preferred_test_cycle', 1)
114        self.ims_handover_iwlan_to_4g_wfc_wifi_preferred_test_cycle = self.user_params.get(
115            'ims_handover_iwlan_to_4g_wfc_wifi_preferred_test_cycle', 1)
116        self.ims_handover_iwlan_to_4g_with_voice_call_wfc_wifi_preferred_test_cycle = self.user_params.get(
117            'ims_handover_iwlan_to_4g_with_voice_call_wfc_wifi_preferred_test_cycle', 1)
118        self.ims_handover_iwlan_to_4g_wfc_cellular_preferred_test_cycle = self.user_params.get(
119            'ims_handover_iwlan_to_4g_wfc_cellular_preferred_test_cycle', 1)
120        self.ims_handover_iwlan_to_4g_with_voice_call_wfc_cellular_preferred_test_cycle = self.user_params.get(
121            'ims_handover_iwlan_to_4g_with_voice_call_wfc_cellular_preferred_test_cycle', 1)
122
123    def teardown_test(self):
124        for ad in self.android_devices:
125            toggle_airplane_mode(self.log, ad, False)
126
127    @test_tracker_info(uuid="d6a59a3c-2bbc-4ed3-a41e-4492b4ab8a50")
128    @TelephonyBaseTest.tel_test_wrap
129    def test_reboot_4g(self):
130        """Reboot UE and measure bootup IMS registration time on LTE.
131
132        Test steps:
133            1. Enable VoLTE at all slots and ensure IMS is registered over LTE
134                cellular network at all slots.
135            2. Reboot UE.
136            3. Parse logcat to calculate IMS registration time on LTE after
137                bootup.
138        """
139        ad = self.android_devices[0]
140        cycle = self.reboot_4g_test_cycle
141        voice_slot = get_slot_index_from_voice_sub_id(ad)
142
143        if getattr(ad, 'dsds', False):
144            the_other_slot = 1 - voice_slot
145        else:
146            the_other_slot = None
147
148        result = []
149        search_intervals = []
150        exit_due_to_high_fail_rate = False
151        for attempt in range(cycle):
152            _continue = True
153            self.log.info(
154                '==================> Reboot on LTE %s/%s <==================',
155                attempt+1,
156                cycle)
157
158            sub_id_list = get_all_sub_id(ad)
159            for sub_id in sub_id_list:
160                if not phone_setup_volte_for_subscription(self.log, ad, sub_id):
161                    result.append(SETUP_PHONE_FAIL)
162                    self._take_bug_report(
163                        self.test_name, begin_time=get_current_epoch_time())
164                    _continue = False
165                    if not test_result(result, cycle, 10, 0.1):
166                        exit_due_to_high_fail_rate = True
167
168            if _continue:
169                if not wait_for_network_service(self.log, ad):
170                    result.append(VERIFY_NETWORK_FAIL)
171                    self._take_bug_report(
172                        self.test_name, begin_time=get_current_epoch_time())
173                    _continue = False
174                    if not test_result(result, cycle, 10, 0.1):
175                        exit_due_to_high_fail_rate = True
176
177            if _continue:
178                begin_time = datetime.now()
179                if reboot_test(self.log, ad):
180                    result.append(True)
181                else:
182                    result.append(False)
183                    self._take_bug_report(
184                        self.test_name, begin_time=get_current_epoch_time())
185                    _continue = False
186                    if not test_result(result, cycle, 10, 0.1):
187                        exit_due_to_high_fail_rate = True
188
189            if _continue:
190                end_time = datetime.now()
191                search_intervals.append([begin_time, end_time])
192
193            if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or (
194                attempt == cycle - 1) or exit_due_to_high_fail_rate:
195
196                ad.log.info(
197                    '====== Test result of IMS bootup registration at slot %s '
198                    '======',
199                    voice_slot)
200                ad.log.info(result)
201
202                for slot in [voice_slot, the_other_slot]:
203                    if slot is None:
204                        continue
205
206                    ims_reg, parsing_fail, avg_ims_reg_duration = parse_ims_reg(
207                        ad, search_intervals, '4g', 'reboot', slot=slot)
208                    ad.log.info(
209                        '====== IMS bootup registration at slot %s ======', slot)
210                    for msg in ims_reg:
211                        print_nested_dict(ad, msg)
212
213                    ad.log.info(
214                        '====== Attempt of parsing fail at slot %s ======' % slot)
215                    for msg in parsing_fail:
216                        ad.log.info(msg)
217
218                    ad.log.warning('====== Summary ======')
219                    ad.log.warning(
220                        '%s/%s cycles failed.',
221                        (len(result) - result.count(True)),
222                        len(result))
223                    for attempt, value in enumerate(result):
224                        if value is not True:
225                            ad.log.warning('Cycle %s: %s', attempt+1, value)
226                    try:
227                        fail_rate = (
228                            len(result) - result.count(True))/len(result)
229                        ad.log.info(
230                            'Fail rate of IMS bootup registration at slot %s: %s',
231                            slot,
232                            fail_rate)
233                    except Exception as e:
234                        ad.log.error(
235                            'Fail rate of IMS bootup registration at slot %s: '
236                            'ERROR (%s)',
237                            slot,
238                            e)
239
240                    ad.log.info(
241                        'Number of trials with valid parsed logs: %s',
242                        len(ims_reg))
243                    ad.log.info(
244                        'Average IMS bootup registration time at slot %s: %s',
245                        slot,
246                        avg_ims_reg_duration)
247
248            if exit_due_to_high_fail_rate:
249                break
250
251        return test_result(result, cycle)
252
253    @test_tracker_info(uuid="c97dd2f2-9e8a-43d4-9352-b53abe5ac6a4")
254    @TelephonyBaseTest.tel_test_wrap
255    def test_reboot_iwlan(self):
256        """Reboot UE and measure bootup IMS registration time over iwlan.
257
258        Test steps:
259            1. Enable VoLTE at all slots; enable WFC and set WFC mode to
260                Wi-Fi-preferred mode; connect Wi-Fi and ensure IMS is registered
261                at all slots over iwlan.
262            2. Reboot UE.
263            3. Parse logcat to calculate IMS registration time over iwlan after
264                bootup.
265        """
266        ad = self.android_devices[0]
267        cycle = self.reboot_iwlan_test_cycle
268        voice_slot = get_slot_index_from_voice_sub_id(ad)
269
270        if getattr(ad, 'dsds', False):
271            the_other_slot = 1 - voice_slot
272        else:
273            the_other_slot = None
274
275        result = []
276        search_intervals = []
277        exit_due_to_high_fail_rate = False
278        for attempt in range(cycle):
279            _continue = True
280            self.log.info(
281                '==================> Reboot on iwlan %s/%s <==================',
282                attempt+1,
283                cycle)
284
285            sub_id_list = get_all_sub_id(ad)
286            for sub_id in sub_id_list:
287                if not phone_setup_iwlan_for_subscription(
288                    self.log,
289                    ad,
290                    sub_id,
291                    False,
292                    WFC_MODE_WIFI_PREFERRED,
293                    self.wifi_network_ssid,
294                    self.wifi_network_pass):
295
296                    result.append(SETUP_PHONE_FAIL)
297                    self._take_bug_report(
298                        self.test_name, begin_time=get_current_epoch_time())
299                    _continue = False
300                    if not test_result(result, cycle, 10, 0.1):
301                        exit_due_to_high_fail_rate = True
302
303                    wait_for_wifi_disconnected(ad, self.wifi_network_ssid)
304
305            if _continue:
306                if not verify_internet_connection(self.log, ad):
307                    result.append(VERIFY_INTERNET_FAIL)
308                    self._take_bug_report(
309                        self.test_name, begin_time=get_current_epoch_time())
310                    _continue = False
311                    if not test_result(result, cycle, 10, 0.1):
312                        exit_due_to_high_fail_rate = True
313
314            if _continue:
315                begin_time = datetime.now()
316                if reboot_test(self.log, ad, wifi_ssid=self.wifi_network_ssid):
317                    result.append(True)
318                else:
319                    result.append(False)
320                    self._take_bug_report(
321                        self.test_name, begin_time=get_current_epoch_time())
322                    _continue = False
323                    if not test_result(result, cycle, 10, 0.1):
324                        exit_due_to_high_fail_rate = True
325
326            if _continue:
327                end_time = datetime.now()
328                search_intervals.append([begin_time, end_time])
329
330            if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or (
331                attempt == cycle - 1) or exit_due_to_high_fail_rate:
332
333                ad.log.info(
334                    '====== Test result of IMS bootup registration at slot %s '
335                    '======',
336                    voice_slot)
337                ad.log.info(result)
338
339                for slot in [voice_slot, the_other_slot]:
340                    if slot is None:
341                        continue
342
343                    ims_reg, parsing_fail, avg_ims_reg_duration = parse_ims_reg(
344                        ad, search_intervals, 'iwlan', 'reboot', slot=slot)
345                    ad.log.info(
346                        '====== IMS bootup registration at slot %s ======', slot)
347                    for msg in ims_reg:
348                        print_nested_dict(ad, msg)
349
350                    ad.log.info(
351                        '====== Attempt of parsing fail at slot %s ======' % slot)
352                    for msg in parsing_fail:
353                        ad.log.info(msg)
354
355                    ad.log.warning('====== Summary ======')
356                    ad.log.warning(
357                        '%s/%s cycles failed.',
358                        (len(result) - result.count(True)),
359                        len(result))
360                    for attempt, value in enumerate(result):
361                        if value is not True:
362                            ad.log.warning('Cycle %s: %s', attempt+1, value)
363
364                    try:
365                        fail_rate = (
366                            len(result) - result.count(True))/len(result)
367                        ad.log.info(
368                            'Fail rate of IMS bootup registration at slot %s: %s',
369                            slot,
370                            fail_rate)
371                    except Exception as e:
372                        ad.log.error(
373                            'Fail rate of IMS bootup registration at slot %s: '
374                            'ERROR (%s)',
375                            slot,
376                            e)
377
378                    ad.log.info(
379                        'Number of trials with valid parsed logs: %s',
380                        len(ims_reg))
381                    ad.log.info(
382                        'Average IMS bootup registration time at slot %s: %s',
383                        slot, avg_ims_reg_duration)
384            if exit_due_to_high_fail_rate:
385                break
386
387        return test_result(result, cycle)
388
389    @test_tracker_info(uuid="45ed4572-7de9-4e1b-b2ec-58dea722fa3e")
390    @TelephonyBaseTest.tel_test_wrap
391    def test_cycle_airplane_mode_4g(self):
392        """Cycle airplane mode and measure IMS registration time on LTE
393
394        Test steps:
395            1. Enable VoLTE at all slots and ensure IMS is registered on LTE at
396                all slots.
397            2. Cycle airplane mode.
398            3. Parse logcat to calculate IMS registration time right after
399                recovery of cellular service.
400        """
401        ad = self.android_devices[0]
402        cycle = self.cycle_apm_4g_test_cycle
403        voice_slot = get_slot_index_from_voice_sub_id(ad)
404
405        if getattr(ad, 'dsds', False):
406            the_other_slot = 1 - voice_slot
407        else:
408            the_other_slot = None
409
410        result = []
411        search_intervals = []
412        exit_due_to_high_fail_rate = False
413        for attempt in range(cycle):
414            _continue = True
415            self.log.info(
416                '============> Cycle airplane mode on LTE %s/%s <============',
417                attempt+1,
418                cycle)
419
420            sub_id_list = get_all_sub_id(ad)
421            for sub_id in sub_id_list:
422                if not phone_setup_volte_for_subscription(self.log, ad, sub_id):
423                    result.append(SETUP_PHONE_FAIL)
424                    self._take_bug_report(
425                        self.test_name, begin_time=get_current_epoch_time())
426                    _continue = False
427                    if not test_result(result, cycle, 10, 0.1):
428                        exit_due_to_high_fail_rate = True
429
430            if _continue:
431                if not wait_for_network_service(self.log, ad):
432                    result.append(VERIFY_NETWORK_FAIL)
433                    self._take_bug_report(
434                        self.test_name, begin_time=get_current_epoch_time())
435                    _continue = False
436                    if not test_result(result, cycle, 10, 0.1):
437                        exit_due_to_high_fail_rate = True
438
439            if _continue:
440                begin_time = datetime.now()
441                if airplane_mode_test(self.log, ad):
442                    result.append(True)
443                else:
444                    result.append(False)
445                    self._take_bug_report(
446                        self.test_name, begin_time=get_current_epoch_time())
447                    _continue = False
448                    if not test_result(result, cycle, 10, 0.1):
449                        exit_due_to_high_fail_rate = True
450
451            if _continue:
452                end_time = datetime.now()
453                search_intervals.append([begin_time, end_time])
454
455            if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or (
456                attempt == cycle - 1) or exit_due_to_high_fail_rate:
457
458                ad.log.info(
459                    '====== Test result of IMS registration at slot %s ======',
460                    voice_slot)
461                ad.log.info(result)
462
463                for slot in [voice_slot, the_other_slot]:
464                    if slot is None:
465                        continue
466
467                    ims_reg, parsing_fail, avg_ims_reg_duration = parse_ims_reg(
468                        ad, search_intervals, '4g', 'apm', slot=slot)
469                    ad.log.info(
470                        '====== IMS registration at slot %s ======', slot)
471                    for msg in ims_reg:
472                        print_nested_dict(ad, msg)
473
474                    ad.log.info(
475                        '====== Attempt of parsing fail at slot %s ======' % slot)
476                    for msg in parsing_fail:
477                        ad.log.info(msg)
478
479                    ad.log.warning('====== Summary ======')
480                    ad.log.warning('%s/%s cycles failed.', (len(result) - result.count(True)), len(result))
481                    for attempt, value in enumerate(result):
482                        if value is not True:
483                            ad.log.warning('Cycle %s: %s', attempt+1, value)
484
485                    try:
486                        fail_rate = (
487                            len(result) - result.count(True))/len(result)
488                        ad.log.info(
489                            'Fail rate of IMS registration at slot %s: %s',
490                            slot,
491                            fail_rate)
492                    except Exception as e:
493                        ad.log.error(
494                            'Fail rate of IMS registration at slot %s: '
495                            'ERROR (%s)',
496                            slot,
497                            e)
498
499                    ad.log.info(
500                        'Number of trials with valid parsed logs: %s',
501                        len(ims_reg))
502                    ad.log.info(
503                        'Average IMS registration time at slot %s: %s',
504                        slot, avg_ims_reg_duration)
505
506            if exit_due_to_high_fail_rate:
507                break
508
509        return test_result(result, cycle)
510
511    @test_tracker_info(uuid="915c9403-8bbc-45c7-be53-8b0de4191716")
512    @TelephonyBaseTest.tel_test_wrap
513    def test_cycle_wifi_in_apm_mode(self):
514        """Cycle Wi-Fi in airplane mode and measure IMS registration time over
515            iwlan.
516
517        Test steps:
518            1. Enable VoLTE; enable WFC and set WFC mode to Wi-Fi-preferred mode;
519                turn on airplane mode and connect Wi-Fi to ensure IMS is
520                registered over iwlan.
521            2. Cycle Wi-Fi.
522            3. Parse logcat to calculate IMS registration time right after
523                recovery of Wi-Fi connection in airplane mode.
524        """
525        ad = self.android_devices[0]
526        cycle = self.cycle_wifi_in_apm_mode_test_cycle
527        voice_slot = get_slot_index_from_voice_sub_id(ad)
528
529        result = []
530        search_intervals = []
531        exit_due_to_high_fail_rate = False
532        for attempt in range(cycle):
533            _continue = True
534            self.log.info(
535                '============> Cycle WiFi in airplane mode %s/%s <============',
536                attempt+1,
537                cycle)
538
539            begin_time = datetime.now()
540
541            if not wait_for_wifi_disconnected(ad, self.wifi_network_ssid):
542                result.append(False)
543                self._take_bug_report(
544                    self.test_name, begin_time=get_current_epoch_time())
545                _continue = False
546                if not test_result(result, cycle, 10, 0.1):
547                    exit_due_to_high_fail_rate = True
548
549            if _continue:
550                if not phone_setup_iwlan(
551                    self.log,
552                    ad,
553                    True,
554                    WFC_MODE_WIFI_PREFERRED,
555                    self.wifi_network_ssid,
556                    self.wifi_network_pass):
557
558                    result.append(False)
559                    self._take_bug_report(
560                        self.test_name, begin_time=get_current_epoch_time())
561                    _continue = False
562                    if not test_result(result, cycle, 10, 0.1):
563                        exit_due_to_high_fail_rate = True
564
565            if _continue:
566                if not verify_internet_connection(self.log, ad):
567                    result.append(VERIFY_INTERNET_FAIL)
568                    self._take_bug_report(
569                        self.test_name, begin_time=get_current_epoch_time())
570                    _continue = False
571                    if not test_result(result, cycle, 10, 0.1):
572                        exit_due_to_high_fail_rate = True
573
574            if _continue:
575                if not wait_for_wifi_disconnected(
576                    ad, self.wifi_network_ssid):
577                    result.append(False)
578                    self._take_bug_report(
579                        self.test_name, begin_time=get_current_epoch_time())
580                    _continue = False
581                    if not test_result(result, cycle, 10, 0.1):
582                        exit_due_to_high_fail_rate = True
583
584            if _continue:
585                result.append(True)
586                end_time = datetime.now()
587                search_intervals.append([begin_time, end_time])
588
589            if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or (
590                attempt == cycle - 1) or exit_due_to_high_fail_rate:
591
592                ad.log.info(
593                    '====== Test result of IMS registration at slot %s ======',
594                    voice_slot)
595                ad.log.info(result)
596
597                ims_reg, parsing_fail, avg_ims_reg_duration = parse_ims_reg(
598                    ad, search_intervals, 'iwlan', 'apm')
599                ad.log.info(
600                    '====== IMS registration at slot %s ======', voice_slot)
601                for msg in ims_reg:
602                    ad.log.info(msg)
603
604                ad.log.info(
605                    '====== Attempt of parsing fail at slot %s ======' % voice_slot)
606                for msg in parsing_fail:
607                    ad.log.info(msg)
608
609                ad.log.warning('====== Summary ======')
610                ad.log.warning(
611                    '%s/%s cycles failed.',
612                    (len(result) - result.count(True)),
613                    len(result))
614                for attempt, value in enumerate(result):
615                    if value is not True:
616                        ad.log.warning('Cycle %s: %s', attempt+1, value)
617
618                try:
619                    fail_rate = (len(result) - result.count(True))/len(result)
620                    ad.log.info(
621                        'Fail rate of IMS registration at slot %s: %s',
622                        voice_slot,
623                        fail_rate)
624                except Exception as e:
625                    ad.log.error(
626                        'Fail rate of IMS registration at slot %s: ERROR (%s)',
627                        voice_slot,
628                        e)
629
630                ad.log.info(
631                    'Number of trials with valid parsed logs: %s', len(ims_reg))
632                ad.log.info(
633                    'Average IMS registration time at slot %s: %s',
634                    voice_slot, avg_ims_reg_duration)
635
636            if exit_due_to_high_fail_rate:
637                break
638        toggle_airplane_mode(self.log, ad, False)
639        return test_result(result, cycle)
640
641    def ims_handover_4g_to_iwlan_wfc_wifi_preferred(self, voice_call=False):
642        """Connect WFC to make IMS registration hand over from LTE to iwlan in
643            Wi-Fi-preferred mode. Measure IMS handover time.
644
645        Test steps:
646            1. Enable WFC and set WFC mode to Wi-Fi-preferred mode.
647            2. Ensure Wi-Fi are disconnected and all cellular services are
648                available.
649            3. (Optional) Make a VoLTE call and keep the call active.
650            4. Connect Wi-Fi. The IMS registration should hand over from LTE
651                to iwlan.
652            5. Parse logcat to calculate the IMS handover time.
653
654        Args:
655            voice_call: True if an active VoLTE call is desired in the background
656                during IMS handover procedure. Otherwise False.
657        """
658        ad = self.android_devices[0]
659        if voice_call:
660            cycle = self.ims_handover_4g_to_iwlan_with_voice_call_wfc_wifi_preferred_test_cycle
661        else:
662            cycle = self.ims_handover_4g_to_iwlan_wfc_wifi_preferred_test_cycle
663
664        voice_slot = get_slot_index_from_voice_sub_id(ad)
665
666        result = []
667        search_intervals = []
668        exit_due_to_high_fail_rate = False
669
670        if not set_wfc_mode(self.log, ad, WFC_MODE_WIFI_PREFERRED):
671            return False
672
673        for attempt in range(cycle):
674            _continue = True
675            self.log.info(
676                '======> IMS handover from LTE to iwlan in WFC wifi-preferred '
677                'mode %s/%s <======',
678                attempt+1,
679                cycle)
680
681            begin_time = datetime.now()
682
683            if not wait_for_wifi_disconnected(ad, self.wifi_network_ssid):
684                result.append(False)
685                self._take_bug_report(
686                    self.test_name, begin_time=get_current_epoch_time())
687                _continue = False
688                if not test_result(result, cycle, 10, 0.1):
689                    exit_due_to_high_fail_rate = True
690
691            if _continue:
692                if not wait_for_network_service(
693                    self.log,
694                    ad,
695                    wifi_connected=False,
696                    ims_reg=True):
697
698                    result.append(False)
699                    self._take_bug_report(
700                        self.test_name, begin_time=get_current_epoch_time())
701                    _continue = False
702                    if not test_result(result, cycle, 10, 0.1):
703                        exit_due_to_high_fail_rate = True
704
705            if _continue:
706                if voice_call:
707                    ad_mt = self.android_devices[1]
708                    call_params = [(
709                        ad,
710                        ad_mt,
711                        None,
712                        is_phone_in_call_volte,
713                        None)]
714                    call_result = two_phone_call_short_seq(
715                        self.log,
716                        ad,
717                        phone_idle_volte,
718                        is_phone_in_call_volte,
719                        ad_mt,
720                        None,
721                        None,
722                        wait_time_in_call=30,
723                        call_params=call_params)
724                    self.tel_logger.set_result(call_result.result_value)
725                    if not call_result:
726                        self._take_bug_report(
727                            self.test_name, begin_time=get_current_epoch_time())
728                        _continue = False
729                        if not test_result(result, cycle, 10, 0.1):
730                            exit_due_to_high_fail_rate = True
731
732            if _continue:
733                if not phone_setup_iwlan(
734                    self.log,
735                    ad,
736                    False,
737                    WFC_MODE_WIFI_PREFERRED,
738                    self.wifi_network_ssid,
739                    self.wifi_network_pass):
740
741                    result.append(False)
742                    self._take_bug_report(
743                        self.test_name, begin_time=get_current_epoch_time())
744                    _continue = False
745                    if not test_result(result, cycle, 10, 0.1):
746                        exit_due_to_high_fail_rate = True
747
748            if _continue:
749                if voice_slot == 0:
750                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT0
751                else:
752                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT1
753
754                if wait_for_log(ad, ims_pattern, begin_time=begin_time):
755                    ad.log.info(
756                        'IMS registration is handed over from LTE to iwlan.')
757                else:
758                    ad.log.error(
759                        'IMS registration is NOT yet handed over from LTE to '
760                        'iwlan.')
761
762            if voice_call:
763                hangup_call(self.log, ad)
764
765            if _continue:
766                if not verify_internet_connection(self.log, ad):
767                    result.append(VERIFY_INTERNET_FAIL)
768                    self._take_bug_report(
769                        self.test_name, begin_time=get_current_epoch_time())
770                    _continue = False
771                    if not test_result(result, cycle, 10, 0.1):
772                        exit_due_to_high_fail_rate = True
773
774            if _continue:
775                if not wait_for_wifi_disconnected(
776                    ad, self.wifi_network_ssid):
777                    result.append(False)
778                    self._take_bug_report(
779                        self.test_name, begin_time=get_current_epoch_time())
780                    _continue = False
781                    if not test_result(result, cycle, 10, 0.1):
782                        exit_due_to_high_fail_rate = True
783
784            if _continue:
785                if voice_slot == 0:
786                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_4G_SLOT0
787                else:
788                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_4G_SLOT1
789
790                if wait_for_log(ad, ims_pattern, begin_time=begin_time):
791                    ad.log.info(
792                        'IMS registration is handed over from iwlan to LTE.')
793                else:
794                    ad.log.error(
795                        'IMS registration is NOT yet handed over from iwlan to '
796                        'LTE.')
797
798            if _continue:
799                result.append(True)
800                end_time = datetime.now()
801                search_intervals.append([begin_time, end_time])
802
803            if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or (
804                attempt == cycle - 1) or exit_due_to_high_fail_rate:
805
806                ad.log.info(
807                    '====== Test result of IMS registration at slot %s ======',
808                    voice_slot)
809                ad.log.info(result)
810
811                ims_reg, parsing_fail, avg_ims_reg_duration = parse_ims_reg(
812                    ad, search_intervals, 'iwlan', 'apm')
813                ad.log.info(
814                    '====== IMS registration at slot %s ======', voice_slot)
815                for msg in ims_reg:
816                    ad.log.info(msg)
817
818                ad.log.info(
819                    '====== Attempt of parsing fail at slot %s ======' % voice_slot)
820                for msg in parsing_fail:
821                    ad.log.info(msg)
822
823                ad.log.warning('====== Summary ======')
824                ad.log.warning(
825                    '%s/%s cycles failed.',
826                    (len(result) - result.count(True)),
827                    len(result))
828                for attempt, value in enumerate(result):
829                    if value is not True:
830                        ad.log.warning('Cycle %s: %s', attempt+1, value)
831
832                try:
833                    fail_rate = (len(result) - result.count(True))/len(result)
834                    ad.log.info(
835                        'Fail rate of IMS registration at slot %s: %s',
836                        voice_slot,
837                        fail_rate)
838                except Exception as e:
839                    ad.log.error(
840                        'Fail rate of IMS registration at slot %s: ERROR (%s)',
841                        voice_slot,
842                        e)
843
844                ad.log.info(
845                    'Number of trials with valid parsed logs: %s',len(ims_reg))
846                ad.log.info(
847                    'Average IMS registration time at slot %s: %s',
848                    voice_slot, avg_ims_reg_duration)
849
850            if exit_due_to_high_fail_rate:
851                break
852
853        return test_result(result, cycle)
854
855    @test_tracker_info(uuid="e3d1aaa8-f673-4a2b-adb1-cfa525a4edbd")
856    @TelephonyBaseTest.tel_test_wrap
857    def test_ims_handover_4g_to_iwlan_with_voice_call_wfc_wifi_preferred(self):
858        """Connect WFC to make IMS registration hand over from LTE to iwlan in
859            Wi-Fi-preferred mode. Measure IMS handover time.
860
861        Test steps:
862            1. Enable WFC and set WFC mode to Wi-Fi-preferred mode.
863            2. Ensure Wi-Fi are disconnected and all cellular services are
864                available.
865            3. Make a VoLTE call and keep the call active.
866            4. Connect Wi-Fi. The IMS registration should hand over from LTE
867                to iwlan.
868            5. Parse logcat to calculate the IMS handover time.
869        """
870        return self.ims_handover_4g_to_iwlan_wfc_wifi_preferred(True)
871
872    @test_tracker_info(uuid="bd86fb46-04bd-4642-923a-747e6c9d4282")
873    @TelephonyBaseTest.tel_test_wrap
874    def test_ims_handover_4g_to_iwlan_wfc_wifi_preferred(self):
875        """Connect WFC to make IMS registration hand over from LTE to iwlan in
876            Wi-Fi-preferred mode. Measure IMS handover time.
877
878        Test steps:
879            1. Enable WFC and set WFC mode to Wi-Fi-preferred mode.
880            2. Ensure Wi-Fi are disconnected and all cellular services are
881                available.
882            3. Connect Wi-Fi. The IMS registration should hand over from LTE
883                to iwlan.
884            4. Parse logcat to calculate the IMS handover time.
885        """
886        return self.ims_handover_4g_to_iwlan_wfc_wifi_preferred(False)
887
888    def ims_handover_iwlan_to_4g_wfc_wifi_preferred(self, voice_call=False):
889        """Disconnect Wi-Fi to make IMS registration hand over from iwlan to LTE
890            in Wi-Fi-preferred mode. Measure IMS handover time.
891
892        Test steps:
893            1. Enable WFC, set WFC mode to Wi-Fi-preferred mode, and then
894                connect Wi-Fi to let IMS register over iwlan.
895            2. (Optional) Make a WFC call and keep the call active.
896            3. Disconnect Wi-Fi. The IMS registration should hand over from iwlan
897                to LTE.
898            4. Parse logcat to calculate the IMS handover time.
899
900        Args:
901            voice_call: True if an active WFC call is desired in the background
902                during IMS handover procedure. Otherwise False.
903        """
904        ad = self.android_devices[0]
905        if voice_call:
906            cycle = self.ims_handover_iwlan_to_4g_with_voice_call_wfc_wifi_preferred_test_cycle
907        else:
908            cycle = self.ims_handover_iwlan_to_4g_wfc_wifi_preferred_test_cycle
909        voice_slot = get_slot_index_from_voice_sub_id(ad)
910
911        result = []
912        search_intervals = []
913        exit_due_to_high_fail_rate = False
914        for attempt in range(cycle):
915            _continue = True
916            self.log.info(
917                '======> IMS handover from iwlan to LTE in WFC wifi-preferred '
918                'mode %s/%s <======',
919                attempt+1,
920                cycle)
921
922            begin_time = datetime.now()
923
924            if not phone_setup_iwlan(
925                self.log,
926                ad,
927                False,
928                WFC_MODE_WIFI_PREFERRED,
929                self.wifi_network_ssid,
930                self.wifi_network_pass):
931
932                result.append(False)
933                self._take_bug_report(
934                    self.test_name, begin_time=get_current_epoch_time())
935                _continue = False
936                if not test_result(result, cycle, 10, 0.1):
937                    exit_due_to_high_fail_rate = True
938
939                wait_for_wifi_disconnected(ad, self.wifi_network_ssid)
940
941            if _continue:
942                if voice_slot == 0:
943                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT0
944                else:
945                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT1
946
947                if wait_for_log(ad, ims_pattern, begin_time=begin_time):
948                    ad.log.info(
949                        'IMS registration is handed over from LTE to iwlan.')
950                else:
951                    ad.log.error(
952                        'IMS registration is NOT yet handed over from LTE to '
953                        'iwlan.')
954
955            if _continue:
956                if not verify_internet_connection(self.log, ad):
957                    result.append(VERIFY_INTERNET_FAIL)
958                    self._take_bug_report(
959                        self.test_name, begin_time=get_current_epoch_time())
960                    _continue = False
961                    if not test_result(result, cycle, 10, 0.1):
962                        exit_due_to_high_fail_rate = True
963
964            if _continue:
965                if voice_call:
966                    ad_mt = self.android_devices[1]
967                    call_params = [(
968                        ad,
969                        ad_mt,
970                        None,
971                        is_phone_in_call_iwlan,
972                        None)]
973                    call_result = two_phone_call_short_seq(
974                        self.log,
975                        ad,
976                        phone_idle_iwlan,
977                        is_phone_in_call_iwlan,
978                        ad_mt,
979                        None,
980                        None,
981                        wait_time_in_call=30,
982                        call_params=call_params)
983                    self.tel_logger.set_result(call_result.result_value)
984                    if not call_result:
985                        self._take_bug_report(
986                            self.test_name, begin_time=get_current_epoch_time())
987                        _continue = False
988                        if not test_result(result, cycle, 10, 0.1):
989                            exit_due_to_high_fail_rate = True
990
991            if _continue:
992                if not wait_for_wifi_disconnected(
993                    ad, self.wifi_network_ssid):
994                    result.append(False)
995                    self._take_bug_report(
996                        self.test_name, begin_time=get_current_epoch_time())
997                    _continue = False
998                    if not test_result(result, cycle, 10, 0.1):
999                        exit_due_to_high_fail_rate = True
1000
1001            if _continue:
1002                if voice_slot == 0:
1003                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_4G_SLOT0
1004                else:
1005                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_4G_SLOT1
1006
1007                if wait_for_log(ad, ims_pattern, begin_time=begin_time):
1008                    ad.log.info(
1009                        'IMS registration is handed over from iwlan to LTE.')
1010                else:
1011                    ad.log.error(
1012                        'IMS registration is NOT yet handed over from iwlan to '
1013                        'LTE.')
1014
1015            if voice_call:
1016                hangup_call(self.log, ad)
1017
1018            if _continue:
1019                if not wait_for_network_service(
1020                    self.log,
1021                    ad,
1022                    wifi_connected=False,
1023                    ims_reg=True):
1024
1025                    result.append(False)
1026                    self._take_bug_report(
1027                        self.test_name, begin_time=get_current_epoch_time())
1028                    _continue = False
1029                    if not test_result(result, cycle, 10, 0.1):
1030                        exit_due_to_high_fail_rate = True
1031
1032            if _continue:
1033                result.append(True)
1034                end_time = datetime.now()
1035                search_intervals.append([begin_time, end_time])
1036
1037            if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or (
1038                attempt == cycle - 1) or exit_due_to_high_fail_rate:
1039
1040                ad.log.info(
1041                    '====== Test result of IMS registration at slot %s ======',
1042                    voice_slot)
1043                ad.log.info(result)
1044
1045                ims_reg, parsing_fail, avg_ims_reg_duration = parse_ims_reg(
1046                    ad, search_intervals, '4g', 'wifi_off')
1047                ad.log.info(
1048                    '====== IMS registration at slot %s ======', voice_slot)
1049                for msg in ims_reg:
1050                    ad.log.info(msg)
1051
1052                ad.log.info(
1053                    '====== Attempt of parsing fail at slot %s ======' % voice_slot)
1054                for msg in parsing_fail:
1055                    ad.log.info(msg)
1056
1057                ad.log.warning('====== Summary ======')
1058                ad.log.warning(
1059                    '%s/%s cycles failed.',
1060                    (len(result) - result.count(True)),
1061                    len(result))
1062                for attempt, value in enumerate(result):
1063                    if value is not True:
1064                        ad.log.warning('Cycle %s: %s', attempt+1, value)
1065
1066                try:
1067                    fail_rate = (len(result) - result.count(True))/len(result)
1068                    ad.log.info(
1069                        'Fail rate of IMS registration at slot %s: %s',
1070                        voice_slot,
1071                        fail_rate)
1072                except Exception as e:
1073                    ad.log.error(
1074                        'Fail rate of IMS registration at slot %s: ERROR (%s)',
1075                        voice_slot,
1076                        e)
1077
1078                ad.log.info(
1079                    'Number of trials with valid parsed logs: %s', len(ims_reg))
1080                ad.log.info(
1081                    'Average IMS registration time at slot %s: %s',
1082                    voice_slot, avg_ims_reg_duration)
1083
1084            if exit_due_to_high_fail_rate:
1085                break
1086
1087        return test_result(result, cycle)
1088
1089    @test_tracker_info(uuid="6ce623a6-7ef9-42db-8099-d5c449e70bff")
1090    @TelephonyBaseTest.tel_test_wrap
1091    def test_ims_handover_iwlan_to_4g_wfc_wifi_preferred(self):
1092        """Disconnect Wi-Fi to make IMS registration hand over from iwlan to LTE
1093            in Wi-Fi-preferred mode. Measure IMS handover time.
1094
1095        Test steps:
1096            1. Enable WFC, set WFC mode to Wi-Fi-preferred mode, and then
1097                connect Wi-Fi to let IMS register over iwlan.
1098            2. Disconnect Wi-Fi. The IMS registration should hand over from iwlan
1099                to LTE.
1100            3. Parse logcat to calculate the IMS handover time.
1101        """
1102        return self.ims_handover_iwlan_to_4g_wfc_wifi_preferred(False)
1103
1104    @test_tracker_info(uuid="b965ab09-d8b1-423f-bb98-2cdd43babbe3")
1105    @TelephonyBaseTest.tel_test_wrap
1106    def test_ims_handover_iwlan_to_4g_with_voice_call_wfc_wifi_preferred(self):
1107        """Disconnect Wi-Fi to make IMS registration hand over from iwlan to LTE
1108            in Wi-Fi-preferred mode. Measure IMS handover time.
1109
1110        Test steps:
1111            1. Enable WFC, set WFC mode to Wi-Fi-preferred mode, and then
1112                connect Wi-Fi to let IMS register over iwlan.
1113            2. Make a WFC call and keep the call active.
1114            3. Disconnect Wi-Fi. The IMS registration should hand over from iwlan
1115                to LTE.
1116            4. Parse logcat to calculate the IMS handover time.
1117        """
1118        return self.ims_handover_iwlan_to_4g_wfc_wifi_preferred(True)
1119
1120    def ims_handover_iwlan_to_4g_wfc_cellular_preferred(self, voice_call=False):
1121        """Turn off airplane mode to make IMS registration hand over from iwlan to LTE
1122            in WFC cellular-preferred mode. Measure IMS handover time.
1123
1124        Test steps:
1125            1. Enable WFC, set WFC mode to cellular-preferred mode, turn on
1126                airplane mode and then connect Wi-Fi to let IMS register over
1127                iwlan.
1128            2. (Optional) Make a WFC call and keep the call active.
1129            3. Turn off airplane mode. The IMS registration should hand over
1130                from iwlan to LTE.
1131            4. Parse logcat to calculate the IMS handover time.
1132
1133        Args:
1134            voice_call: True if an active WFC call is desired in the background
1135                during IMS handover procedure. Otherwise False.
1136        """
1137        ad = self.android_devices[0]
1138        if voice_call:
1139            cycle = self.ims_handover_iwlan_to_4g_with_voice_call_wfc_cellular_preferred_test_cycle
1140        else:
1141            cycle = self.ims_handover_iwlan_to_4g_wfc_cellular_preferred_test_cycle
1142
1143        voice_slot = get_slot_index_from_voice_sub_id(ad)
1144
1145        result = []
1146        search_intervals = []
1147        exit_due_to_high_fail_rate = False
1148        for attempt in range(cycle):
1149            _continue = True
1150
1151            self.log.info(
1152                '======> IMS handover from iwlan to LTE in WFC '
1153                'cellular-preferred mode %s/%s <======',
1154                attempt+1,
1155                cycle)
1156
1157            begin_time = datetime.now()
1158
1159            if not phone_setup_iwlan(
1160                self.log,
1161                ad,
1162                True,
1163                WFC_MODE_CELLULAR_PREFERRED,
1164                self.wifi_network_ssid,
1165                self.wifi_network_pass):
1166
1167                result.append(False)
1168                self._take_bug_report(
1169                    self.test_name, begin_time=get_current_epoch_time())
1170                _continue = False
1171                if not test_result(result, cycle, 10, 0.1):
1172                    exit_due_to_high_fail_rate = True
1173
1174                toggle_airplane_mode(self.log, ad, False)
1175
1176            if _continue:
1177                if voice_slot == 0:
1178                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT0
1179                else:
1180                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_IWLAN_SLOT1
1181
1182                if wait_for_log(ad, ims_pattern, begin_time=begin_time):
1183                    ad.log.info(
1184                        'IMS registration is handed over from LTE to iwlan.')
1185                else:
1186                    ad.log.error(
1187                        'IMS registration is NOT yet handed over from LTE to '
1188                        'iwlan.')
1189
1190            if _continue:
1191                if not verify_internet_connection(self.log, ad):
1192                    result.append(VERIFY_INTERNET_FAIL)
1193                    self._take_bug_report(
1194                        self.test_name, begin_time=get_current_epoch_time())
1195                    _continue = False
1196                    if not test_result(result, cycle, 10, 0.1):
1197                        exit_due_to_high_fail_rate = True
1198
1199            if _continue:
1200                if voice_call:
1201                    ad_mt = self.android_devices[1]
1202                    call_params = [(
1203                        ad,
1204                        ad_mt,
1205                        None,
1206                        is_phone_in_call_iwlan,
1207                        None)]
1208                    call_result = two_phone_call_short_seq(
1209                        self.log,
1210                        ad,
1211                        phone_idle_iwlan,
1212                        is_phone_in_call_iwlan,
1213                        ad_mt,
1214                        None,
1215                        None,
1216                        wait_time_in_call=30,
1217                        call_params=call_params)
1218                    self.tel_logger.set_result(call_result.result_value)
1219                    if not call_result:
1220                        self._take_bug_report(
1221                            self.test_name, begin_time=get_current_epoch_time())
1222                        _continue = False
1223                        if not test_result(result, cycle, 10, 0.1):
1224                            exit_due_to_high_fail_rate = True
1225
1226            if _continue:
1227                if not toggle_airplane_mode(self.log, ad, False):
1228                    result.append(TOGGLE_OFF_APM_FAIL)
1229                    self._take_bug_report(
1230                        self.test_name, begin_time=get_current_epoch_time())
1231                    _continue = False
1232                    if not test_result(result, cycle, 10, 0.1):
1233                        exit_due_to_high_fail_rate = True
1234
1235            if _continue:
1236                if voice_slot == 0:
1237                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_4G_SLOT0
1238                else:
1239                    ims_pattern = ON_IMS_MM_TEL_CONNECTED_4G_SLOT1
1240
1241                if wait_for_log(ad, ims_pattern, begin_time=begin_time):
1242                    ad.log.info(
1243                        'IMS registration is handed over from iwlan to LTE.')
1244                else:
1245                    ad.log.error(
1246                        'IMS registration is NOT yet handed over from iwlan to '
1247                        'LTE.')
1248
1249            if voice_call:
1250                hangup_call(self.log, ad)
1251
1252            if _continue:
1253                if not wait_for_network_service(
1254                    self.log,
1255                    ad,
1256                    wifi_connected=True,
1257                    wifi_ssid=self.wifi_network_ssid,
1258                    ims_reg=True):
1259
1260                    result.append(False)
1261                    self._take_bug_report(
1262                        self.test_name, begin_time=get_current_epoch_time())
1263                    _continue = False
1264                    if not test_result(result, cycle, 10, 0.1):
1265                        exit_due_to_high_fail_rate = True
1266
1267            if _continue:
1268                result.append(True)
1269                end_time = datetime.now()
1270                search_intervals.append([begin_time, end_time])
1271
1272            if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or (
1273                attempt == cycle - 1) or exit_due_to_high_fail_rate:
1274
1275                ad.log.info(
1276                    '====== Test result of IMS registration at slot %s ======',
1277                    voice_slot)
1278                ad.log.info(result)
1279
1280                ims_reg, parsing_fail, avg_ims_reg_duration = parse_ims_reg(
1281                    ad, search_intervals, '4g', 'apm')
1282                ad.log.info(
1283                    '====== IMS registration at slot %s ======', voice_slot)
1284                for msg in ims_reg:
1285                    ad.log.info(msg)
1286
1287                ad.log.info(
1288                    '====== Attempt of parsing fail at slot %s ======' % voice_slot)
1289                for msg in parsing_fail:
1290                    ad.log.info(msg)
1291
1292                ad.log.warning('====== Summary ======')
1293                ad.log.warning(
1294                    '%s/%s cycles failed.',
1295                    (len(result) - result.count(True)),
1296                    len(result))
1297                for attempt, value in enumerate(result):
1298                    if value is not True:
1299                        ad.log.warning('Cycle %s: %s', attempt+1, value)
1300
1301                try:
1302                    fail_rate = (len(result) - result.count(True))/len(result)
1303                    ad.log.info(
1304                        'Fail rate of IMS registration at slot %s: %s',
1305                        voice_slot,
1306                        fail_rate)
1307                except Exception as e:
1308                    ad.log.error(
1309                        'Fail rate of IMS registration at slot %s: ERROR (%s)',
1310                        voice_slot,
1311                        e)
1312
1313                ad.log.info(
1314                    'Number of trials with valid parsed logs: %s', len(ims_reg))
1315                ad.log.info(
1316                    'Average IMS registration time at slot %s: %s',
1317                    voice_slot, avg_ims_reg_duration)
1318
1319            if exit_due_to_high_fail_rate:
1320                break
1321
1322        return test_result(result, cycle)
1323
1324    @test_tracker_info(uuid="ce69fac3-931b-4177-82ea-dbae50b2b310")
1325    @TelephonyBaseTest.tel_test_wrap
1326    def test_ims_handover_iwlan_to_4g_wfc_cellular_preferred(self):
1327        """Turn off airplane mode to make IMS registration hand over from iwlan to LTE
1328            in WFC cellular-preferred mode. Measure IMS handover time.
1329
1330        Test steps:
1331            1. Enable WFC, set WFC mode to cellular-preferred mode, turn on
1332                airplane mode and then connect Wi-Fi to let IMS register over
1333                iwlan.
1334            2. Turn off airplane mode. The IMS registration should hand over
1335                from iwlan to LTE.
1336            3. Parse logcat to calculate the IMS handover time.
1337        """
1338        return self.ims_handover_iwlan_to_4g_wfc_cellular_preferred(False)
1339
1340    @test_tracker_info(uuid="0ac7d43e-34e6-4ea3-92f4-e413e90a8bc1")
1341    @TelephonyBaseTest.tel_test_wrap
1342    def test_ims_handover_iwlan_to_4g_with_voice_call_wfc_cellular_preferred(self):
1343        """Turn off airplane mode to make IMS registration hand over from iwlan to LTE
1344            in WFC cellular-preferred mode. Measure IMS handover time.
1345
1346        Test steps:
1347            1. Enable WFC, set WFC mode to cellular-preferred mode, turn on
1348                airplane mode and then connect Wi-Fi to let IMS register over
1349                iwlan.
1350            2. Make a WFC call and keep the call active.
1351            3. Turn off airplane mode. The IMS registration should hand over
1352                from iwlan to LTE.
1353            4. Parse logcat to calculate the IMS handover time.
1354        """
1355        return self.ims_handover_iwlan_to_4g_wfc_cellular_preferred(True)