• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3# Copyright (C) 2017 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"""
17Bluetooth HID Device Test.
18"""
19
20from acts.base_test import BaseTestClass
21from acts.test_decorators import test_tracker_info
22from acts_contrib.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
23from acts_contrib.test_utils.bt.bt_test_utils import setup_multiple_devices_for_bt_test
24from acts_contrib.test_utils.bt.bt_test_utils import clear_bonded_devices
25from acts_contrib.test_utils.bt.bt_test_utils import pair_pri_to_sec
26from acts_contrib.test_utils.bt.bt_test_utils import hid_keyboard_report
27from acts_contrib.test_utils.bt.bt_test_utils import hid_device_send_key_data_report
28from acts_contrib.test_utils.bt.bt_constants import hid_connection_timeout
29from acts_contrib.test_utils.bt import bt_constants
30import time
31
32
33class HidDeviceTest(BluetoothBaseTest):
34    tests = None
35    default_timeout = 10
36
37    def setup_class(self):
38        super().setup_class()
39        self.host_ad = self.android_devices[0]
40        self.device_ad = self.android_devices[1]
41
42    def setup_test(self):
43        for a in self.android_devices:
44            if not clear_bonded_devices(a):
45                return False
46        for a in self.android_devices:
47            a.ed.clear_all_events()
48
49        i = 0
50        while not self.device_ad.droid.bluetoothHidDeviceIsReady():
51            time.sleep(1)
52            i += 1
53            self.log.info("BluetoothHidDevice NOT Ready")
54            if i == 10:
55                return False
56
57        if not self.device_ad.droid.bluetoothHidDeviceRegisterApp():
58            self.log.error("Device: registration failed")
59            return False
60
61        self.log.info("Device: registration done")
62        return True
63
64    def teardown_test(self):
65        self.log.info("Device: unregister")
66        self.device_ad.droid.bluetoothHidDeviceUnregisterApp()
67        time.sleep(2)
68        return True
69
70    @BluetoothBaseTest.bt_test_wrap
71    @test_tracker_info(uuid='047afb31-96c5-4a56-acb5-2b216037f35d')
72    def test_hid(self):
73        """Test HID Host and Device basic functionality
74
75        Test the HID Device framework app registration; test HID Host sending
76        report through HID control channel and interrupt channel.
77
78        Steps:
79        1. Bluetooth HID device registers the Bluetooth input device service.
80        2. Get the MAC address of the HID host and HID device.
81        3. Establish HID profile connection from the HID host to the HID device.
82        4. HID host sends set_report, get_report, set_protocol, send_data to
83        the HID device, and check if the HID device receives them.
84        5. HID device sends data report, report_error, reply_report commands to
85        the HID host, and check if the HID host receives them.
86
87        Expected Result:
88        HID profile connection is successfully established; all commands and
89        data reports are correctly handled.
90
91        Returns:
92          Pass if True
93          Fail if False
94
95        TAGS: Classic, HID
96        Priority: 1
97        """
98
99        test_result = True
100
101        pair_pri_to_sec(self.host_ad, self.device_ad, attempts=3)
102
103        self.log.info("Device bonded: {}".format(
104                self.device_ad.droid.bluetoothGetBondedDevices()))
105        self.log.info("Host bonded: {}".format(
106                self.host_ad.droid.bluetoothGetBondedDevices()))
107
108        host_id = self.host_ad.droid.bluetoothGetLocalAddress()
109        device_id = self.device_ad.droid.bluetoothGetLocalAddress()
110
111        self.host_ad.droid.bluetoothConnectBonded(device_id)
112
113        time.sleep(hid_connection_timeout)
114        self.log.info("Device: connected: {}".format(
115                self.device_ad.droid.bluetoothHidDeviceGetConnectedDevices()))
116
117        self.log.info("Host: set report")
118        self.host_ad.droid.bluetoothHidSetReport(
119                device_id, 1, bt_constants.hid_default_set_report_payload)
120
121        try:
122            hid_device_callback = self.device_ad.ed.pop_event(
123                    bt_constants.hid_on_set_report_event,
124                    bt_constants.hid_default_event_timeout)
125        except Empty as err:
126            self.log.error("Callback not received: {}".format(err))
127            test_result = False
128
129        self.log.info("Host: get report")
130        self.host_ad.droid.bluetoothHidGetReport(device_id, 1, 1, 1024)
131
132        try:
133            hid_device_callback = self.device_ad.ed.pop_event(
134                    bt_constants.hid_on_get_report_event,
135                    bt_constants.hid_default_event_timeout)
136        except Empty as err:
137            self.log.error("Callback not received: {}".format(err))
138            test_result = False
139
140        self.log.info("Host: set_protocol")
141        self.host_ad.droid.bluetoothHidSetProtocolMode(device_id, 1)
142
143        try:
144            hid_device_callback = self.device_ad.ed.pop_event(
145                    bt_constants.hid_on_set_protocol_event,
146                    bt_constants.hid_default_event_timeout)
147        except Empty as err:
148            self.log.error("Callback not received: {}".format(err))
149            test_result = False
150
151        self.log.info("Host: send data")
152        self.host_ad.droid.bluetoothHidSendData(device_id, "It's a report")
153
154        try:
155            hid_device_callback = self.device_ad.ed.pop_event(
156                    bt_constants.hid_on_intr_data_event,
157                    bt_constants.hid_default_event_timeout)
158        except Empty as err:
159            self.log.error("Callback not received: {}".format(err))
160            test_result = False
161
162        self.log.info("Device: send data report through interrupt channel")
163        hid_device_send_key_data_report(host_id, self.device_ad, "04")
164        hid_device_send_key_data_report(host_id, self.device_ad, "05")
165
166        self.log.info("Device: report error")
167        self.device_ad.droid.bluetoothHidDeviceReportError(host_id, 1)
168
169        self.log.info("Device: reply report")
170        self.device_ad.droid.bluetoothHidDeviceReplyReport(
171                host_id, 1, 1, hid_keyboard_report("04"))
172
173        self.log.info("Device bonded: {}".format(
174                      self.device_ad.droid.bluetoothGetBondedDevices()))
175        self.log.info("Host bonded: {}".format(
176                      self.host_ad.droid.bluetoothGetBondedDevices()))
177
178        return test_result
179
180    @BluetoothBaseTest.bt_test_wrap
181    @test_tracker_info(uuid='5ddc3eb1-2b8d-43b5-bdc4-ba577d90481d')
182    def test_hid_host_unplug(self):
183        """Test HID Host Virtual_cable_unplug
184
185        Test the HID host and HID device handle Virtual_cable_unplug correctly
186
187        Steps:
188        1. Bluetooth HID device registers the Bluetooth input device service.
189        2. Get the MAC address of the HID host and HID device.
190        3. Establish HID profile connection from the HID host to the HID device.
191        4. HID host sends virtual_cable_unplug command to the HID device.
192
193        Expected Result:
194        HID profile connection is successfully established; After the HID host
195        sends virtual_cable_unplug command to the HID device, both disconnect
196        each other, but not unpair.
197
198        Returns:
199          Pass if True
200          Fail if False
201
202        TAGS: Classic, HID
203        Priority: 2
204        """
205
206        test_result = True
207        pair_pri_to_sec(self.host_ad, self.device_ad, attempts=3)
208
209        self.log.info("Device bonded: {}".format(
210                      self.device_ad.droid.bluetoothGetBondedDevices()))
211        self.log.info("Host bonded: {}".format(
212                      self.host_ad.droid.bluetoothGetBondedDevices()))
213
214        host_id = self.host_ad.droid.bluetoothGetLocalAddress()
215        device_id = self.device_ad.droid.bluetoothGetLocalAddress()
216
217        self.host_ad.droid.bluetoothConnectBonded(device_id)
218
219        time.sleep(hid_connection_timeout)
220        self.log.info("Device connected: {}".format(
221                self.device_ad.droid.bluetoothHidDeviceGetConnectedDevices()))
222
223        self.log.info("Device: send data report through interrupt channel")
224        hid_device_send_key_data_report(host_id, self.device_ad, "04")
225        hid_device_send_key_data_report(host_id, self.device_ad, "05")
226
227        self.log.info("Host: virtual unplug")
228        self.host_ad.droid.bluetoothHidVirtualUnplug(device_id)
229
230        try:
231            hid_device_callback = self.device_ad.ed.pop_event(
232                    bt_constants.hid_on_virtual_cable_unplug_event,
233                    bt_constants.hid_default_event_timeout)
234        except Empty as err:
235            self.log.error("Callback not received: {}".format(err))
236            test_result = False
237
238        self.log.info("Device bonded: {}".format(
239                self.device_ad.droid.bluetoothGetBondedDevices()))
240        self.log.info("Host bonded: {}".format(
241                self.host_ad.droid.bluetoothGetBondedDevices()))
242
243        if self.device_ad.droid.bluetoothGetBondedDevices():
244            self.log.error("HID device didn't unbond on virtual_cable_unplug")
245            test_result = False
246
247        if self.host_ad.droid.bluetoothGetBondedDevices():
248            self.log.error("HID host didn't unbond on virtual_cable_unplug")
249            test_result = False
250
251        return test_result
252
253