1//
2//  Copyright (C) 2015 Google, Inc.
3//
4//  Licensed under the Apache License, Version 2.0 (the "License");
5//  you may not use this file except in compliance with the License.
6//  You may obtain a copy of the License at:
7//
8//  http://www.apache.org/licenses/LICENSE-2.0
9//
10//  Unless required by applicable law or agreed to in writing, software
11//  distributed under the License is distributed on an "AS IS" BASIS,
12//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13//  See the License for the specific language governing permissions and
14//  limitations under the License.
15//
16
17#include "service/adapter.h"
18
19#include <atomic>
20#include <mutex>
21#include <string>
22#include <unordered_set>
23
24#include <base/logging.h>
25#include <base/observer_list.h>
26
27#include "service/common/bluetooth/util/atomic_string.h"
28#include "service/gatt_client.h"
29#include "service/gatt_server.h"
30#include "service/hal/bluetooth_interface.h"
31#include "service/logging_helpers.h"
32#include "service/low_energy_client.h"
33
34using std::lock_guard;
35using std::mutex;
36
37namespace bluetooth {
38
39// static
40const char Adapter::kDefaultAddress[] = "00:00:00:00:00:00";
41// static
42const char Adapter::kDefaultName[] = "not-initialized";
43
44// TODO(armansito): The following constants come straight from
45// packages/apps/Bluetooth/src/c/a/b/btservice/AdapterService.java. It would be
46// nice to know if there were a way to obtain these values from the stack
47// instead of hardcoding them here.
48
49// The minimum number of advertising instances required for multi-advertisement
50// support.
51const int kMinAdvInstancesForMultiAdv = 5;
52
53// Used when determining if offloaded scan filtering is supported.
54const int kMinOffloadedFilters = 10;
55
56// Used when determining if offloaded scan batching is supported.
57const int kMinOffloadedScanStorageBytes = 1024;
58
59void Adapter::Observer::OnAdapterStateChanged(Adapter* adapter,
60                                              AdapterState prev_state,
61                                              AdapterState new_state) {
62  // Default implementation does nothing
63}
64
65void Adapter::Observer::OnDeviceConnectionStateChanged(
66    Adapter* adapter, const std::string& device_address, bool connected) {
67  // Default implementation does nothing
68}
69
70// The real Adapter implementation used in production.
71class AdapterImpl : public Adapter,
72                    public hal::BluetoothInterface::Observer {
73 public:
74  AdapterImpl()
75    : state_(ADAPTER_STATE_OFF),
76      address_(kDefaultAddress),
77      name_(kDefaultName) {
78    memset(&local_le_features_, 0, sizeof(local_le_features_));
79    hal::BluetoothInterface::Get()->AddObserver(this);
80    ble_client_factory_.reset(new LowEnergyClientFactory(*this));
81    gatt_client_factory_.reset(new GattClientFactory());
82    gatt_server_factory_.reset(new GattServerFactory());
83    hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties();
84  }
85
86  ~AdapterImpl() override {
87    hal::BluetoothInterface::Get()->RemoveObserver(this);
88  }
89
90  void AddObserver(Adapter::Observer* observer) override {
91    lock_guard<mutex> lock(observers_lock_);
92    observers_.AddObserver(observer);
93  }
94
95  void RemoveObserver(Adapter::Observer* observer) override {
96    lock_guard<mutex> lock(observers_lock_);
97    observers_.RemoveObserver(observer);
98  }
99
100  AdapterState GetState() const override {
101    return state_.load();
102  }
103
104  bool IsEnabled() const override {
105    return state_.load() == ADAPTER_STATE_ON;
106  }
107
108  bool Enable(bool start_restricted) override {
109    AdapterState current_state = GetState();
110    if (current_state != ADAPTER_STATE_OFF) {
111      LOG(INFO) << "Adapter not disabled - state: "
112                << AdapterStateToString(current_state);
113      return false;
114    }
115
116    // Set the state before calling enable() as there might be a race between
117    // here and the AdapterStateChangedCallback.
118    state_ = ADAPTER_STATE_TURNING_ON;
119    NotifyAdapterStateChanged(current_state, state_);
120
121    int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable(start_restricted);
122    if (status != BT_STATUS_SUCCESS) {
123      LOG(ERROR) << "Failed to enable Bluetooth - status: "
124                 << BtStatusText((const bt_status_t)status);
125      state_ = ADAPTER_STATE_OFF;
126      NotifyAdapterStateChanged(ADAPTER_STATE_TURNING_ON, state_);
127      return false;
128    }
129
130    return true;
131  }
132
133  bool Disable() override {
134    if (!IsEnabled()) {
135      LOG(INFO) << "Adapter is not enabled";
136      return false;
137    }
138
139    AdapterState current_state = GetState();
140
141    // Set the state before calling enable() as there might be a race between
142    // here and the AdapterStateChangedCallback.
143    state_ = ADAPTER_STATE_TURNING_OFF;
144    NotifyAdapterStateChanged(current_state, state_);
145
146    int status = hal::BluetoothInterface::Get()->GetHALInterface()->disable();
147    if (status != BT_STATUS_SUCCESS) {
148      LOG(ERROR) << "Failed to disable Bluetooth - status: "
149                 << BtStatusText((const bt_status_t)status);
150      state_ = current_state;
151      NotifyAdapterStateChanged(ADAPTER_STATE_TURNING_OFF, state_);
152      return false;
153    }
154
155    return true;
156  }
157
158  std::string GetName() const override {
159    return name_.Get();
160  }
161
162  bool SetName(const std::string& name) override {
163    bt_bdname_t hal_name;
164    size_t max_name_len = sizeof(hal_name.name);
165
166    // Include the \0 byte in size measurement.
167    if (name.length() >= max_name_len) {
168      LOG(ERROR) << "Given name \"" << name << "\" is larger than maximum"
169                 << " allowed size: " << max_name_len;
170      return false;
171    }
172
173    strncpy(reinterpret_cast<char*>(hal_name.name), name.c_str(),
174            name.length() + 1);
175
176    VLOG(1) << "Setting adapter name: " << name;
177
178    if (!SetAdapterProperty(BT_PROPERTY_BDNAME, &hal_name, sizeof(hal_name))) {
179      LOG(ERROR) << "Failed to set adapter name: " << name;
180      return false;
181    }
182
183    return true;
184  }
185
186  std::string GetAddress() const override {
187    return address_.Get();
188  }
189
190  bool IsMultiAdvertisementSupported() override {
191    lock_guard<mutex> lock(local_le_features_lock_);
192    return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv;
193  }
194
195  bool IsDeviceConnected(const std::string& device_address) override {
196    lock_guard<mutex> lock(connected_devices_lock_);
197    return connected_devices_.find(device_address) != connected_devices_.end();
198  }
199
200  int GetTotalNumberOfTrackableAdvertisements() override {
201    lock_guard<mutex> lock(local_le_features_lock_);
202    return local_le_features_.total_trackable_advertisers;
203  }
204
205  bool IsOffloadedFilteringSupported() override {
206    lock_guard<mutex> lock(local_le_features_lock_);
207    return local_le_features_.max_adv_filter_supported >= kMinOffloadedFilters;
208  }
209
210  bool IsOffloadedScanBatchingSupported() override {
211    lock_guard<mutex> lock(local_le_features_lock_);
212    return local_le_features_.scan_result_storage_size >=
213        kMinOffloadedScanStorageBytes;
214  }
215
216  LowEnergyClientFactory* GetLowEnergyClientFactory() const override {
217    return ble_client_factory_.get();
218  }
219
220  GattClientFactory* GetGattClientFactory() const override {
221    return gatt_client_factory_.get();
222  }
223
224  GattServerFactory* GetGattServerFactory() const override {
225    return gatt_server_factory_.get();
226  }
227
228  // hal::BluetoothInterface::Observer overrides.
229  void AdapterStateChangedCallback(bt_state_t state) override {
230    LOG(INFO) << "Adapter state changed: " << BtStateText(state);
231
232    AdapterState prev_state = GetState();
233
234    switch (state) {
235    case BT_STATE_OFF:
236      state_ = ADAPTER_STATE_OFF;
237      break;
238
239    case BT_STATE_ON:
240      state_ = ADAPTER_STATE_ON;
241      break;
242
243    default:
244      NOTREACHED();
245    }
246
247    NotifyAdapterStateChanged(prev_state, GetState());
248  }
249
250  void AdapterPropertiesCallback(bt_status_t status,
251                                 int num_properties,
252                                 bt_property_t* properties) override {
253    LOG(INFO) << "Adapter properties changed";
254
255    if (status != BT_STATUS_SUCCESS) {
256      LOG(ERROR) << "status: " << BtStatusText(status);
257      return;
258    }
259
260    for (int i = 0; i < num_properties; i++) {
261      bt_property_t* property = properties + i;
262      switch (property->type) {
263        case BT_PROPERTY_BDADDR: {
264          std::string address = BtAddrString(reinterpret_cast<bt_bdaddr_t*>(
265              property->val));
266          LOG(INFO) << "Adapter address changed: " << address;
267          address_.Set(address);
268          break;
269        }
270        case BT_PROPERTY_BDNAME: {
271          bt_bdname_t* hal_name = reinterpret_cast<bt_bdname_t*>(property->val);
272          std::string name = reinterpret_cast<char*>(hal_name->name);
273          LOG(INFO) << "Adapter name changed: " << name;
274          name_.Set(name);
275          break;
276        }
277        case BT_PROPERTY_LOCAL_LE_FEATURES: {
278          lock_guard<mutex> lock(local_le_features_lock_);
279          if (property->len != sizeof(bt_local_le_features_t)) {
280            LOG(WARNING) << "Malformed value received for property: "
281                         << "BT_PROPERTY_LOCAL_LE_FEATURES";
282            break;
283          }
284          bt_local_le_features_t* features =
285              reinterpret_cast<bt_local_le_features_t*>(property->val);
286          memcpy(&local_le_features_, features, sizeof(*features));
287          LOG(INFO) << "Supported LE features updated";
288          break;
289        }
290        default:
291          VLOG(1) << "Unhandled adapter property: "
292                  << BtPropertyText(property->type);
293          break;
294      }
295
296      // TODO(armansito): notify others of the updated properties
297    }
298  }
299
300  void AclStateChangedCallback(bt_status_t status,
301                               const bt_bdaddr_t& remote_bdaddr,
302                               bt_acl_state_t state) override {
303    std::string device_address = BtAddrString(&remote_bdaddr);
304    bool connected = (state == BT_ACL_STATE_CONNECTED);
305    LOG(INFO) << "ACL state changed: " << device_address << " - connected: "
306              << (connected ? "true" : "false");
307
308    // If this is reported with an error status, I suppose the best thing we can
309    // do is to log it and ignore the event.
310    if (status != BT_STATUS_SUCCESS) {
311      LOG(ERROR) << "status: " << BtStatusText(status);
312      return;
313    }
314
315    // Introduce a scope to manage |connected_devices_lock_| with RAII.
316    {
317      lock_guard<mutex> lock(connected_devices_lock_);
318      if (connected)
319        connected_devices_.insert(device_address);
320      else
321        connected_devices_.erase(device_address);
322    }
323
324    lock_guard<mutex> lock(observers_lock_);
325    FOR_EACH_OBSERVER(
326        Adapter::Observer, observers_,
327        OnDeviceConnectionStateChanged(this, device_address, connected));
328  }
329
330  // Sends a request to set the given HAL adapter property type and value.
331  bool SetAdapterProperty(bt_property_type_t type, void* value, int length) {
332    CHECK(length > 0);
333    CHECK(value);
334
335    bt_property_t property;
336    property.len = length;
337    property.val = value;
338    property.type = type;
339
340    int status = hal::BluetoothInterface::Get()->GetHALInterface()->
341        set_adapter_property(&property);
342    if (status != BT_STATUS_SUCCESS) {
343      VLOG(1) << "Failed to set property";
344      return false;
345    }
346
347    return true;
348  }
349
350  // Helper for invoking the AdapterStateChanged observer method.
351  void NotifyAdapterStateChanged(AdapterState prev_state,
352                                 AdapterState new_state) {
353    if (prev_state == new_state)
354      return;
355
356    lock_guard<mutex> lock(observers_lock_);
357    FOR_EACH_OBSERVER(Adapter::Observer, observers_,
358                      OnAdapterStateChanged(this, prev_state, new_state));
359  }
360
361 private:
362  // The current adapter state.
363  std::atomic<AdapterState> state_;
364
365  // The Bluetooth device address of the local adapter in string from
366  // (i.e.. XX:XX:XX:XX:XX:XX)
367  util::AtomicString address_;
368
369  // The current local adapter name.
370  util::AtomicString name_;
371
372  // The current set of supported LE features as obtained from the stack. The
373  // values here are all initially set to 0 and updated when the corresponding
374  // adapter property has been received from the stack.
375  std::mutex local_le_features_lock_;
376  bt_local_le_features_t local_le_features_;
377
378  // List of observers that are interested in notifications from us.
379  std::mutex observers_lock_;
380  base::ObserverList<Adapter::Observer> observers_;
381
382  // List of devices addresses that are currently connected.
383  std::mutex connected_devices_lock_;
384  std::unordered_set<std::string> connected_devices_;
385
386  // Factory used to create per-app LowEnergyClient instances.
387  std::unique_ptr<LowEnergyClientFactory> ble_client_factory_;
388
389  // Factory used to create per-app GattClient instances.
390  std::unique_ptr<GattClientFactory> gatt_client_factory_;
391
392  // Factory used to create per-app GattServer instances.
393  std::unique_ptr<GattServerFactory> gatt_server_factory_;
394
395  DISALLOW_COPY_AND_ASSIGN(AdapterImpl);
396};
397
398// static
399std::unique_ptr<Adapter> Adapter::Create() {
400  return std::unique_ptr<Adapter>(new AdapterImpl());
401}
402
403}  // namespace bluetooth
404