OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chromeos/dbus/bluetooth_media_transport_client.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/ref_counted.h" | |
10 #include "base/observer_list.h" | |
11 #include "dbus/bus.h" | |
12 #include "dbus/message.h" | |
13 #include "dbus/object_manager.h" | |
14 #include "dbus/object_proxy.h" | |
15 #include "third_party/cros_system_api/dbus/service_constants.h" | |
16 | |
17 namespace { | |
18 | |
19 // TODO(mcchou): Add these service constants into dbus/service_constants.h | |
20 // later. | |
21 const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; | |
22 | |
23 // Constants used to indicate exceptional error conditions. | |
24 const char kNoResponseError[] = "org.chromium.Error.NoResponse"; | |
25 const char kUnexpectedResponse[] = "org.chromium.Error.UnexpectedResponse"; | |
26 | |
27 // Method names of Media Transport interface. | |
28 const char kAcquire[] = "Acquire"; | |
29 const char kTryAcquire[] = "TryAcquire"; | |
30 const char kRelease[] = "Release"; | |
31 | |
32 } // namespace | |
33 | |
34 namespace chromeos { | |
35 | |
36 // static | |
37 const char BluetoothMediaTransportClient::kDeviceProperty[] = "Device"; | |
38 const char BluetoothMediaTransportClient::kUUIDProperty[] = "UUID"; | |
39 const char BluetoothMediaTransportClient::kCodecProperty[] = "Codec"; | |
40 const char BluetoothMediaTransportClient::kConfigurationProperty[] = | |
41 "Configuration"; | |
42 const char BluetoothMediaTransportClient::kStateProperty[] = "State"; | |
43 const char BluetoothMediaTransportClient::kDelayProperty[] = "Delay"; | |
44 const char BluetoothMediaTransportClient::kVolumeProperty[] = "Volume"; | |
45 | |
46 // static | |
47 const char BluetoothMediaTransportClient::kStateIdle[] = "idle"; | |
48 const char BluetoothMediaTransportClient::kStatePending[] = "pending"; | |
49 const char BluetoothMediaTransportClient::kStateActive[] = "active"; | |
50 | |
51 BluetoothMediaTransportClient::Properties::Properties( | |
52 dbus::ObjectProxy* object_proxy, | |
53 const std::string& interface_name, | |
54 const PropertyChangedCallback& callback) | |
55 : dbus::PropertySet(object_proxy, interface_name, callback) { | |
56 RegisterProperty(kDeviceProperty, &device); | |
57 RegisterProperty(kUUIDProperty, &uuid); | |
58 RegisterProperty(kCodecProperty, &codec); | |
59 RegisterProperty(kConfigurationProperty, &configuration); | |
60 RegisterProperty(kStateProperty, &state); | |
61 RegisterProperty(kDelayProperty, &delay); | |
62 RegisterProperty(kVolumeProperty, &volume); | |
63 } | |
64 | |
65 BluetoothMediaTransportClient::Properties::~Properties() { | |
66 } | |
67 | |
68 class BluetoothMediaTransportClientImpl | |
69 : public BluetoothMediaTransportClient, | |
70 public dbus::ObjectManager::Interface { | |
71 public: | |
72 BluetoothMediaTransportClientImpl() | |
73 : object_manager_(nullptr), weak_ptr_factory_(this) {} | |
74 | |
75 ~BluetoothMediaTransportClientImpl() override { | |
76 object_manager_->UnregisterInterface(kBluetoothMediaTransportInterface); | |
77 } | |
78 | |
79 // dbus::ObjectManager::Interface overrides. | |
80 | |
81 dbus::PropertySet* CreateProperties( | |
82 dbus::ObjectProxy* object_proxy, | |
83 const dbus::ObjectPath& object_path, | |
84 const std::string& interface_name) override { | |
85 Properties* properties = new Properties( | |
86 object_proxy, | |
87 interface_name, | |
88 base::Bind(&BluetoothMediaTransportClientImpl::OnPropertyChanged, | |
89 weak_ptr_factory_.GetWeakPtr(), object_path)); | |
90 return properties; | |
91 } | |
92 | |
93 void ObjectAdded(const dbus::ObjectPath& object_path, | |
94 const std::string& interface_name) override { | |
95 VLOG(1) << "Remote Media Transport added: " << object_path.value(); | |
96 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, | |
97 observers_, | |
98 MediaTransportAdded(object_path)); | |
99 } | |
100 | |
101 void ObjectRemoved(const dbus::ObjectPath& object_path, | |
102 const std::string& interface_name) override { | |
103 VLOG(1) << "Remote Media Transport removed: " << object_path.value(); | |
104 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, | |
105 observers_, | |
106 MediaTransportRemoved(object_path)); | |
107 } | |
108 | |
109 // BluetoothMediaTransportClient overrides. | |
110 | |
111 void AddObserver(BluetoothMediaTransportClient::Observer* observer) override { | |
112 DCHECK(observer); | |
113 observers_.AddObserver(observer); | |
114 } | |
115 | |
116 void RemoveObserver( | |
117 BluetoothMediaTransportClient::Observer* observer) override { | |
118 DCHECK(observer); | |
119 observers_.RemoveObserver(observer); | |
120 } | |
121 | |
122 Properties* GetProperties(const dbus::ObjectPath& object_path) override { | |
123 DCHECK(object_manager_); | |
124 return static_cast<Properties*>( | |
125 object_manager_->GetProperties(object_path, | |
126 kBluetoothMediaTransportInterface)); | |
127 } | |
128 | |
129 void Acquire(const dbus::ObjectPath& object_path, | |
130 const AcquireCallback& callback, | |
131 const ErrorCallback& error_callback) override { | |
132 VLOG(1) << "Acquire - transport: " << object_path.value(); | |
133 | |
134 DCHECK(object_manager_); | |
135 | |
136 dbus::MethodCall method_call(kBluetoothMediaTransportInterface, kAcquire); | |
137 | |
138 // Get object proxy. | |
139 scoped_refptr<dbus::ObjectProxy> object_proxy( | |
140 object_manager_->GetObjectProxy(object_path)); | |
141 | |
142 // Call Acquire method of Media Transport interface. | |
143 object_proxy->CallMethodWithErrorCallback( | |
144 &method_call, | |
145 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
146 base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess, | |
147 weak_ptr_factory_.GetWeakPtr(), callback, error_callback), | |
148 base::Bind(&BluetoothMediaTransportClientImpl::OnError, | |
149 weak_ptr_factory_.GetWeakPtr(), error_callback)); | |
150 } | |
151 | |
152 void TryAcquire(const dbus::ObjectPath& object_path, | |
153 const AcquireCallback& callback, | |
154 const ErrorCallback& error_callback) override { | |
155 VLOG(1) << "TryAcquire - transport: " << object_path.value(); | |
156 | |
157 DCHECK(object_manager_); | |
158 | |
159 dbus::MethodCall method_call(kBluetoothMediaTransportInterface, | |
160 kTryAcquire); | |
161 | |
162 // Get object proxy. | |
163 scoped_refptr<dbus::ObjectProxy> object_proxy( | |
164 object_manager_->GetObjectProxy(object_path)); | |
165 | |
166 // Call TryAcquire method of Media Transport interface. | |
167 object_proxy->CallMethodWithErrorCallback( | |
168 &method_call, | |
169 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
170 base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess, | |
171 weak_ptr_factory_.GetWeakPtr(), callback, error_callback), | |
172 base::Bind(&BluetoothMediaTransportClientImpl::OnError, | |
173 weak_ptr_factory_.GetWeakPtr(), error_callback)); | |
174 } | |
175 | |
176 void Release(const dbus::ObjectPath& object_path, | |
177 const base::Closure& callback, | |
178 const ErrorCallback& error_callback) override { | |
179 VLOG(1) << "Release - transport: " << object_path.value(); | |
180 | |
181 DCHECK(object_manager_); | |
182 | |
183 dbus::MethodCall method_call(kBluetoothMediaTransportInterface, kRelease); | |
184 | |
185 // Get object proxy. | |
186 scoped_refptr<dbus::ObjectProxy> object_proxy( | |
187 object_manager_->GetObjectProxy(object_path)); | |
188 | |
189 // Call TryAcquire method of Media Transport interface. | |
190 object_proxy->CallMethodWithErrorCallback( | |
191 &method_call, | |
192 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
193 base::Bind(&BluetoothMediaTransportClientImpl::OnSuccess, | |
194 weak_ptr_factory_.GetWeakPtr(), callback), | |
195 base::Bind(&BluetoothMediaTransportClientImpl::OnError, | |
196 weak_ptr_factory_.GetWeakPtr(), error_callback)); | |
197 } | |
198 | |
199 protected: | |
200 void Init(dbus::Bus* bus) override { | |
201 DCHECK(bus); | |
202 object_manager_ = bus->GetObjectManager( | |
203 bluetooth_object_manager::kBluetoothObjectManagerServiceName, | |
204 dbus::ObjectPath( | |
205 bluetooth_object_manager::kBluetoothObjectManagerServicePath)); | |
206 object_manager_->RegisterInterface(kBluetoothMediaTransportInterface, | |
207 this); | |
208 } | |
209 | |
210 private: | |
211 // Called by dbus::PropertySet when a property value is changed. | |
212 void OnPropertyChanged(const dbus::ObjectPath& object_path, | |
213 const std::string& property_name) { | |
214 VLOG(1) << "Name of the changed property: " << property_name; | |
215 | |
216 // Dispatches the change to the corresponding property-changed handler. | |
217 FOR_EACH_OBSERVER( | |
218 BluetoothMediaTransportClient::Observer, observers_, | |
219 MediaTransportPropertyChanged(object_path, property_name)); | |
220 } | |
221 | |
222 // Called when a response for successful method call is received. | |
223 void OnSuccess(const base::Closure& callback, | |
224 dbus::Response* response) { | |
225 DCHECK(response); | |
226 callback.Run(); | |
227 } | |
228 | |
229 // Called when a response for |Acquire|/|TryAcquire| method call is received. | |
230 void OnAcquireSuccess(const AcquireCallback& callback, | |
231 const ErrorCallback& error_callback, | |
232 dbus::Response* response) { | |
233 DCHECK(response); | |
234 | |
235 dbus::FileDescriptor fd; | |
236 uint16_t read_mtu; | |
237 uint16_t write_mtu; | |
238 | |
239 // Parse the response. | |
240 dbus::MessageReader reader(response); | |
241 if (reader.PopFileDescriptor(&fd) && | |
242 reader.PopUint16(&read_mtu) && | |
243 reader.PopUint16(&write_mtu)) { | |
244 fd.CheckValidity(); | |
245 DCHECK(fd.is_valid()); | |
246 | |
247 VLOG(1) << "OnAcquireSuccess - fd: "<< fd.value() | |
248 <<", read MTU: " << read_mtu | |
249 <<", write MTU: " << write_mtu; | |
250 | |
251 // The ownership of the file descriptor is transferred to the user | |
252 // application. | |
253 callback.Run(&fd, read_mtu, write_mtu); | |
254 return; | |
255 } | |
256 | |
257 error_callback.Run( | |
258 kUnexpectedResponse, | |
259 "Failed to retrieve file descriptor, read MTU and write MTU."); | |
260 } | |
261 | |
262 // Called when a response for a failed method call is received. | |
263 void OnError(const ErrorCallback& error_callback, | |
264 dbus::ErrorResponse* response) { | |
265 DCHECK(response); | |
266 | |
267 // Error response has optional error message argument. | |
268 std::string error_name; | |
269 std::string error_message; | |
270 if (response) { | |
271 dbus::MessageReader reader(response); | |
272 error_name = response->GetErrorName(); | |
273 reader.PopString(&error_message); | |
274 } else { | |
275 error_name = kNoResponseError; | |
276 } | |
277 error_callback.Run(error_name, error_message); | |
278 } | |
279 | |
280 dbus::ObjectManager* object_manager_; | |
281 | |
282 // List of observers interested in event notifications from us. | |
283 base::ObserverList<BluetoothMediaTransportClient::Observer> observers_; | |
284 | |
285 base::WeakPtrFactory<BluetoothMediaTransportClientImpl> weak_ptr_factory_; | |
286 | |
287 DISALLOW_COPY_AND_ASSIGN(BluetoothMediaTransportClientImpl); | |
288 }; | |
289 | |
290 BluetoothMediaTransportClient::BluetoothMediaTransportClient() { | |
291 } | |
292 | |
293 BluetoothMediaTransportClient::~BluetoothMediaTransportClient() { | |
294 } | |
295 | |
296 BluetoothMediaTransportClient* BluetoothMediaTransportClient::Create() { | |
297 return new BluetoothMediaTransportClientImpl(); | |
298 } | |
299 | |
300 } // namespace chromeos | |
OLD | NEW |