summaryrefslogtreecommitdiffstats
path: root/device/bluetooth/bluetooth_adapter_bluez.h
blob: de52c896e934e06a1426c226d1c12cdf7636dcff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_BLUEZ_H_
#define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_BLUEZ_H_

#include <stdint.h>

#include <map>
#include <queue>
#include <string>
#include <utility>
#include <vector>

#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_audio_sink.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
#include "device/bluetooth/dbus/bluetooth_device_client.h"
#include "device/bluetooth/dbus/bluetooth_input_client.h"
#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"

namespace base {
class SequencedTaskRunner;
}  // namespace base

namespace device {
class BluetoothSocketThread;
}  // namespace device

namespace bluez {

class BluetoothBlueZTest;
class BluetoothAdapterProfileBlueZ;
class BluetoothDeviceBlueZ;
class BluetoothPairingBlueZ;
class BluetoothRemoteGattCharacteristicBlueZ;
class BluetoothRemoteGattDescriptorBlueZ;
class BluetoothRemoteGattServiceBlueZ;

// The BluetoothAdapterBlueZ class implements BluetoothAdapter for platforms
// that use BlueZ.
//
// All methods are called from the dbus origin / UI thread and are generally
// not assumed to be thread-safe.
//
// This class interacts with sockets using the BluetoothSocketThread to ensure
// single-threaded calls, and posts tasks to the UI thread.
//
// Methods tolerate a shutdown scenario where BluetoothAdapterBlueZ::Shutdown
// causes IsPresent to return false just before the dbus system is shutdown but
// while references to the BluetoothAdapterBlueZ object still exists.
//
// When adding methods to this class verify shutdown behavior in
// BluetoothBlueZTest, Shutdown.
class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterBlueZ
    : public device::BluetoothAdapter,
      public bluez::BluetoothAdapterClient::Observer,
      public bluez::BluetoothDeviceClient::Observer,
      public bluez::BluetoothInputClient::Observer,
      public bluez::BluetoothAgentServiceProvider::Delegate {
 public:
  typedef base::Callback<void(const std::string& error_message)>
      ErrorCompletionCallback;
  typedef base::Callback<void(BluetoothAdapterProfileBlueZ* profile)>
      ProfileRegisteredCallback;

  // Calls |init_callback| after a BluetoothAdapter is fully initialized.
  static base::WeakPtr<BluetoothAdapter> CreateAdapter(
      const InitCallback& init_callback);

  // BluetoothAdapter:
  void Shutdown() override;
  UUIDList GetUUIDs() const override;
  std::string GetAddress() const override;
  std::string GetName() const override;
  void SetName(const std::string& name,
               const base::Closure& callback,
               const ErrorCallback& error_callback) override;
  bool IsInitialized() const override;
  bool IsPresent() const override;
  bool IsPowered() const override;
  void SetPowered(bool powered,
                  const base::Closure& callback,
                  const ErrorCallback& error_callback) override;
  bool IsDiscoverable() const override;
  void SetDiscoverable(bool discoverable,
                       const base::Closure& callback,
                       const ErrorCallback& error_callback) override;
  bool IsDiscovering() const override;
  void CreateRfcommService(
      const device::BluetoothUUID& uuid,
      const ServiceOptions& options,
      const CreateServiceCallback& callback,
      const CreateServiceErrorCallback& error_callback) override;
  void CreateL2capService(
      const device::BluetoothUUID& uuid,
      const ServiceOptions& options,
      const CreateServiceCallback& callback,
      const CreateServiceErrorCallback& error_callback) override;
  void RegisterAudioSink(
      const device::BluetoothAudioSink::Options& options,
      const device::BluetoothAdapter::AcquiredCallback& callback,
      const device::BluetoothAudioSink::ErrorCallback& error_callback) override;

  void RegisterAdvertisement(
      scoped_ptr<device::BluetoothAdvertisement::Data> advertisement_data,
      const CreateAdvertisementCallback& callback,
      const CreateAdvertisementErrorCallback& error_callback) override;

  // Locates the device object by object path (the devices map and
  // BluetoothDevice methods are by address).
  BluetoothDeviceBlueZ* GetDeviceWithPath(const dbus::ObjectPath& object_path);

  // Announces to observers a change in device state that is not reflected by
  // its D-Bus properties. |device| is owned by the caller and cannot be NULL.
  void NotifyDeviceChanged(BluetoothDeviceBlueZ* device);

  // Announce to observers a device address change.
  void NotifyDeviceAddressChanged(BluetoothDeviceBlueZ* device,
                                  const std::string& old_address);

  // Returns the object path of the adapter.
  const dbus::ObjectPath& object_path() const { return object_path_; }

  // Request a profile on the adapter for a custom service with a
  // specific UUID for the device at |device_path| to be sent to |delegate|.
  // If |device_path| is the empty string, incoming connections will be
  // assigned to |delegate|.  When the profile is
  // successfully registered, |success_callback| will be called with a pointer
  // to the profile which is managed by BluetoothAdapterBlueZ.  On failure,
  // |error_callback| will be called.
  void UseProfile(const device::BluetoothUUID& uuid,
                  const dbus::ObjectPath& device_path,
                  const bluez::BluetoothProfileManagerClient::Options& options,
                  bluez::BluetoothProfileServiceProvider::Delegate* delegate,
                  const ProfileRegisteredCallback& success_callback,
                  const ErrorCompletionCallback& error_callback);

  // Release use of a profile by a device.
  void ReleaseProfile(const dbus::ObjectPath& device_path,
                      BluetoothAdapterProfileBlueZ* profile);

 protected:
  // BluetoothAdapter:
  void RemovePairingDelegateInternal(
      device::BluetoothDevice::PairingDelegate* pairing_delegate) override;

 private:
  friend class BluetoothBlueZTest;
  friend class BluetoothBlueZTest_Shutdown_Test;
  friend class BluetoothBlueZTest_Shutdown_OnStartDiscovery_Test;
  friend class BluetoothBlueZTest_Shutdown_OnStartDiscoveryError_Test;
  friend class BluetoothBlueZTest_Shutdown_OnStopDiscovery_Test;
  friend class BluetoothBlueZTest_Shutdown_OnStopDiscoveryError_Test;

  // typedef for callback parameters that are passed to AddDiscoverySession
  // and RemoveDiscoverySession. This is used to queue incoming requests while
  // a call to BlueZ is pending.
  typedef std::tuple<device::BluetoothDiscoveryFilter*,
                     base::Closure,
                     DiscoverySessionErrorCallback> DiscoveryParamTuple;
  typedef std::queue<DiscoveryParamTuple> DiscoveryCallbackQueue;

  // Callback pair for the profile registration queue.
  typedef std::pair<base::Closure, ErrorCompletionCallback>
      RegisterProfileCompletionPair;

  explicit BluetoothAdapterBlueZ(const InitCallback& init_callback);
  ~BluetoothAdapterBlueZ() override;

  // Init will get asynchronouly called once we know if Object Manager is
  // supported.
  void Init();

  // bluez::BluetoothAdapterClient::Observer override.
  void AdapterAdded(const dbus::ObjectPath& object_path) override;
  void AdapterRemoved(const dbus::ObjectPath& object_path) override;
  void AdapterPropertyChanged(const dbus::ObjectPath& object_path,
                              const std::string& property_name) override;

  // bluez::BluetoothDeviceClient::Observer override.
  void DeviceAdded(const dbus::ObjectPath& object_path) override;
  void DeviceRemoved(const dbus::ObjectPath& object_path) override;
  void DevicePropertyChanged(const dbus::ObjectPath& object_path,
                             const std::string& property_name) override;

  // bluez::BluetoothInputClient::Observer override.
  void InputPropertyChanged(const dbus::ObjectPath& object_path,
                            const std::string& property_name) override;

  // bluez::BluetoothAgentServiceProvider::Delegate override.
  void Released() override;
  void RequestPinCode(const dbus::ObjectPath& device_path,
                      const PinCodeCallback& callback) override;
  void DisplayPinCode(const dbus::ObjectPath& device_path,
                      const std::string& pincode) override;
  void RequestPasskey(const dbus::ObjectPath& device_path,
                      const PasskeyCallback& callback) override;
  void DisplayPasskey(const dbus::ObjectPath& device_path,
                      uint32_t passkey,
                      uint16_t entered) override;
  void RequestConfirmation(const dbus::ObjectPath& device_path,
                           uint32_t passkey,
                           const ConfirmationCallback& callback) override;
  void RequestAuthorization(const dbus::ObjectPath& device_path,
                            const ConfirmationCallback& callback) override;
  void AuthorizeService(const dbus::ObjectPath& device_path,
                        const std::string& uuid,
                        const ConfirmationCallback& callback) override;
  void Cancel() override;

  // Called by dbus:: on completion of the D-Bus method call to register the
  // pairing agent.
  void OnRegisterAgent();
  void OnRegisterAgentError(const std::string& error_name,
                            const std::string& error_message);

  // Called by dbus:: on completion of the D-Bus method call to request that
  // the pairing agent be made the default.
  void OnRequestDefaultAgent();
  void OnRequestDefaultAgentError(const std::string& error_name,
                                  const std::string& error_message);

  // Called by BluetoothAudioSinkBlueZ on completion of registering an audio
  // sink.
  void OnRegisterAudioSink(
      const device::BluetoothAdapter::AcquiredCallback& callback,
      const device::BluetoothAudioSink::ErrorCallback& error_callback,
      scoped_refptr<device::BluetoothAudioSink> audio_sink);

  // Internal method to obtain a BluetoothPairingBlueZ object for the device
  // with path |object_path|. Returns the existing pairing object if the device
  // already has one (usually an outgoing connection in progress) or a new
  // pairing object with the default pairing delegate if not. If no default
  // pairing object exists, NULL will be returned.
  BluetoothPairingBlueZ* GetPairing(const dbus::ObjectPath& object_path);

  // Set the tracked adapter to the one in |object_path|, this object will
  // subsequently operate on that adapter until it is removed.
  void SetAdapter(const dbus::ObjectPath& object_path);

  // Set the adapter name to one chosen from the system information.
  void SetDefaultAdapterName();

  // Remove the currently tracked adapter. IsPresent() will return false after
  // this is called.
  void RemoveAdapter();

  // Announce to observers a change in the adapter state.
  void PoweredChanged(bool powered);
  void DiscoverableChanged(bool discoverable);
  void DiscoveringChanged(bool discovering);
  void PresentChanged(bool present);

  // Called by dbus:: on completion of the discoverable property change.
  void OnSetDiscoverable(const base::Closure& callback,
                         const ErrorCallback& error_callback,
                         bool success);

  // Called by dbus:: on completion of an adapter property change.
  void OnPropertyChangeCompleted(const base::Closure& callback,
                                 const ErrorCallback& error_callback,
                                 bool success);

  // BluetoothAdapter:
  void AddDiscoverySession(
      device::BluetoothDiscoveryFilter* discovery_filter,
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback) override;
  void RemoveDiscoverySession(
      device::BluetoothDiscoveryFilter* discovery_filter,
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback) override;
  void SetDiscoveryFilter(
      scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter,
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback) override;

  // Called by dbus:: on completion of the D-Bus method call to start discovery.
  void OnStartDiscovery(const base::Closure& callback,
                        const DiscoverySessionErrorCallback& error_callback);
  void OnStartDiscoveryError(
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback,
      const std::string& error_name,
      const std::string& error_message);

  // Called by dbus:: on completion of the D-Bus method call to stop discovery.
  void OnStopDiscovery(const base::Closure& callback);
  void OnStopDiscoveryError(const DiscoverySessionErrorCallback& error_callback,
                            const std::string& error_name,
                            const std::string& error_message);

  void OnPreSetDiscoveryFilter(
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback);
  void OnPreSetDiscoveryFilterError(
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback,
      device::UMABluetoothDiscoverySessionOutcome outcome);
  void OnSetDiscoveryFilter(
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback);
  void OnSetDiscoveryFilterError(
      const base::Closure& callback,
      const DiscoverySessionErrorCallback& error_callback,
      const std::string& error_name,
      const std::string& error_message);

  // Called by dbus:: on completion of the D-Bus method to register a profile.
  void OnRegisterProfile(const device::BluetoothUUID& uuid,
                         scoped_ptr<BluetoothAdapterProfileBlueZ> profile);

  void SetProfileDelegate(
      const device::BluetoothUUID& uuid,
      const dbus::ObjectPath& device_path,
      bluez::BluetoothProfileServiceProvider::Delegate* delegate,
      const ProfileRegisteredCallback& success_callback,
      const ErrorCompletionCallback& error_callback);
  void OnRegisterProfileError(const device::BluetoothUUID& uuid,
                              const std::string& error_name,
                              const std::string& error_message);

  // Called by BluetoothAdapterProfileBlueZ when no users of a profile
  // remain.
  void RemoveProfile(const device::BluetoothUUID& uuid);

  // Processes the queued discovery requests. For each DiscoveryParamTuple in
  // the queue, this method will try to add a new discovery session. This method
  // is called whenever a pending D-Bus call to start or stop discovery has
  // ended (with either success or failure).
  void ProcessQueuedDiscoveryRequests();

  InitCallback init_callback_;

  bool initialized_;

  // Set in |Shutdown()|, makes IsPresent()| return false.
  bool dbus_is_shutdown_;

  // Number of discovery sessions that have been added.
  int num_discovery_sessions_;

  // True, if there is a pending request to start or stop discovery.
  bool discovery_request_pending_;

  // List of queued requests to add new discovery sessions. While there is a
  // pending request to BlueZ to start or stop discovery, many requests from
  // within Chrome to start or stop discovery sessions may occur. We only
  // queue requests to add new sessions to be processed later. All requests to
  // remove a session while a call is pending immediately return failure. Note
  // that since BlueZ keeps its own reference count of applications that have
  // requested discovery, dropping our count to 0 won't necessarily result in
  // the controller actually stopping discovery if, for example, an application
  // other than Chrome, such as bt_console, was also used to start discovery.
  DiscoveryCallbackQueue discovery_request_queue_;

  // Object path of the adapter we track.
  dbus::ObjectPath object_path_;

  // Instance of the D-Bus agent object used for pairing, initialized with
  // our own class as its delegate.
  scoped_ptr<bluez::BluetoothAgentServiceProvider> agent_;

  // UI thread task runner and socket thread object used to create sockets.
  scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
  scoped_refptr<device::BluetoothSocketThread> socket_thread_;

  // The profiles we have registered with the bluetooth daemon.
  std::map<device::BluetoothUUID, BluetoothAdapterProfileBlueZ*> profiles_;

  // Queue of delegates waiting for a profile to register.
  std::map<device::BluetoothUUID, std::vector<RegisterProfileCompletionPair>*>
      profile_queues_;

  scoped_ptr<device::BluetoothDiscoveryFilter> current_filter_;

  // Note: This should remain the last member so it'll be destroyed and
  // invalidate its weak pointers before any other members are destroyed.
  base::WeakPtrFactory<BluetoothAdapterBlueZ> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterBlueZ);
};

}  // namespace bluez

#endif  // DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_BLUEZ_H_