xref: /aosp_15_r20/external/autotest/server/cros/bluetooth/bluetooth_test_utils.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright 2019 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"""Provides utilities to support bluetooth adapter tests"""
6
7from __future__ import absolute_import
8
9import logging
10import re
11import uuid
12
13import common
14from autotest_lib.client.bin.input.linux_input import EV_KEY
15from autotest_lib.server.cros.bluetooth.debug_linux_keymap import (
16        linux_input_keymap)
17from ast import literal_eval as make_tuple
18
19
20def reconstruct_string(events):
21    """ Tries to reconstruct a string from linux input in a simple way
22
23    @param events: list of event objects received over the BT channel
24
25    @returns: reconstructed string
26    """
27    recon = []
28
29    for ev in events:
30        # If it's a key pressed event
31        if ev.type == EV_KEY and ev.value == 1:
32            recon.append(linux_input_keymap.get(ev.code, "_"))
33
34    return "".join(recon)
35
36
37def parse_trace_file(filename):
38    """ Reads contents of trace file
39
40    @param filename: location of trace file on disk
41
42    @returns: structure containing contents of filename
43    """
44
45    contents = []
46
47    try:
48        with open(filename, 'r') as mf:
49            for line in mf:
50                # Reconstruct tuple and add to trace
51                contents.append(make_tuple(line))
52    except EnvironmentError:
53        logging.error('Unable to open file %s', filename)
54        return None
55
56    return contents
57
58
59class Bluetooth_UUID(uuid.UUID):
60    """A class to manipulate Bluetooth UUIDs."""
61
62    BLUETOOTH_BASE_UUID_FORMAT = '%s-0000-1000-8000-00805F9B34FB'
63
64    def __init__(self, hex_str):
65        super(Bluetooth_UUID, self).__init__(hex_str)
66
67
68    @classmethod
69    def create_valid_uuid(cls, hex_str):
70        """Create valid long UUIDs based on Bluetooth short UUIDs.
71
72        @param hex_str: the hex string that represents a short or long UUID.
73
74        @returns: the UUID object if successful; or None otherwise.
75        """
76        h = re.sub('^0x', '', hex_str).replace('-', '')
77
78        # The Bluetooth spec only allowed short UUIDs in 16 bits or 32 bits.
79        # The long UUID takes 128 bits.
80        # Reference:
81        # www.bluetooth.com/specifications/assigned-numbers/service-discovery
82        hlen = len(h)
83        if hlen not in (4, 8, 32):
84            return None
85
86        # Convert the short UUIDs to the full UUID.
87        if hlen in (4, 8):
88            h = cls.BLUETOOTH_BASE_UUID_FORMAT % h.zfill(8)
89
90        return cls(h)
91
92
93class BluetoothPolicy(object):
94    """A helper class to keep popular bluetooth service lists.
95
96    Refer to
97    https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/
98    """
99
100    def to_allowlist(uuids):
101        """Helper function to convert a group of uuids to allowlist format
102
103        @param uuids: an iterable object of UUID string
104
105        @returns: comma-separated UUID string
106        """
107        return ','.join(list(uuids))
108
109    UUID_HID = '0x1124'
110    UUID_HOG = '0x1812'
111    UUID_DIS = '0x180a'
112    UUID_BATT = '0x180f'
113
114    UUID_A2DP = '0x110d'
115    UUID_AUDIO_SOURCE = '0x110a'
116    UUID_AUDIO_SINK = '0x110b'
117    UUID_AVRCP = '0x110e'
118    UUID_AVRCP_TARGET = '0x110c'
119    UUID_AVRCP_CONTROLLER = '0x110f'
120    UUID_GENERIC_AUDIO = '0x1203'
121    UUID_HANDSFREE = '0x111e'
122    UUID_HANDSFREE_AUDIO_GATEWAY = '0x111f'
123    UUID_HEADSET = '0x1108'
124    UUID_HEADSET_AUDIO_GATEWAY = '0x1112'
125
126    UUIDSET_BLE_HID = {UUID_HOG, UUID_DIS, UUID_BATT}
127    UUIDSET_AUDIO = {UUID_A2DP, UUID_AUDIO_SINK, UUID_AUDIO_SOURCE,
128                     UUID_AVRCP, UUID_AVRCP_TARGET, UUID_AVRCP_CONTROLLER,
129                     UUID_GENERIC_AUDIO,
130                     UUID_HANDSFREE, UUID_HANDSFREE_AUDIO_GATEWAY,
131                     UUID_HEADSET, UUID_HEADSET_AUDIO_GATEWAY}
132
133    ALLOWLIST_CLASSIC_HID = UUID_HID
134    ALLOWLIST_BLE_HID = to_allowlist(UUIDSET_BLE_HID)
135    ALLOWLIST_AUDIO = to_allowlist(UUIDSET_AUDIO)
136    ALLOWLIST_BLE_HID_AUDIO = to_allowlist(UUIDSET_BLE_HID.union(UUIDSET_AUDIO))
137    ALLOWLIST_CLASSIC_BLE_HID = to_allowlist(UUIDSET_BLE_HID.union({UUID_HID}))
138