xref: /aosp_15_r20/external/autotest/server/cros/bluetooth/bluetooth_adapter_leadvertising_tests.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright 2016 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Server side bluetooth tests on adapter ble advertising.
7
8The Mnemonics describing the test cases:
9    CD: check advertising duration and intervals
10    RA: register advertisements
11    UA: unregister advertisements
12    SI: set advertising intervals
13    RS: reset advertising
14    FRA: fail to register extra advertisements when max ones
15         have been registered.
16    FSI: fail to set advertising intervals beyond legitimate range
17         of [20 ms, 10,240 ms].
18    PC: power cycle the bluetooth adapter (controller).
19    SR: suspend and resume the DUT (chromebook)
20
21A test represents a component of a test case which comprises a
22sequence of tests. A test case usually requires a tester (user)
23to perform a sequence of actions and make a sequence of
24observations if the test case is performed manually.
25
26A test consists of an optional action such as "register n
27advertisements" and a number of test criteria such as "verifying
28if min advertising interval is set to an expected value" or
29"verifying if advertising is disabled".
30
31"""
32
33from __future__ import absolute_import
34from __future__ import division
35from __future__ import print_function
36
37import copy
38import logging
39import re
40import time
41
42import common
43from autotest_lib.server.cros.bluetooth import advertisements_data
44from autotest_lib.server.cros.bluetooth import bluetooth_adapter_tests
45from six.moves import range
46from six.moves import zip
47
48test_case_log = bluetooth_adapter_tests.test_case_log
49test_retry_and_log = bluetooth_adapter_tests.test_retry_and_log
50
51class bluetooth_AdapterLEAdvertising(
52        bluetooth_adapter_tests.BluetoothAdapterTests):
53    """Server side bluetooth adapter advertising Test.
54
55    This class comprises a number of test cases to verify
56    bluetooth low-energy advertising.
57
58    Refer to BluetoothAdapterTests for the implementation of the tests
59    performed in this autotest test.
60
61    Refer to the design doc for more details:
62    "Test Cases for Bluetooth Low-Energy Advertising".
63
64    """
65
66    # The software advertising rotation is a default bluez parameter, 2 seconds
67    SOFTWARE_ROTATION_INTERVAL_S = 2
68
69    # If hardware offloading is available, a 'default' discovery time is used,
70    # that will not depend on number of advertisements registered since they are
71    # advertised in parallel.
72    DEFAULT_DISCOVERY_TIME_S = 3
73
74    @staticmethod
75    def get_instance_ids(advertisements):
76        """Get the list of instace IDs starting at 1.
77
78        @param advertisements: a list of advertisements.
79
80        """
81        return list(range(1, len(advertisements) + 1))
82
83
84    def register_advertisements(self, advertisements, min_adv_interval_ms,
85                                max_adv_interval_ms, instance_ids=None):
86        """Register multiple advertisements continuously.
87
88        @param advertisements: a list of advertisement instances.
89        @param min_adv_interval_ms: min_adv_interval in milliseconds.
90        @param max_adv_interval_ms: max_adv_interval in milliseconds.
91        @param instance_ids: the list of instance IDs to register.
92        """
93        if instance_ids is None:
94            instance_ids = self.get_instance_ids(advertisements)
95
96        for instance_id, advertisement in zip(instance_ids, advertisements):
97            advertisement['MinInterval'] = min_adv_interval_ms
98            advertisement['MaxInterval'] = max_adv_interval_ms
99
100            self.test_register_advertisement(advertisement, instance_id)
101
102
103    def unregister_advertisements(self, advertisements, instance_ids=None):
104        """Register multiple advertisements.
105
106        @param advertisements: a list of advertisement instances.
107        @param instance_ids: the list of instance IDs to unregister.
108
109        """
110        if instance_ids is None:
111            instance_ids = self.get_instance_ids(advertisements)
112
113        count = 0
114        number_advs = len(advertisements)
115        for instance_id, advertisement in zip(instance_ids, advertisements):
116            # Advertising is only disabled at the removal of the
117            # last advertisement.
118            count += 1
119            advertising_disabled = count == number_advs
120            self.test_unregister_advertisement(advertisement,
121                                               instance_id,
122                                               advertising_disabled)
123
124
125    def check_kernel_version(self):
126        """ Check if test can execute on this kernel version."""
127
128        logging.info("Checking kernel version {}".format(self.kernel_version))
129        #
130        # Due to crbug/729648, we cannot set advertising intervals
131        # on kernels that are 3.8.11 and below, so we raise TestNAError.
132        # 3.8.12 used so that version of the form 3.8.11<suffix> fails the check
133        #
134        self.is_supported_kernel_version(self.kernel_version, "3.8.12",
135                                         'Test cannnot proceed on old kernels')
136        #
137        # Due to crbug/946835, some messages does not reach btmon
138        # causing our tests to fails. This is seen on kernel 3.18 and lower.
139        # Remove this check when the issue is fixed
140        # TODO(crbug/946835)
141        #
142        self.is_supported_kernel_version(self.kernel_version, "3.19",
143                                         'Test cannnot proceed on this'
144                                         'kernel due to crbug/946835 ')
145        logging.debug("Test is supported on this kernel version")
146
147
148    # ---------------------------------------------------------------
149    # Definitions of all test cases
150    # ---------------------------------------------------------------
151
152    def _get_uuids_from_advertisement(self, adv, type):
153        """Parses Solicit or Service UUIDs from advertising data
154
155        Data to be parsed has the following structure:
156        16-bit Service UUIDs (complete): 2 entries
157            Heart Rate (0x180d)
158            Battery Service (0x180f)
159
160        @param adv: string advertising data as collected by btmon
161        @param type: Type of UUIDs to parse, either 'Solicit' or 'Service'
162
163        @returns: list of UUIDs as ints
164        """
165        if not adv:
166            return []
167
168        lines = adv.split('\n')
169        num_uuids = 0
170        # Find Service UUID section in adv and grab number of entries
171        for idx, line in enumerate(lines):
172            if '{} UUIDs (complete)'.format(type) in line:
173                search_res = re.search('(\d) entr', line)
174                if search_res and search_res.group(1):
175                    num_uuids = int(search_res.group(1))
176                    break
177
178        found_uuids = []
179        # Iterate through each entry and collect UUIDs. UUIDs are saved as ints
180        # to reduce complexity of comparing hex strings, i.e. ab vs AB vs 0xab
181        for lineidx in range(idx+1, idx+num_uuids+1):
182            line = lines[lineidx]
183            search_res = re.search('\((.*?)\)', line)
184            if search_res and search_res.group(1):
185                uuid = search_res.group(1)
186                found_uuids.append(int(uuid, 16))
187
188        return found_uuids
189
190
191    def _get_company_data_from_advertisement(self, adv):
192        """Parses Company ID and associated company data from advertisement
193
194        Data to be parsed has the following structure:
195        Company: not assigned (65281)
196            Data: 1a1b1c1d1e
197
198        @param adv: string advertising data as collected by btmon
199
200        @returns: dictionary with structure {company uuid: company data}
201        """
202
203        lines = adv.split('\n')
204
205        for idx, line in enumerate(lines):
206            if 'Company:' in line:
207                search_res = re.search('\((.*?)\)', line)
208                if search_res and search_res.group(1):
209                    company_id = int(search_res.group(1))
210                    break
211
212        # Company data is on the line after the header, and is the last block
213        # printed
214        if company_id and idx+1 < len(lines):
215            company_data = lines[idx+1].split(' ')[-1]
216            return {company_id: company_data}
217
218        return {}
219
220
221    def _get_service_data_from_advertisement(self, adv):
222        """Parses Service data from advertisement
223
224        Data to be parsed has the following structure:
225        Service Data (UUID 0x9991): 1112131415
226
227        @param adv: string advertising data as collected by btmon
228
229        @returns: dictionary with structure {company uuid: company data}
230        """
231
232        lines = adv.split('\n')
233
234        discovered_service_data = {}
235        # Iterate through lines in advertisement, grabbing Service Data entries
236        for line in lines:
237            if 'Service Data' in line:
238                search_res = re.search('\(UUID (.*?)\)', line)
239                if search_res and search_res.group(1):
240                    found_uuid = search_res.group(1)
241                    found_data = line.split(' ')[-1]
242
243                    discovered_service_data[int(found_uuid, 16)] = found_data
244
245        return discovered_service_data
246
247
248    def validate_scan_rsp_reception(self, peer, advertisement, discover_time):
249        """Validate our advertisement's scan response is located by the peer
250
251        If our advertisements are configured with scan response data, we wish
252        to confirm that a scanning peer will be able to discover this content.
253
254        @param peer: Handle to peer device for advertisement collection
255        @param advertisement: Advertisement data that has been enabled on DUT
256            side
257        @param discover_time: Number of seconds we should spend discovering
258            before considering the device undiscoverable
259
260        @returns: True if scan response is discovered and is correct, else False
261        """
262
263        scan_rsp_data = advertisement.get('ScanResponseData', {})
264
265        # For now, scan response can only contain service data (ad type 0x16):
266        # It appears in a scan response event with the following format:
267        # 'Service Data (UUID 0xfef3): 010203...'
268        if '0x16' in scan_rsp_data:
269            service_uuid_data = scan_rsp_data['0x16']
270
271            # First two bytes of data make up 16 bit service UUID
272            uuid = service_uuid_data[1] * 256 + service_uuid_data[0]
273            # Subsequent bytes make up the service data
274            service_data = ''.join(
275                    ['{:02x}'.format(data) for data in service_uuid_data[2:]])
276
277            search_str = 'Service Data (UUID 0x{:4x}): {}'.format(
278                    uuid, service_data)
279            logging.debug('Searching btmon for content: {}'.format(search_str))
280
281            # Locate a scan response with the above entry. Pass if it is found
282            start_time = time.time()
283            found_adv = peer.FindAdvertisementWithAttributes(
284                    [search_str, 'SCAN_RSP'], discover_time)
285
286            logging.info('Scan response discovered after %fs',
287                         time.time() - start_time)
288
289            return bool(found_adv)
290
291        return True
292
293    def _test_peer_received_correct_adv(self, peer, advertisement,
294                                        discover_time):
295        """Test that configured advertisements are found by peer
296
297        We need to verify quality of advertising service from the perspective of
298        the client, as this is externally visible in cases like Nearby features.
299        This test ensures advertisements are discovered and are correct,
300        helping to confirm quality provided, especially with multi-advertising
301
302        @param peer: Handle to peer device for advertisement collection
303        @param advertisement: Advertisement data that has been enabled on DUT
304            side
305        @param discover_time: Number of seconds we should spend discovering
306            before considering the device undiscoverable
307
308        @returns: True if advertisement is discovered and is correct, else False
309        """
310
311        self.results = {}
312
313        # We locate the advertisement by searching for the ServiceData
314        # attribute we configured.
315        data_to_match = list(advertisement['ServiceData'].keys())[0]
316
317        start_time = time.time()
318        found_adv = peer.FindAdvertisementWithAttributes([data_to_match],
319                                                         discover_time)
320        logging.info('Advertisement discovered after %fs',
321                     time.time() - start_time)
322
323        if not found_adv:
324            self.results['advertisement_found'] = False
325
326        # Check that our service UUIDs match what we expect
327        found_service_uuids = self._get_uuids_from_advertisement(
328                found_adv, 'Service')
329
330        for UUID in advertisement.get('ServiceUUIDs', []):
331            if int(UUID, 16) not in found_service_uuids:
332                logging.info('Service id %d not found in %s', int(UUID, 16),
333                             str(found_service_uuids))
334                self.results['service_ids_found'] = False
335                return False
336
337        # Check that our solicit UUIDs match what we expect
338        found_solicit_uuids = self._get_uuids_from_advertisement(
339                found_adv, 'Solicit')
340
341        for UUID in advertisement.get('SolicitUUIDs', []):
342            if int(UUID, 16) not in found_solicit_uuids:
343                logging.info('Solicid ID %d not found in %s', int(UUID, 16),
344                             str(found_solicit_uuids))
345                self.results['solicit_ids_found'] = False
346                return False
347
348        # Check that our Manufacturer info is correct
349        company_info = self._get_company_data_from_advertisement(found_adv)
350
351        expected_company_info = advertisement.get('ManufacturerData', {})
352        for UUID in expected_company_info:
353            if int(UUID, 16) not in company_info:
354                logging.info('Company ID %d not found in advertisement',
355                        int(UUID, 16))
356                self.results['manufacturer_uuid_found'] = False
357                return False
358
359            expected_data = expected_company_info.get(UUID, None)
360            formatted_data = ''.join([format(d, 'x') for d in expected_data])
361
362            if formatted_data != company_info.get(int(UUID, 16)):
363                logging.info('Manufacturer data %s didn\'t match expected %s',
364                        company_info.get(int(UUID, 16)), formatted_data)
365                self.results['manufacturer_data_found'] = False
366                return False
367
368        # Check that our service data is correct
369        service_data = self._get_service_data_from_advertisement(found_adv)
370
371        expected_service_data = advertisement.get('ServiceData', {})
372        for UUID in expected_service_data:
373            if int(UUID, 16) not in service_data:
374                logging.info('Service UUID %d not found in advertisement',
375                             int(UUID, 16))
376                self.results['service_data_uuid_found'] = False
377                return False
378
379            expected_data = expected_service_data.get(UUID, None)
380            formatted_data = ''.join([format(d, 'x') for d in expected_data])
381
382            if formatted_data != service_data.get(int(UUID, 16)):
383                logging.info('Service data %s didn\'t match expected %s',
384                             service_data.get(int(UUID, 16)), formatted_data)
385                self.results['service_data_found'] = False
386                return False
387
388        # Validate scan response from peer's perspective
389        if not self.validate_scan_rsp_reception(peer, advertisement,
390                                                discover_time):
391            self.results['scan_rsp_found'] = False
392            return False
393
394        return True
395
396
397    def get_host_discovery_time(self, num_adv):
398        """Estimates how long it will take the peer to discover the host
399
400        The amount of time we wait for the peer to discover the host's
401        advertisement depends on how many advertisements are registered, and
402        whether the host platform is using hardware offloaded multi-advertising
403        or software rotation.
404
405        @param num_adv: Number of advertisements that are active
406        @returns: number of seconds we should wait for discovery
407        """
408
409        if self.ext_adv_enabled():
410            return self.DEFAULT_DISCOVERY_TIME_S
411
412        return num_adv * self.SOFTWARE_ROTATION_INTERVAL_S
413
414    @test_retry_and_log(False)
415    def test_peer_received_correct_adv(self, peer, advertisement,
416                                       discover_time):
417        """Tests that advertisement can be received by the peer"""
418
419        return self._test_peer_received_correct_adv(peer, advertisement,
420                                                    discover_time)
421
422    @test_retry_and_log(False, messages_start=False, messages_stop=False)
423    def test_peer_failed_received_correct_adv(self, peer, advertisement,
424                                              discover_time):
425        """Tests that advertisement can not be received by the peer"""
426
427        return not self._test_peer_received_correct_adv(
428                peer, advertisement, discover_time)
429
430    def advertising_peer_test(self, peer):
431        """Verifies that advertisements registered on DUT are seen by peer
432
433        @param peer: handle to peer used in test
434        """
435
436        self.kernel_version = self.host.get_kernel_version()
437        self.check_kernel_version()
438
439        self.bluetooth_le_facade = self.bluetooth_facade
440
441        # Register some advertisements
442        num_adv = 3
443        self.test_reset_advertising()
444
445        for i in range(0, num_adv):
446            self.bluetooth_le_facade.register_advertisement(
447                    advertisements_data.ADVERTISEMENTS[i])
448
449        discover_time = self.get_host_discovery_time(num_adv)
450
451        for i in range(0, num_adv):
452            res = self.test_peer_received_correct_adv(
453                    peer, advertisements_data.ADVERTISEMENTS[i], discover_time)
454
455    def advertising_peer_suspend_resume_test(self, peer):
456        """Verify expected advertising behavior around suspend/resume
457
458        For power and usage sake, we expect that when the system suspends, any
459        advertising instances should be paused. When we resume from suspend,
460        they should be re-enabled again. To confirm this behavior, the test
461        performs the following steps:
462
463        - Register some advertisements
464        - Verify that advertisements are discoverable by remote device
465        - Enter suspend
466        - Verify that advertisements are NOT discoverable by remote device
467        - Exit suspend
468        - Verify that advertisements are discoverable by remote device
469
470        @param peer: handle to peer used in test
471        """
472
473        self.kernel_version = self.host.get_kernel_version()
474        self.check_kernel_version()
475
476        self.bluetooth_le_facade = self.bluetooth_facade
477
478        # Register some advertisements
479        num_adv = 3
480        discover_time = self.get_host_discovery_time(num_adv)
481        self.test_reset_advertising()
482
483        for i in range(0, num_adv):
484            self.bluetooth_le_facade.register_advertisement(
485                    advertisements_data.ADVERTISEMENTS[i])
486
487        # Verify they can all be discovered
488        for i in range(0, num_adv):
489            res = self.test_peer_received_correct_adv(
490                    peer, advertisements_data.ADVERTISEMENTS[i], discover_time)
491
492        # Enter suspend long enough to verify none of the registered
493        # advertisements are discoverable. Give a few extra seconds in suspend
494        # to be safe
495        suspend_time = discover_time * num_adv + 10
496        logging.debug(
497                'suspend_time(%d) = discover_time(%d) * num_adv(%d) + 10',
498                suspend_time, discover_time, num_adv)
499
500        # Trigger suspend, asynchronously trigger wake and wait for resume
501        boot_id = self.host.get_boot_id()
502        suspend = self.suspend_async(suspend_time=suspend_time)
503        start_time = self.bluetooth_facade.get_device_utc_time()
504        self.test_suspend_and_wait_for_sleep(suspend, sleep_timeout=5)
505
506        # Verify they can not be discovered
507        for i in range(0, num_adv):
508            res = self.test_peer_failed_received_correct_adv(
509                    peer, advertisements_data.ADVERTISEMENTS[i], discover_time)
510
511        # Wait for device to come out of suspend
512        logging.debug('test_wait_for_resume(resume_timeout=%d, start_time=%s)',
513                      suspend_time, start_time)
514        self.test_wait_for_resume(boot_id,
515                                  suspend,
516                                  resume_timeout=suspend_time,
517                                  test_start_time=start_time)
518
519        # Verify reception of advertisements again
520        for i in range(0, num_adv):
521            res = self.test_peer_received_correct_adv(
522                    peer, advertisements_data.ADVERTISEMENTS[i], discover_time)
523
524
525    @test_case_log
526    def test_case_SI200_RA3_CD_UA3(self):
527        """Test Case: SI(200) - RA(3) - CD - UA(3)"""
528        new_min_adv_interval_ms = 200
529        new_max_adv_interval_ms = 200
530        advertisements = self.three_advertisements
531
532        self.test_reset_advertising()
533
534        self.register_advertisements(advertisements, new_min_adv_interval_ms,
535                                     new_max_adv_interval_ms)
536
537        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
538                                               new_max_adv_interval_ms,
539                                               len(advertisements))
540
541        self.unregister_advertisements(advertisements)
542
543
544    @test_case_log
545    def test_case_SI200_RA3_CD_RA1_CD_UA1_CD_UA3(self):
546        """Test Case: SI(200) - RA(3) - CD - RA(1) - CD - UA(1) - CD - UA(3)"""
547        new_min_adv_interval_ms = 200
548        new_max_adv_interval_ms = 200
549        # Make a copy of advertisements since we are going to modify it.
550        advertisements = copy.copy(self.three_advertisements)
551        number_advs = len(advertisements)
552        one_more_advertisement = [self.sixth_advertisement]
553
554        self.test_reset_advertising()
555
556        self.register_advertisements(advertisements, new_min_adv_interval_ms,
557                                     new_max_adv_interval_ms)
558
559        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
560                                               new_max_adv_interval_ms,
561                                               number_advs)
562
563        # Register one more advertisement.
564        # The instance ID to register is len(advertisements) + 1 = 4
565        self.register_advertisements(one_more_advertisement,
566                                     new_min_adv_interval_ms,
567                                     new_max_adv_interval_ms,
568                                     instance_ids=[number_advs + 1])
569
570        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
571                                               new_max_adv_interval_ms,
572                                               number_advs + 1)
573
574        # Unregister the 3rd advertisement.
575        # After removing the advertisement, the remaining instance IDs
576        # would be [1, 2, 4]
577        instance_id = 3
578        self.test_unregister_advertisement(advertisements.pop(instance_id - 1),
579                                           instance_id,
580                                           advertising_disabled=False)
581
582        if not self.ext_adv_enabled():
583            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
584                                                   new_max_adv_interval_ms,
585                                                   number_advs)
586
587        # Unregister all existing advertisements which are [1, 2, 4]
588        # since adv 3 was removed in the previous step.
589        self.unregister_advertisements(advertisements + one_more_advertisement,
590                                       instance_ids=[1, 2, 4])
591
592
593    @test_case_log
594    def test_case_SI200_RA3_CD_RS(self):
595        """Test Case: SI(200) - RA(3) - CD - RS"""
596        new_min_adv_interval_ms = 200
597        new_max_adv_interval_ms = 200
598        advertisements = self.three_advertisements
599        number_advs = len(advertisements)
600
601        self.test_reset_advertising()
602
603        self.register_advertisements(advertisements, new_min_adv_interval_ms,
604                                     new_max_adv_interval_ms)
605
606        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
607                                               new_max_adv_interval_ms,
608                                               number_advs)
609
610        self.test_reset_advertising(self.get_instance_ids(advertisements))
611
612
613    @test_case_log
614    def test_case_SI200_RA3_CD_UA1_CD_RS(self):
615        """Test Case: SI(200) - RA(3) - CD - UA(1) - CD - RS"""
616        new_min_adv_interval_ms = 200
617        new_max_adv_interval_ms = 200
618        # Make a copy of advertisements since we are going to modify it.
619        advertisements = copy.copy(self.three_advertisements)
620
621        self.test_reset_advertising()
622
623        self.register_advertisements(advertisements, new_min_adv_interval_ms,
624                                     new_max_adv_interval_ms)
625
626        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
627                                               new_max_adv_interval_ms,
628                                               len(advertisements))
629
630        # Unregister the 1st advertisement.
631        # After removing the advertisement, the remaining instance IDs
632        # would be [2, 3]
633        instance_id = 1
634        self.test_unregister_advertisement(advertisements.pop(instance_id - 1),
635                                           instance_id,
636                                           advertising_disabled=False)
637
638        if not self.ext_adv_enabled():
639            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
640                                                   new_max_adv_interval_ms,
641                                                   len(advertisements) - 1)
642
643        self.test_reset_advertising([2, 3])
644
645
646    @test_case_log
647    def test_case_SI200_RA3_CD_UA1_CD_RA2_CD_UA4(self):
648        """Test Case: SI(200) - RA(3) - CD - UA(1) - CD - RA(2) - CD - UA(4)"""
649        new_min_adv_interval_ms = 200
650        new_max_adv_interval_ms = 200
651        # Make a copy of three_advertisements since we are going to modify it.
652        advertisements1 = copy.copy(self.three_advertisements)
653        advertisements2 = self.two_advertisements
654        number_advs1 = len(advertisements1)
655        number_advs2 = len(advertisements2)
656
657        self.test_reset_advertising()
658
659        self.register_advertisements(advertisements1, new_min_adv_interval_ms,
660                                     new_max_adv_interval_ms)
661
662        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
663                                               new_max_adv_interval_ms,
664                                               number_advs1)
665
666        # Unregister the 2nd advertisement.
667        # After removing the 2nd advertisement, the remaining instance IDs
668        # would be [1, 3]
669        instance_id = 2
670        self.test_unregister_advertisement(advertisements1.pop(instance_id - 1),
671                                           instance_id,
672                                           advertising_disabled=False)
673
674        if not self.ext_adv_enabled():
675            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
676                                                   new_max_adv_interval_ms,
677                                                   number_advs1 - 1)
678
679        # Register two more advertisements.
680        # The instance IDs to register would be [2, 4]
681        self.register_advertisements(advertisements2, new_min_adv_interval_ms,
682                                     new_max_adv_interval_ms,
683                                     instance_ids=[2, 4])
684
685        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
686                                               new_max_adv_interval_ms,
687                                               number_advs1 + number_advs2 - 1)
688
689        # Unregister all advertisements.
690        # The instance_ids of advertisements1 is [1, 3].
691        # The instance_ids of advertisements2 is [2, 4].
692        self.unregister_advertisements(advertisements1 + advertisements2,
693                                       instance_ids=[1, 3, 2, 4])
694
695
696    @test_case_log
697    def test_case_SI200_RA5_CD_FRA1_CD_UA5(self):
698        """Test Case: SI(200) - RA(5) - CD - FRA(1) - CD - UA(5)"""
699        new_min_adv_interval_ms = 200
700        new_max_adv_interval_ms = 200
701        advertisements = self.five_advertisements
702        extra_advertisement = self.sixth_advertisement
703        number_advs = len(advertisements)
704
705        self.test_reset_advertising()
706
707        self.register_advertisements(advertisements, new_min_adv_interval_ms,
708                                     new_max_adv_interval_ms)
709
710        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
711                                               new_max_adv_interval_ms,
712                                               number_advs)
713
714        self.test_fail_to_register_advertisement(extra_advertisement,
715                                                 new_min_adv_interval_ms,
716                                                 new_max_adv_interval_ms)
717
718        # If the registration fails and extended advertising is available,
719        # there will be no events in btmon. Therefore, we only run this part of
720        # the test if extended advertising is not available, indicating that
721        # software advertisement rotation is being used.
722        if not self.ext_adv_enabled():
723            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
724                                                   new_max_adv_interval_ms,
725                                                   number_advs)
726
727        self.unregister_advertisements(advertisements)
728
729
730    @test_case_log
731    def test_case_SI200_RA3_CD_PC_CD_UA3(self):
732        """Test Case: SI(200) - RA(3) - CD - PC - CD - UA(3)"""
733        new_min_adv_interval_ms = 200
734        new_max_adv_interval_ms = 200
735        advertisements = self.three_advertisements
736
737        self.test_reset_advertising()
738
739        self.register_advertisements(advertisements, new_min_adv_interval_ms,
740                                     new_max_adv_interval_ms)
741
742        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
743                                               new_max_adv_interval_ms,
744                                               len(advertisements))
745
746        # Turn off and then turn on the adapter.
747        self.test_power_off_adapter()
748        time.sleep(1)
749        self.test_power_on_adapter()
750
751        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
752                                               new_max_adv_interval_ms,
753                                               len(advertisements))
754
755        self.unregister_advertisements(advertisements)
756
757
758    @test_case_log
759    def test_case_SI200_RA3_CD_SR_CD_UA3(self):
760        """Test Case: SI(200) - RA(3) - CD - SR - CD - UA(3)"""
761        new_min_adv_interval_ms = 200
762        new_max_adv_interval_ms = 200
763        advertisements = self.three_advertisements
764
765        self.test_reset_advertising()
766
767        self.register_advertisements(advertisements, new_min_adv_interval_ms,
768                                     new_max_adv_interval_ms)
769
770        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
771                                               new_max_adv_interval_ms,
772                                               len(advertisements))
773
774        # Suspend for a while and resume.
775        self.suspend_resume()
776
777        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
778                                               new_max_adv_interval_ms,
779                                               len(advertisements))
780
781        self.unregister_advertisements(advertisements)
782
783
784    @test_case_log
785    def test_case_RA3_CD_SI200_CD_UA3(self):
786        """Test Case: RA(3) - CD - SI(200) - CD - UA(3)"""
787        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
788        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
789        new_min_adv_interval_ms = 200
790        new_max_adv_interval_ms = 200
791        advertisements = self.three_advertisements
792        number_advs = len(advertisements)
793
794        self.test_reset_advertising()
795
796        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
797                                     orig_max_adv_interval_ms)
798
799        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
800                                               orig_max_adv_interval_ms,
801                                               number_advs)
802
803        self.unregister_advertisements(advertisements)
804        self.register_advertisements(advertisements, new_min_adv_interval_ms,
805                                     new_max_adv_interval_ms)
806
807        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
808                                               new_max_adv_interval_ms,
809                                               number_advs)
810
811        self.unregister_advertisements(advertisements)
812
813
814    @test_case_log
815    def test_case_RA3_CD_SI200_CD_RS(self):
816        """Test Case: RA(3) - CD - SI(200) - CD - RS"""
817        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
818        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
819        new_min_adv_interval_ms = 200
820        new_max_adv_interval_ms = 200
821        advertisements = self.three_advertisements
822        number_advs = len(advertisements)
823
824        self.test_reset_advertising()
825
826        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
827                                     orig_max_adv_interval_ms)
828
829        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
830                                               orig_max_adv_interval_ms,
831                                               number_advs)
832
833        self.unregister_advertisements(advertisements)
834        self.register_advertisements(advertisements, new_min_adv_interval_ms,
835                                     new_max_adv_interval_ms)
836
837        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
838                                               new_max_adv_interval_ms,
839                                               number_advs)
840
841        self.test_reset_advertising(self.get_instance_ids(advertisements))
842
843
844
845    @test_case_log
846    def test_case_RA3_CD_SI200_CD_UA1_CD_RS(self):
847        """Test Case: RA(3) - CD - SI(200) - CD - UA(1) - CD - RS"""
848        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
849        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
850        new_min_adv_interval_ms = 200
851        new_max_adv_interval_ms = 200
852        advertisements = self.three_advertisements
853        number_advs = len(advertisements)
854
855        self.test_reset_advertising()
856
857        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
858                                     orig_max_adv_interval_ms)
859
860        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
861                                               orig_max_adv_interval_ms,
862                                               number_advs)
863
864        self.unregister_advertisements(advertisements)
865        self.register_advertisements(advertisements, new_min_adv_interval_ms,
866                                     new_max_adv_interval_ms)
867
868        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
869                                               new_max_adv_interval_ms,
870                                               number_advs)
871
872        # Unregister the 2nd advertisement.
873        instance_id = 2
874        self.test_unregister_advertisement(advertisements[instance_id - 1],
875                                           instance_id,
876                                           advertising_disabled=False)
877
878        if not self.ext_adv_enabled():
879            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
880                                                   new_max_adv_interval_ms,
881                                                   number_advs - 1)
882
883        # Test if advertising is reset correctly.Only instances [1, 3] are left.
884        self.test_reset_advertising([1, 3])
885
886
887    @test_case_log
888    def test_case_RA3_CD_SI200_CD_SI2000_CD_UA3(self):
889        """Test Case: RA(3) - CD - SI(200) - CD - SI(2000) - CD - UA(3)"""
890        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
891        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
892        new_small_min_adv_interval_ms = 200
893        new_small_max_adv_interval_ms = 200
894        new_large_min_adv_interval_ms = 2000
895        new_large_max_adv_interval_ms = 2000
896        advertisements = self.three_advertisements
897        number_advs = len(advertisements)
898
899        self.test_reset_advertising()
900
901        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
902                                     orig_max_adv_interval_ms)
903
904        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
905                                               orig_max_adv_interval_ms,
906                                               number_advs)
907
908        self.unregister_advertisements(advertisements)
909        self.register_advertisements(advertisements,
910                                     new_small_min_adv_interval_ms,
911                                     new_small_max_adv_interval_ms)
912
913        self.test_check_duration_and_intervals(new_small_min_adv_interval_ms,
914                                               new_small_max_adv_interval_ms,
915                                               number_advs)
916
917        self.unregister_advertisements(advertisements)
918        self.register_advertisements(advertisements,
919                                     new_large_min_adv_interval_ms,
920                                     new_large_max_adv_interval_ms)
921
922        self.test_check_duration_and_intervals(new_large_min_adv_interval_ms,
923                                               new_large_max_adv_interval_ms,
924                                               number_advs)
925
926        self.unregister_advertisements(advertisements)
927
928
929    @test_case_log
930    def test_case_RA5_CD_SI200_CD_FRA1_CD_UA5(self):
931        """Test Case: RA(5) - CD - SI(200) - CD - FRA(1) - CD - UA(5)"""
932        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
933        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
934        new_min_adv_interval_ms = 200
935        new_max_adv_interval_ms = 200
936        advertisements = self.five_advertisements
937        extra_advertisement = self.sixth_advertisement
938        number_advs = len(advertisements)
939
940        self.test_reset_advertising()
941
942        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
943                                     orig_max_adv_interval_ms)
944
945        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
946                                               orig_max_adv_interval_ms,
947                                               number_advs)
948
949        self.unregister_advertisements(advertisements)
950        self.register_advertisements(advertisements, new_min_adv_interval_ms,
951                                     new_max_adv_interval_ms)
952
953        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
954                                               new_max_adv_interval_ms,
955                                               number_advs)
956
957        self.test_fail_to_register_advertisement(extra_advertisement,
958                                                 new_min_adv_interval_ms,
959                                                 new_max_adv_interval_ms)
960
961        # If the registration fails and extended advertising is available,
962        # there will be no events in btmon. Therefore, we only run this part of
963        # the test if extended advertising is not available, indicating that
964        # software advertisement rotation is being used.
965        if not self.ext_adv_enabled():
966            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
967                                                   new_max_adv_interval_ms,
968                                                   number_advs)
969
970        self.unregister_advertisements(advertisements)
971
972
973    @test_case_log
974    def test_case_RA3_CD_SI200_CD_FSI10_CD_FSI20000_CD_UA3(self):
975        """Test Case: RA(3) - CD - SI(200) - CD - FSI(10) - CD - FSI(20000) - CD
976        - UA(3)
977        """
978        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
979        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
980        new_min_adv_interval_ms = 200
981        new_max_adv_interval_ms = 200
982        invalid_small_min_adv_interval_ms = 10
983        invalid_small_max_adv_interval_ms = 10
984        invalid_large_min_adv_interval_ms = 20000
985        invalid_large_max_adv_interval_ms = 20000
986        advertisements = self.three_advertisements
987        number_advs = len(advertisements)
988
989        self.test_reset_advertising()
990
991        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
992                                     orig_max_adv_interval_ms)
993
994        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
995                                               orig_max_adv_interval_ms,
996                                               number_advs)
997
998        self.unregister_advertisements(advertisements)
999        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1000                                     new_max_adv_interval_ms)
1001
1002        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1003                                               new_max_adv_interval_ms,
1004                                               number_advs)
1005
1006        # Fails to set intervals that are too small. Intervals remain the same.
1007        self.test_fail_to_set_advertising_intervals(
1008                invalid_small_min_adv_interval_ms,
1009                invalid_small_max_adv_interval_ms,
1010                new_min_adv_interval_ms, new_max_adv_interval_ms)
1011
1012        if not self.ext_adv_enabled():
1013            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1014                                                   new_max_adv_interval_ms,
1015                                                   number_advs)
1016
1017        # Fails to set intervals that are too large. Intervals remain the same.
1018        self.test_fail_to_set_advertising_intervals(
1019                invalid_large_min_adv_interval_ms,
1020                invalid_large_max_adv_interval_ms,
1021                new_min_adv_interval_ms, new_max_adv_interval_ms)
1022
1023        if not self.ext_adv_enabled():
1024            self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1025                                                   new_max_adv_interval_ms,
1026                                                   number_advs)
1027
1028        # Unregister all advertisements.
1029        self.unregister_advertisements(advertisements)
1030
1031
1032    @test_case_log
1033    def test_case_RA3_CD_SI200_CD_PC_CD_UA3(self):
1034        """Test Case: RA(3) - CD - SI(200) - CD - PC - CD - UA(3)"""
1035        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1036        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1037        new_min_adv_interval_ms = 200
1038        new_max_adv_interval_ms = 200
1039        advertisements = self.three_advertisements
1040        number_advs = len(advertisements)
1041
1042        self.test_reset_advertising()
1043
1044        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1045                                     orig_max_adv_interval_ms)
1046
1047        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1048                                               orig_max_adv_interval_ms,
1049                                               number_advs)
1050
1051        self.unregister_advertisements(advertisements)
1052        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1053                                     new_max_adv_interval_ms)
1054
1055        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1056                                               new_max_adv_interval_ms,
1057                                               number_advs)
1058
1059        # Turn off and then turn on the adapter.
1060        self.test_power_off_adapter()
1061        time.sleep(1)
1062        self.test_power_on_adapter()
1063
1064        # Check if the advertising durations remain the same after resume.
1065        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1066                                               new_max_adv_interval_ms,
1067                                               number_advs)
1068
1069        # Unregister all advertisements.
1070        self.unregister_advertisements(advertisements)
1071
1072
1073    @test_case_log
1074    def test_case_RA3_CD_SI200_CD_SR_CD_UA3(self):
1075        """Test Case: RA(3) - CD - SI(200) - CD - SR - CD - UA(3)"""
1076        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1077        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1078        new_min_adv_interval_ms = 200
1079        new_max_adv_interval_ms = 200
1080        advertisements = self.three_advertisements
1081        number_advs = len(advertisements)
1082
1083        self.test_reset_advertising()
1084
1085        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1086                                     orig_max_adv_interval_ms)
1087
1088        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1089                                               orig_max_adv_interval_ms,
1090                                               number_advs)
1091
1092        self.unregister_advertisements(advertisements)
1093        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1094                                     new_max_adv_interval_ms)
1095
1096        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1097                                               new_max_adv_interval_ms,
1098                                               number_advs)
1099
1100        # Suspend for a while and resume.
1101        self.suspend_resume()
1102
1103        # Check if the advertising durations remain the same after resume.
1104        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1105                                               new_max_adv_interval_ms,
1106                                               number_advs)
1107
1108        # Unregister all advertisements.
1109        self.unregister_advertisements(advertisements)
1110
1111    # SINGLE TEST CASES
1112    @test_case_log
1113    def test_case_SI200_RA1_CD_UA1(self):
1114        """Test Case: SI(200) - RA(1) - CD - UA(1)"""
1115        new_min_adv_interval_ms = 200
1116        new_max_adv_interval_ms = 200
1117        advertisements = [self.sixth_advertisement]
1118
1119        self.test_reset_advertising()
1120
1121        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1122                                     new_max_adv_interval_ms)
1123
1124        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1125                                               new_max_adv_interval_ms,
1126                                               len(advertisements))
1127
1128        self.unregister_advertisements(advertisements)
1129
1130
1131    @test_case_log
1132    def test_case_SI200_RA1_CD_RS(self):
1133        """Test Case: SI(200) - RA(1) - CD - RS"""
1134        new_min_adv_interval_ms = 200
1135        new_max_adv_interval_ms = 200
1136        advertisements = [self.first_advertisement]
1137
1138        self.test_reset_advertising()
1139
1140        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1141                                     new_max_adv_interval_ms)
1142
1143        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1144                                               new_max_adv_interval_ms,
1145                                               len(advertisements))
1146
1147        self.test_reset_advertising()
1148
1149
1150    @test_case_log
1151    def test_case_SI200_RA1_CD_SR_CD_UA1(self):
1152        """Test Case: SI(200) - RA(1) - CD - SR - CD - UA(1)"""
1153        new_min_adv_interval_ms = 200
1154        new_max_adv_interval_ms = 200
1155        advertisements = [self.sixth_advertisement]
1156
1157        self.test_reset_advertising()
1158
1159        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1160                                     new_max_adv_interval_ms)
1161
1162        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1163                                               new_max_adv_interval_ms,
1164                                               len(advertisements))
1165
1166        self.suspend_resume()
1167
1168        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1169                                               new_max_adv_interval_ms,
1170                                               len(advertisements))
1171
1172        self.unregister_advertisements(advertisements)
1173
1174
1175    @test_case_log
1176    def test_case_RA1_CD_SI200_CD_UA1(self):
1177        """Test Case: RA(1) - CD - SI(200) - CD - UA(1)"""
1178        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1179        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1180        new_min_adv_interval_ms = 200
1181        new_max_adv_interval_ms = 200
1182        advertisements = [self.first_advertisement]
1183
1184        self.test_reset_advertising()
1185
1186        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1187                                     orig_max_adv_interval_ms)
1188
1189        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1190                                               orig_max_adv_interval_ms,
1191                                               len(advertisements))
1192
1193        self.unregister_advertisements(advertisements)
1194        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1195                                     new_max_adv_interval_ms)
1196
1197        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1198                                               new_max_adv_interval_ms,
1199                                               len(advertisements))
1200
1201        self.unregister_advertisements(advertisements)
1202
1203
1204    @test_case_log
1205    def test_case_RA1_CD_SI200_CD_RS(self):
1206        """Test Case: RA(1) - CD - SI(200) - CD - RS"""
1207        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1208        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1209        new_min_adv_interval_ms = 200
1210        new_max_adv_interval_ms = 200
1211        advertisements = [self.sixth_advertisement]
1212        self.test_reset_advertising()
1213
1214        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1215                                     orig_max_adv_interval_ms)
1216
1217        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1218                                               orig_max_adv_interval_ms,
1219                                               len(advertisements))
1220
1221        self.unregister_advertisements(advertisements)
1222        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1223                                     new_max_adv_interval_ms)
1224
1225        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1226                                               new_max_adv_interval_ms,
1227                                               len(advertisements))
1228        self.test_reset_advertising()
1229
1230
1231    @test_case_log
1232    def test_case_RA1_CD_SI200_CD_FSI10_UA1_RA1_CD_UA1(self):
1233        """Test Case:  RA(1) - CD - SI(200) - CD - FSI(10) - UA(1)
1234         - RA(1) - CD - UA(1)"""
1235        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1236        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1237        new_min_adv_interval_ms = 200
1238        new_max_adv_interval_ms = 200
1239        invalid_small_min_adv_interval_ms = 10
1240        invalid_small_max_adv_interval_ms = 10
1241        advertisements = [self.three_advertisements[1]]
1242        new_advertisement = [self.three_advertisements[2]]
1243
1244        self.test_reset_advertising()
1245
1246        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1247                                     orig_max_adv_interval_ms)
1248
1249        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1250                                               orig_max_adv_interval_ms,
1251                                               len(advertisements))
1252
1253        self.unregister_advertisements(advertisements)
1254        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1255                                     new_max_adv_interval_ms)
1256
1257        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1258                                               new_max_adv_interval_ms,
1259                                               len(advertisements))
1260
1261        # Fails to set intervals that are too small. Intervals remain the same.
1262        self.test_fail_to_set_advertising_intervals(
1263                invalid_small_min_adv_interval_ms,
1264                invalid_small_max_adv_interval_ms,
1265                new_min_adv_interval_ms, new_max_adv_interval_ms)
1266
1267        self.unregister_advertisements(advertisements)
1268
1269        # Register a new advertisement in order to avoid kernel caching.
1270        self.register_advertisements(new_advertisement, new_min_adv_interval_ms,
1271                                     new_max_adv_interval_ms)
1272
1273        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1274                                               new_max_adv_interval_ms,
1275                                               len(advertisements))
1276
1277        self.unregister_advertisements(new_advertisement)
1278
1279
1280    @test_case_log
1281    def test_case_RA1_CD_SI200_CD_FSI20000_UA1_RA1_CD_UA1(self):
1282        """Test Case:  RA(1) - CD - SI(200) - CD - FSI(20000) - UA(1)
1283         - RA(1) - CD - UA(1)"""
1284        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1285        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1286        new_min_adv_interval_ms = 200
1287        new_max_adv_interval_ms = 200
1288        invalid_large_min_adv_interval_ms = 20000
1289        invalid_large_max_adv_interval_ms = 20000
1290        advertisements = [self.three_advertisements[1]]
1291        new_advertisement = [self.three_advertisements[2]]
1292
1293        self.test_reset_advertising()
1294
1295        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1296                                     orig_max_adv_interval_ms)
1297
1298        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1299                                               orig_max_adv_interval_ms,
1300                                               len(advertisements))
1301
1302        self.unregister_advertisements(advertisements)
1303        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1304                                     new_max_adv_interval_ms)
1305
1306        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1307                                               new_max_adv_interval_ms,
1308                                               len(advertisements))
1309        # Fails to set intervals that are too large. Intervals remain the same.
1310        self.test_fail_to_set_advertising_intervals(
1311                invalid_large_min_adv_interval_ms,
1312                invalid_large_max_adv_interval_ms,
1313                new_min_adv_interval_ms, new_max_adv_interval_ms)
1314
1315        self.unregister_advertisements(advertisements)
1316
1317        # Register a new advertisement in order to avoid kernel caching.
1318        self.register_advertisements(new_advertisement, new_min_adv_interval_ms,
1319                                     new_max_adv_interval_ms)
1320
1321        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1322                                               new_max_adv_interval_ms,
1323                                               len(advertisements))
1324
1325        self.unregister_advertisements(new_advertisement)
1326
1327
1328    @test_case_log
1329    def test_case_RA1_CD_SI200_CD_PC_CD_UA1(self):
1330        """Test Case: RA(1) - CD - SI(200) - CD - PC - CD - UA(1)"""
1331        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1332        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1333        new_min_adv_interval_ms = 200
1334        new_max_adv_interval_ms = 200
1335        advertisements = [self.sixth_advertisement]
1336        self.test_reset_advertising()
1337
1338        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1339                                     orig_max_adv_interval_ms)
1340
1341        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1342                                               orig_max_adv_interval_ms,
1343                                               len(advertisements))
1344
1345        self.unregister_advertisements(advertisements)
1346        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1347                                     new_max_adv_interval_ms)
1348
1349        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1350                                               new_max_adv_interval_ms,
1351                                               len(advertisements))
1352
1353        # Turn off and then turn on the adapter.
1354        self.test_power_off_adapter()
1355        time.sleep(1)
1356        self.test_power_on_adapter()
1357
1358        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1359                                               new_max_adv_interval_ms,
1360                                               len(advertisements))
1361
1362        self.unregister_advertisements(advertisements)
1363
1364
1365    @test_case_log
1366    def test_case_RA1_CD_SI200_CD_SR_CD_UA1(self):
1367        """Test Case: RA(1) - CD - SI(200) - CD - SR - CD - UA(1)"""
1368        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1369        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1370        new_min_adv_interval_ms = 200
1371        new_max_adv_interval_ms = 200
1372        advertisements = [self.first_advertisement]
1373        self.test_reset_advertising()
1374
1375        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1376                                     orig_max_adv_interval_ms)
1377
1378        self.test_check_duration_and_intervals(orig_min_adv_interval_ms,
1379                                               orig_max_adv_interval_ms,
1380                                               len(advertisements))
1381
1382        self.unregister_advertisements(advertisements)
1383        self.register_advertisements(advertisements, new_min_adv_interval_ms,
1384                                     new_max_adv_interval_ms)
1385
1386        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1387                                               new_max_adv_interval_ms,
1388                                               len(advertisements))
1389
1390        self.suspend_resume()
1391
1392        self.test_check_duration_and_intervals(new_min_adv_interval_ms,
1393                                               new_max_adv_interval_ms,
1394                                               len(advertisements))
1395
1396        self.unregister_advertisements(advertisements)
1397
1398    @test_case_log
1399    def test_case_nearby_mediums_fast(self):
1400        """Verify minimal test case for nearby sharing"""
1401        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1402        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1403
1404        # We set a specific advertisement with fields required by Nearby
1405        # sharing service
1406        advertisements = [advertisements_data.NEARBY_MEDIUMS_FAST_ADV]
1407
1408        self.test_reset_advertising()
1409
1410        # Nearby share requires general discoverable advertising flag be set.
1411        # Bluez sets this flag based on the adapter's Discoverable property,
1412        # so we apply this setting here
1413        self.bluetooth_facade.set_discoverable(True)
1414
1415        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1416                                     orig_max_adv_interval_ms)
1417
1418        # Ensure that our discoverable flag is advertised
1419        self.test_advertising_flags(['Advertise as Discoverable'])
1420
1421    @test_case_log
1422    def test_case_adv_before_scan(self):
1423        """Verify we can scan after advertising starts
1424
1425        We found that when extended advertising is available, any Set Adv
1426        Disable HCI command would mark the hdev as not advertising, even if
1427        other instances were active at the time. Later attempts to start
1428        discovery would fail, because kernel tries to update the random address
1429        without knowing to pause the advertisements. This test case replicates
1430        this failure condition to validate the fix.
1431        """
1432        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1433        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1434        advertisements = self.three_advertisements
1435
1436        self.test_reset_advertising()
1437
1438        # Register several advertisements
1439        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1440                                     orig_max_adv_interval_ms)
1441
1442        # Unregister one active advertisement.
1443        instance_id = 2
1444        self.test_unregister_advertisement(advertisements[instance_id - 1],
1445                                           instance_id,
1446                                           advertising_disabled=False)
1447
1448        self.test_start_discovery()
1449
1450        # Test if advertising is reset correctly.Only instances [1, 3] are left.
1451        self.test_reset_advertising([1, 3])
1452
1453    @test_case_log
1454    def test_case_broadcast(self):
1455        """Verify minimal test case for broadcasted advertising"""
1456        orig_min_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1457        orig_max_adv_interval_ms = self.DEFAULT_MIN_ADVERTISEMENT_INTERVAL_MS
1458
1459        # We set a specific advertisement that uses the 'broadcast' mode
1460        advertisements = [advertisements_data.NEARBY_BROADCAST_ADV]
1461
1462        self.test_reset_advertising()
1463
1464        # Verify that registration is successful, and that all configured
1465        # properties are sent to the controller.
1466        self.register_advertisements(advertisements, orig_min_adv_interval_ms,
1467                                     orig_max_adv_interval_ms)
1468
1469    def run_le_advertising_test(self, host, advertisements, test_type, \
1470                                num_iterations=1):
1471        """Running Bluetooth adapter LE advertising autotest.
1472
1473        @param host: device under test host.
1474        @param advertisements: a list of advertisement instances.
1475        @param test_type: indicating one of three test types: multi-advertising,
1476                          single-advertising, reboot (stress only), or
1477                          suspend_resume (stress only).
1478
1479        @raises TestNAError: if DUT has low kernel version (<=3.8.11)
1480
1481        """
1482        self.host = host
1483        self.kernel_version = self.host.get_kernel_version()
1484        self.check_kernel_version()
1485
1486        self.advertisements = advertisements
1487        self.first_advertisement = advertisements[0]
1488        self.two_advertisements = advertisements[3:5]
1489        self.three_advertisements = advertisements[0:3]
1490        self.five_advertisements = advertisements[0:5]
1491        self.sixth_advertisement = advertisements[5]
1492
1493        self.bluetooth_le_facade = self.bluetooth_facade
1494
1495        # Reset the adapter to forget previous stored data and turn it on.
1496        self.test_reset_on_adapter()
1497
1498        if test_type == 'multi_advertising':
1499            # Run all test cases for multiple advertisements.
1500            self.test_case_SI200_RA3_CD_UA3()
1501            self.test_case_SI200_RA3_CD_RA1_CD_UA1_CD_UA3()
1502            self.test_case_SI200_RA3_CD_RS()
1503            self.test_case_SI200_RA3_CD_UA1_CD_RS()
1504            self.test_case_SI200_RA3_CD_UA1_CD_RA2_CD_UA4()
1505            # TODO (b/169603469) this test will fail on platforms supporting
1506            # >5 advertising slots due to new advertising feature, so disable
1507            # until test can be refactored.
1508            # self.test_case_SI200_RA5_CD_FRA1_CD_UA5()
1509            self.test_case_RA3_CD_SI200_CD_UA3()
1510            self.test_case_RA3_CD_SI200_CD_RS()
1511            self.test_case_RA3_CD_SI200_CD_UA1_CD_RS()
1512            self.test_case_RA3_CD_SI200_CD_SI2000_CD_UA3()
1513            # TODO (b/169603469) this test will fail on platforms supporting
1514            # >5 advertising slots due to new advertising feature, so disable
1515            # until test can be refactored.
1516            # self.test_case_RA5_CD_SI200_CD_FRA1_CD_UA5()
1517            self.test_case_RA3_CD_SI200_CD_FSI10_CD_FSI20000_CD_UA3()
1518            self.test_case_SI200_RA3_CD_PC_CD_UA3()
1519            self.test_case_RA3_CD_SI200_CD_PC_CD_UA3()
1520
1521        elif test_type == 'single_advertising':
1522            # Run all test cases for single advertisement.
1523            # Note: it is required to change the advertisement instance
1524            #       so that the advertisement data could be monitored by btmon.
1525            #       Otherwise, the advertisement data would be just cached and
1526            #       reused such that the data would not be visible in btmon.
1527            self.test_case_SI200_RA1_CD_UA1()
1528            self.test_case_SI200_RA1_CD_RS()
1529            self.test_case_RA1_CD_SI200_CD_UA1()
1530            self.test_case_RA1_CD_SI200_CD_RS()
1531            self.test_case_RA1_CD_SI200_CD_FSI10_UA1_RA1_CD_UA1()
1532            self.test_case_RA1_CD_SI200_CD_FSI20000_UA1_RA1_CD_UA1()
1533            self.test_case_RA1_CD_SI200_CD_PC_CD_UA1()
1534
1535        elif test_type == 'suspend_resume':
1536            # Run all test cases for suspend resume stress testing.
1537            for i in range(num_iterations):
1538                logging.info('Starting suspend resume loop #%d', i+1)
1539                self.test_case_SI200_RA3_CD_SR_CD_UA3()
1540                self.test_case_RA3_CD_SI200_CD_SR_CD_UA3()
1541                self.test_case_SI200_RA1_CD_SR_CD_UA1()
1542                self.test_case_RA1_CD_SI200_CD_SR_CD_UA1()
1543
1544        elif test_type == 'reboot':
1545            # Run all test cases for reboot stress testing.
1546            for i in range(num_iterations):
1547                logging.info('Starting reboot loop #%d', i+1)
1548                self.test_case_SI200_RA3_CD_PC_CD_UA3()
1549                self.test_case_RA3_CD_SI200_CD_PC_CD_UA3()
1550                self.test_case_RA1_CD_SI200_CD_PC_CD_UA1()
1551
1552        elif test_type == 'nearby':
1553            self.test_case_nearby_mediums_fast()
1554            self.test_case_adv_before_scan()
1555
1556        elif test_type == 'broadcast':
1557            self.test_case_broadcast()
1558