summaryrefslogtreecommitdiffstats
path: root/device/bluetooth/bluetooth_audio_sink_chromeos.h
blob: 750b31de5f9589d1bbb833732487815a674d104c (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
// Copyright 2015 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_AUDIO_SINK_CHROMEOS_H_
#define DEVICE_BLUETOOTH_BLUETOOTH_AUDIO_SINK_CHROMEOS_H_

#include <stdint.h>
#include <string>
#include <vector>

#include "base/files/file.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/observer_list.h"
#include "dbus/file_descriptor.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_audio_sink.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/dbus/bluetooth_media_client.h"
#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h"
#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"

namespace chromeos {

class BluetoothAudioSinkChromeOSTest;

class DEVICE_BLUETOOTH_EXPORT BluetoothAudioSinkChromeOS
    : public device::BluetoothAudioSink,
      public device::BluetoothAdapter::Observer,
      public bluez::BluetoothMediaClient::Observer,
      public bluez::BluetoothMediaTransportClient::Observer,
      public bluez::BluetoothMediaEndpointServiceProvider::Delegate,
      public base::MessageLoopForIO::Watcher {
 public:
  explicit BluetoothAudioSinkChromeOS(
      scoped_refptr<device::BluetoothAdapter> adapter);

  // device::BluetoothAudioSink overrides.
  // Unregisters a BluetoothAudioSink. |callback| should handle
  // the clean-up after the audio sink is deleted successfully, otherwise
  // |error_callback| will be called.
  void Unregister(
      const base::Closure& callback,
      const device::BluetoothAudioSink::ErrorCallback& error_callback) override;
  void AddObserver(BluetoothAudioSink::Observer* observer) override;
  void RemoveObserver(BluetoothAudioSink::Observer* observer) override;
  device::BluetoothAudioSink::State GetState() const override;
  uint16_t GetVolume() const override;

  // Registers a BluetoothAudioSink. User applications can use |options| to
  // configure the audio sink. |callback| will be executed if the audio sink is
  // successfully registered, otherwise |error_callback| will be called. Called
  // by BluetoothAdapterChromeOS.
  void Register(
      const device::BluetoothAudioSink::Options& options,
      const base::Closure& callback,
      const device::BluetoothAudioSink::ErrorCallback& error_callback);

  // Returns a pointer to the media endpoint object. This function should be
  // used for testing purpose only.
  bluez::BluetoothMediaEndpointServiceProvider* GetEndpointServiceProvider();

 private:
  ~BluetoothAudioSinkChromeOS() override;

  // device::BluetoothAdapter::Observer overrides.
  void AdapterPresentChanged(device::BluetoothAdapter* adapter,
                             bool present) override;
  void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
                             bool powered) override;

  // bluez::BluetoothMediaClient::Observer overrides.
  void MediaRemoved(const dbus::ObjectPath& object_path) override;

  // bluez::BluetoothMediaTransportClient::Observer overrides.
  void MediaTransportRemoved(const dbus::ObjectPath& object_path) override;
  void MediaTransportPropertyChanged(const dbus::ObjectPath& object_path,
                                     const std::string& property_name) override;

  // bluez::BluetoothMediaEndpointServiceProvider::Delegate overrides.
  void SetConfiguration(const dbus::ObjectPath& transport_path,
                        const TransportProperties& properties) override;
  void SelectConfiguration(
      const std::vector<uint8_t>& capabilities,
      const SelectConfigurationCallback& callback) override;
  void ClearConfiguration(const dbus::ObjectPath& transport_path) override;
  void Released() override;

  // base::MessageLoopForIO::Watcher overrides.
  void OnFileCanReadWithoutBlocking(int fd) override;
  void OnFileCanWriteWithoutBlocking(int fd) override;

  // Acquires file descriptor via current transport object when the state change
  // is triggered by MediaTransportPropertyChanged.
  void AcquireFD();

  // Watches if there is any available data from |fd_|.
  void WatchFD();

  // Stops watching |fd_| and resets |fd_|.
  void StopWatchingFD();

  // Reads from the file descriptor acquired via Media Transport object and
  // notify |observer_| while the audio data is available.
  void ReadFromFile();

  // Called when the state property of BluetoothMediaTransport has been updated.
  void StateChanged(device::BluetoothAudioSink::State state);

  // Called when the volume property of BluetoothMediaTransport has been
  // updated.
  void VolumeChanged(uint16_t volume);

  // Called when the registration of Media Endpoint has succeeded.
  void OnRegisterSucceeded(const base::Closure& callback);

  // Called when the registration of Media Endpoint failed.
  void OnRegisterFailed(
      const device::BluetoothAudioSink::ErrorCallback& error_callback,
      const std::string& error_name,
      const std::string& error_message);

  // Called when the unregistration of Media Endpoint has succeeded. The
  // clean-up of media, media transport and media endpoint will be handled here.
  void OnUnregisterSucceeded(const base::Closure& callback);

  // Called when the unregistration of Media Endpoint failed.
  void OnUnregisterFailed(
      const device::BluetoothAudioSink::ErrorCallback& error_callback,
      const std::string& error_name,
      const std::string& error_message);

  // Called when the file descriptor, read MTU and write MTU are retrieved
  // successfully using |transport_path_|.
  void OnAcquireSucceeded(dbus::FileDescriptor* fd,
                          const uint16_t read_mtu,
                          const uint16_t write_mtu);

  // Called when acquiring the file descriptor, read MTU and write MTU failed.
  void OnAcquireFailed(const std::string& error_name,
                       const std::string& error_message);

  // Called when the file descriptor is released successfully.
  void OnReleaseFDSucceeded();

  // Called when it failed to release file descriptor.
  void OnReleaseFDFailed(const std::string& error_name,
                         const std::string& error_message);

  // Helper functions to clean up media, media transport and media endpoint.
  // Called when the |state_| changes to either STATE_INVALID or
  // STATE_DISCONNECTED.
  void ResetMedia();
  void ResetTransport();
  void ResetEndpoint();

  // The connection state between the BluetoothAudioSinkChromeOS and the remote
  // device.
  device::BluetoothAudioSink::State state_;

  // The volume control by the remote device during the streaming. The valid
  // range of volume is 0-127, and 128 is used to represent invalid volume.
  uint16_t volume_;

  // Read MTU of the file descriptor acquired via Media Transport object.
  uint16_t read_mtu_;

  // Write MTU of the file descriptor acquired via Media Transport object.
  uint16_t write_mtu_;

  // Flag for logging the read failure in ReadFromFD.
  bool read_has_failed_;

  // The file which takes ownership of the file descriptor acquired via Media
  // Transport object.
  scoped_ptr<base::File> file_;

  // To avoid reallocation of memory, data will be updated only when |read_mtu_|
  // changes.
  scoped_ptr<char[]> data_;

  // File descriptor watcher for the file descriptor acquired via Media
  // Transport object.
  base::MessageLoopForIO::FileDescriptorWatcher fd_read_watcher_;

  // Object path of the media object being used.
  dbus::ObjectPath media_path_;

  // Object path of the transport object being used.
  dbus::ObjectPath transport_path_;

  // Object path of the media endpoint object being used.
  dbus::ObjectPath endpoint_path_;

  // BT adapter which the audio sink binds to. |adapter_| should outlive
  // a BluetoothAudioSinkChromeOS object.
  scoped_refptr<device::BluetoothAdapter> adapter_;

  // Options used to initiate Media Endpoint and select configuration for the
  // transport.
  device::BluetoothAudioSink::Options options_;

  // Media Endpoint object owned by the audio sink object.
  scoped_ptr<bluez::BluetoothMediaEndpointServiceProvider> media_endpoint_;

  // List of observers interested in event notifications from us. Objects in
  // |observers_| are expected to outlive a BluetoothAudioSinkChromeOS object.
  base::ObserverList<BluetoothAudioSink::Observer> observers_;

  // 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<BluetoothAudioSinkChromeOS> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(BluetoothAudioSinkChromeOS);
};

}  // namespace chromeos

#endif  // DEVICE_BLUETOOTH_BLUETOOTH_AUDIO_SINK_CHROMEOS_H_