1#!/usr/bin/env python3
2#
3# Copyright (C) 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# 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, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
16"""
17Basic SDP Tests.
18
19This only requires a single bluetooth_device
20and exercises adding/removing services, initialization, and
21adding search records.
22"""
23from acts import signals
24from acts.base_test import BaseTestClass
25from acts.test_utils.abstract_devices.bluetooth_device import AndroidBluetoothDevice
26from acts.test_utils.abstract_devices.bluetooth_device import FuchsiaBluetoothDevice
27from acts.test_utils.abstract_devices.bluetooth_device import create_bluetooth_device
28from acts.test_utils.bt.bt_constants import bt_attribute_values
29from acts.test_utils.bt.bt_constants import sig_uuid_constants
30
31TEST_SDP_RECORD = {
32    'service_class_uuids': ["0001"],
33    'protocol_descriptors': [
34        {
35            'protocol':
36            int(sig_uuid_constants['AVDTP'], 16),
37            'params': [
38                {
39                    'data': 0x0103  # to indicate 1.3
40                },
41                {
42                    'data': 0x0105  # to indicate 1.5
43                }
44            ]
45        },
46        {
47            'protocol': int(sig_uuid_constants['SDP'], 16),
48            'params': [{
49                'data': int(sig_uuid_constants['AVDTP'], 16),
50            }]
51        }
52    ],
53    'profile_descriptors': [{
54        'profile_id':
55        int(sig_uuid_constants['AdvancedAudioDistribution'], 16),
56        'major_version':
57        1,
58        'minor_version':
59        3,
60    }],
61    'additional_protocol_descriptors': [{
62        'protocol':
63        int(sig_uuid_constants['L2CAP'], 16),
64        'params': [{
65            'data': int(sig_uuid_constants['AVDTP'], 16),
66        }]
67    }],
68    'information': [{
69        'language': "en",
70        'name': "A2DP",
71        'description': "Advanced Audio Distribution Profile",
72        'provider': "Fuchsia"
73    }],
74    'additional_attributes':
75    None
76}
77
78
79class SdpSetupTest(BaseTestClass):
80    def setup_class(self):
81        super(SdpSetupTest, self).setup_class()
82        if 'dut' in self.user_params:
83            if self.user_params['dut'] == 'fuchsia_devices':
84                self.dut = create_bluetooth_device(self.fuchsia_devices[0])
85            elif self.user_params['dut'] == 'android_devices':
86                self.dut = create_bluetooth_device(self.android_devices[0])
87            else:
88                raise ValueError('Invalid DUT specified in config. (%s)' %
89                                 self.user_params['dut'])
90        else:
91            # Default is an fuchsia device
92            self.dut = create_bluetooth_device(self.fuchsia_devices[0])
93        self.dut.initialize_bluetooth_controller()
94
95
96    def setup_test(self):
97        self.dut.sdp_clean_up()
98
99    def cleanup_class(self):
100        self.dut.sdp_clean_up()
101
102    def test_init(self):
103        result = self.dut.sdp_init()
104        if result.get("error") is None:
105            raise signals.TestPass("Success")
106        else:
107            raise signals.TestFailure(
108                "Failed to initialize SDP with {}".format(result.get("error")))
109
110    def test_add_service(self):
111        self.dut.sdp_init()
112        result = self.dut.sdp_add_service(TEST_SDP_RECORD)
113        if result.get("error") is not None:
114            raise signals.TestFailure(
115                "Failed to add SDP service record: {}".format(
116                    result.get("error")))
117        else:
118            raise signals.TestPass("Success")
119
120    def test_malformed_service(self):
121        self.dut.sdp_init()
122        malformed_record = {'malformed_sdp_record_input': ["1101"]}
123        result = self.dut.sdp_add_service(malformed_record)
124        if result.get("error") is not None:
125            raise signals.TestPass("Successfully failed with: {}".format(
126                result.get("error")))
127        else:
128            raise signals.TestFailure(
129                "Expected failure of adding SDP record: {}".format(
130                    malformed_record))
131
132    def test_add_search(self):
133        attributes = [
134            bt_attribute_values['ATTR_PROTOCOL_DESCRIPTOR_LIST'],
135            bt_attribute_values['ATTR_SERVICE_CLASS_ID_LIST'],
136            bt_attribute_values['ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST'],
137            bt_attribute_values['ATTR_A2DP_SUPPORTED_FEATURES'],
138        ]
139
140        self.dut.sdp_init()
141        profile_id = int(sig_uuid_constants['AudioSource'], 16)
142        result = self.dut.sdp_add_search(attributes, profile_id)
143        if result.get("error") is not None:
144            raise signals.TestFailure("Failed to add SDP search: {}".format(
145                result.get("error")))
146        else:
147            raise signals.TestPass("Success")
148
149    def test_include_additional_attributes(self):
150        self.dut.sdp_init()
151        additional_attributes = [{
152            'id': 0x0201,
153            'element': {
154                'data': int(sig_uuid_constants['AVDTP'], 16)
155            }
156        }]
157
158        TEST_SDP_RECORD['additional_attributes'] = additional_attributes
159        result = self.dut.sdp_add_service(TEST_SDP_RECORD)
160        if result.get("error") is not None:
161            raise signals.TestFailure(
162                "Failed to add SDP service record: {}".format(
163                    result.get("error")))
164        else:
165            raise signals.TestPass("Success")
166
167    def test_add_multiple_services(self):
168        self.dut.sdp_init()
169        number_of_records = 10
170        for _ in range(number_of_records):
171            result = self.dut.sdp_add_service(TEST_SDP_RECORD)
172            if result.get("error") is not None:
173                raise signals.TestFailure(
174                    "Failed to add SDP service record: {}".format(
175                        result.get("error")))
176        raise signals.TestPass("Success")
177