Home | History | Annotate | Download | only in pts
      1 #/usr/bin/env python3.4
      2 #
      3 # Copyright (C) 2016 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 """
     17 Ble libraries
     18 """
     19 
     20 from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseMode
     21 from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseTxPower
     22 from acts.test_utils.bt.BleEnum import ScanSettingsScanMode
     23 from acts.test_utils.bt.bt_test_utils import TIMEOUT_SMALL
     24 from acts.test_utils.bt.bt_test_utils import adv_fail
     25 from acts.test_utils.bt.bt_test_utils import adv_succ
     26 from acts.test_utils.bt.bt_test_utils import advertising_set_on_own_address_read
     27 from acts.test_utils.bt.bt_test_utils import advertising_set_started
     28 from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
     29 
     30 import time
     31 import os
     32 
     33 
     34 class BleLib():
     35     def __init__(self, log, mac_addr, dut):
     36         self.advertisement_list = []
     37         self.dut = dut
     38         self.log = log
     39         self.mac_addr = mac_addr
     40         self.default_timeout = 5
     41         self.set_advertisement_list = []
     42         self.generic_uuid = "0000{}-0000-1000-8000-00805f9b34fb"
     43 
     44     def _verify_ble_adv_started(self, advertise_callback):
     45         """Helper for verifying if an advertisment started or not"""
     46         regex = "({}|{})".format(
     47             adv_succ.format(advertise_callback),
     48             adv_fail.format(advertise_callback))
     49         try:
     50             event = self.dut.ed.pop_events(regex, 5, TIMEOUT_SMALL)
     51         except Empty:
     52             self.dut.log.error("Failed to get success or failed event.")
     53             return
     54         if event[0]["name"] == adv_succ.format(advertise_callback):
     55             self.dut.log.info("Advertisement started successfully.")
     56             return True
     57         else:
     58             self.dut.log.info("Advertisement failed to start.")
     59             return False
     60 
     61     def start_generic_connectable_advertisement(self, line):
     62         """Start a connectable LE advertisement"""
     63         scan_response = None
     64         if line:
     65             scan_response = bool(line)
     66         self.dut.droid.bleSetAdvertiseSettingsAdvertiseMode(
     67             AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
     68         self.dut.droid.bleSetAdvertiseSettingsIsConnectable(True)
     69         advertise_callback, advertise_data, advertise_settings = (
     70             generate_ble_advertise_objects(self.dut.droid))
     71         if scan_response:
     72             self.dut.droid.bleStartBleAdvertisingWithScanResponse(
     73                 advertise_callback, advertise_data, advertise_settings,
     74                 advertise_data)
     75         else:
     76             self.dut.droid.bleStartBleAdvertising(
     77                 advertise_callback, advertise_data, advertise_settings)
     78         if self._verify_ble_adv_started(advertise_callback):
     79             self.log.info(
     80                 "Tracking Callback ID: {}".format(advertise_callback))
     81             self.advertisement_list.append(advertise_callback)
     82             self.log.info(self.advertisement_list)
     83 
     84     def start_connectable_advertisement_set(self, line):
     85         """Start Connectable Advertisement Set"""
     86         adv_callback = self.dut.droid.bleAdvSetGenCallback()
     87         adv_data = {
     88             "includeDeviceName": True,
     89         }
     90         self.dut.droid.bleAdvSetStartAdvertisingSet({
     91             "connectable":
     92             True,
     93             "legacyMode":
     94             False,
     95             "primaryPhy":
     96             "PHY_LE_1M",
     97             "secondaryPhy":
     98             "PHY_LE_1M",
     99             "interval":
    100             320
    101         }, adv_data, None, None, None, 0, 0, adv_callback)
    102         evt = self.dut.ed.pop_event(
    103             advertising_set_started.format(adv_callback), self.default_timeout)
    104         set_id = evt['data']['setId']
    105         self.log.error("did not receive the set started event!")
    106         evt = self.dut.ed.pop_event(
    107             advertising_set_on_own_address_read.format(set_id),
    108             self.default_timeout)
    109         address = evt['data']['address']
    110         self.log.info("Advertiser address is: {}".format(str(address)))
    111         self.set_advertisement_list.append(adv_callback)
    112 
    113     def stop_all_advertisement_set(self, line):
    114         """Stop all Advertisement Sets"""
    115         for adv in self.set_advertisement_list:
    116             try:
    117                 self.dut.droid.bleAdvSetStopAdvertisingSet(adv)
    118             except Exception as err:
    119                 self.log.error("Failed to stop advertisement: {}".format(err))
    120 
    121     def adv_add_service_uuid_list(self, line):
    122         """Add service UUID to the LE advertisement inputs:
    123          [uuid1 uuid2 ... uuidN]"""
    124         uuids = line.split()
    125         uuid_list = []
    126         for uuid in uuids:
    127             if len(uuid) == 4:
    128                 uuid = self.generic_uuid.format(line)
    129             uuid_list.append(uuid)
    130         self.dut.droid.bleSetAdvertiseDataSetServiceUuids(uuid_list)
    131 
    132     def adv_data_include_local_name(self, is_included):
    133         """Include local name in the advertisement. inputs: [true|false]"""
    134         self.dut.droid.bleSetAdvertiseDataIncludeDeviceName(bool(is_included))
    135 
    136     def adv_data_include_tx_power_level(self, is_included):
    137         """Include tx power level in the advertisement. inputs: [true|false]"""
    138         self.dut.droid.bleSetAdvertiseDataIncludeTxPowerLevel(
    139             bool(is_included))
    140 
    141     def adv_data_add_manufacturer_data(self, line):
    142         """Include manufacturer id and data to the advertisment:
    143         [id data1 data2 ... dataN]"""
    144         info = line.split()
    145         manu_id = int(info[0])
    146         manu_data = []
    147         for data in info[1:]:
    148             manu_data.append(int(data))
    149         self.dut.droid.bleAddAdvertiseDataManufacturerId(manu_id, manu_data)
    150 
    151     def start_generic_nonconnectable_advertisement(self, line):
    152         """Start a nonconnectable LE advertisement"""
    153         self.dut.droid.bleSetAdvertiseSettingsAdvertiseMode(
    154             AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
    155         self.dut.droid.bleSetAdvertiseSettingsIsConnectable(False)
    156         advertise_callback, advertise_data, advertise_settings = (
    157             generate_ble_advertise_objects(self.dut.droid))
    158         self.dut.droid.bleStartBleAdvertising(
    159             advertise_callback, advertise_data, advertise_settings)
    160         if self._verify_ble_adv_started(advertise_callback):
    161             self.log.info(
    162                 "Tracking Callback ID: {}".format(advertise_callback))
    163             self.advertisement_list.append(advertise_callback)
    164             self.log.info(self.advertisement_list)
    165 
    166     def stop_all_advertisements(self, line):
    167         """Stop all LE advertisements"""
    168         for callback_id in self.advertisement_list:
    169             self.log.info("Stopping Advertisement {}".format(callback_id))
    170             self.dut.droid.bleStopBleAdvertising(callback_id)
    171             time.sleep(1)
    172         self.advertisement_list = []
    173 
    174     def do_ble_stop_advertisement(self, callback_id):
    175         """Stop an LE advertisement"""
    176         if not callback_id:
    177             self.log.info("Need a callback ID")
    178             return
    179         callback_id = int(callback_id)
    180         if callback_id not in self.advertisement_list:
    181             self.log.info("Callback not in list of advertisements.")
    182             return
    183         self.dut.droid.bleStopBleAdvertising(callback_id)
    184         self.advertisement_list.remove(callback_id)
    185