1# Copyright (C) 2016 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14import logging
15import time
16from google import protobuf
17
18from acts import asserts
19from acts.test_utils.bt.BtMetricsBaseTest import BtMetricsBaseTest
20from acts.test_utils.bt.bt_test_utils import clear_bonded_devices
21from acts.test_utils.bt.bt_test_utils import pair_pri_to_sec
22from acts.test_utils.bt.bt_test_utils import reset_bluetooth
23from acts.utils import get_current_epoch_time, sync_device_time
24
25
26class BtMetricsTest(BtMetricsBaseTest):
27    def __init__(self, controllers):
28        BtMetricsBaseTest.__init__(self, controllers)
29        self.iterations = 1
30
31    def setup_class(self):
32        return super(BtMetricsTest, self).setup_class()
33
34    def setup_test(self):
35        # Reset bluetooth
36        reset_bluetooth(self.android_devices)
37        for ad in self.android_devices:
38            if not clear_bonded_devices(ad):
39                logging.error("Failed to unbound device")
40                return False
41            # Sync device time for timestamp comparison
42            sync_device_time(ad)
43        return super(BtMetricsTest, self).setup_test()
44
45    def test_pairing_metric(self):
46        """Test if a pairing event generates the correct metric entry
47
48        This test tries to pair two Bluetooth devices and dumps metrics after
49        pairing. A correctly implemented stack should record 8 pairing events.
50
51        Steps:
52        1. Start pairing between two Bluetooth devices
53        2. After pairing is done, dump and parse the metrics
54        3. Compare the number of pairing events and the time stamp of the
55        pairing event
56
57        Expected Result:
58        No errors, 8 pairing events should be generated
59        Returns:
60          Pass if True
61          Fail if False
62
63        TAGS: Classic
64        Priority: 1
65        """
66        time_bonds = []
67        for n in range(self.iterations):
68            start_time = get_current_epoch_time()
69            self.log.info("Pair bluetooth iteration {}.".format(n + 1))
70            if (not pair_pri_to_sec(
71                    self.android_devices[0],
72                    self.android_devices[1],
73                    attempts=1,
74                    auto_confirm=False)):
75                self.log.error("Failed to bond devices.")
76                return False
77            end_time = get_current_epoch_time()
78            time_bonds.append((start_time, end_time))
79            # A device bond will trigger a number of system routines that need
80            # to settle before unbond
81            time.sleep(2)
82            for ad in self.android_devices:
83                if not clear_bonded_devices(ad):
84                    return False
85                # Necessary sleep time for entries to update unbonded state
86                time.sleep(2)
87                bonded_devices = ad.droid.bluetoothGetBondedDevices()
88                if len(bonded_devices) > 0:
89                    self.log.error("Failed to unbond devices: {}".format(
90                        bonded_devices))
91                    return False
92        end_time = get_current_epoch_time()
93        bluetooth_logs, bluetooth_logs_ascii = \
94            self.collect_bluetooth_manager_metrics_logs(
95                [self.android_devices[0]])
96        bluetooth_log = bluetooth_logs[0]
97        bluetooth_log_ascii = bluetooth_logs_ascii[0]
98        asserts.assert_equal(
99            len(bluetooth_log.pair_event), 8, extras=bluetooth_log_ascii)
100        for pair_event in bluetooth_log.pair_event:
101            t = pair_event.event_time_millis
102            asserts.assert_true(start_time <= t <= end_time,
103                                "Event time %d not within limit [%d, %d]" %
104                                (t, start_time, end_time))
105            device_info = pair_event.device_paired_with
106            asserts.assert_true(device_info, "Device info is none")
107            asserts.assert_equal(device_info.device_type, self.android_devices[
108                0].bluetooth_proto_module.DeviceInfo.DEVICE_TYPE_BREDR,
109                                 "Device type does not match")
110
111    def test_bluetooth_metrics_parsing(self):
112        """Test if metrics could be dumped and parsed
113
114        This test simply dumps Bluetooth metrics and print out the ASCII
115        representation
116
117        Steps:
118        1. For the first Android device, dump metrics
119        2. Parse and print metrics in INFO log using ASCII format
120
121        Expected Result:
122        No errors, metrics should be printed to INFO log
123
124        Returns:
125          Pass if True
126          Fail if False
127
128        TAGS: Classic
129        Priority: 1
130        """
131        bluetooth_logs, bluetooth_logs_ascii = \
132            self.collect_bluetooth_manager_metrics_logs(
133                [self.android_devices[0]])
134        bluetooth_log = bluetooth_logs[0]
135        self.log.info(protobuf.text_format.MessageToString(bluetooth_log))
136        return True
137