OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/dbus/fake_bluetooth_media_transport_client.h" | 5 #include "chromeos/dbus/fake_bluetooth_media_transport_client.h" |
6 | 6 |
7 #include <unistd.h> | |
8 #include <sys/socket.h> | |
9 | |
7 #include <sstream> | 10 #include <sstream> |
8 | 11 |
9 #include "base/bind.h" | 12 #include "base/bind.h" |
10 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
11 #include "chromeos/dbus/bluetooth_media_client.h" | 14 #include "chromeos/dbus/bluetooth_media_client.h" |
12 #include "chromeos/dbus/dbus_thread_manager.h" | 15 #include "chromeos/dbus/dbus_thread_manager.h" |
13 #include "chromeos/dbus/fake_bluetooth_adapter_client.h" | 16 #include "chromeos/dbus/fake_bluetooth_adapter_client.h" |
14 #include "chromeos/dbus/fake_bluetooth_media_client.h" | 17 #include "chromeos/dbus/fake_bluetooth_media_client.h" |
15 #include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" | 18 #include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" |
16 | 19 |
17 using dbus::ObjectPath; | 20 using dbus::ObjectPath; |
18 | 21 |
19 namespace { | 22 namespace { |
20 | 23 |
21 // TODO(mcchou): Remove this constants once it is in cros_system_api. | 24 // TODO(mcchou): Remove this constants once it is in cros_system_api. |
22 const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; | 25 const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; |
23 const char kNotImplemented[] = "org.bluez.NotImplemented"; | 26 const char kNotImplemented[] = "org.bluez.NotImplemented"; |
27 const char kNotAuthorized[] = "org.bluez.NotAuthorized"; | |
28 const char kFailed[] = "org.bluez.Failed"; | |
29 const char kNotAvailable[] = "org.bluez.NotAvailable"; | |
30 | |
31 const uint16_t kReadMtu = 20; | |
32 const uint16_t kWriteMtu = 25; | |
24 | 33 |
25 ObjectPath GenerateTransportPath() { | 34 ObjectPath GenerateTransportPath() { |
26 static unsigned int sequence_number = 0; | 35 static unsigned int sequence_number = 0; |
27 ++sequence_number; | 36 ++sequence_number; |
28 std::stringstream path; | 37 std::stringstream path; |
29 path << chromeos::FakeBluetoothAdapterClient::kAdapterPath | 38 path << chromeos::FakeBluetoothAdapterClient::kAdapterPath |
30 << chromeos::FakeBluetoothMediaTransportClient::kTransportDevicePath | 39 << chromeos::FakeBluetoothMediaTransportClient::kTransportDevicePath |
31 << "/fd" << sequence_number; | 40 << "/fd" << sequence_number; |
32 return ObjectPath(path.str()); | 41 return ObjectPath(path.str()); |
33 } | 42 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 properties.reset(transport_properties); | 91 properties.reset(transport_properties); |
83 } | 92 } |
84 | 93 |
85 FakeBluetoothMediaTransportClient::Transport::~Transport() { | 94 FakeBluetoothMediaTransportClient::Transport::~Transport() { |
86 } | 95 } |
87 | 96 |
88 FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() { | 97 FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() { |
89 } | 98 } |
90 | 99 |
91 FakeBluetoothMediaTransportClient::~FakeBluetoothMediaTransportClient() { | 100 FakeBluetoothMediaTransportClient::~FakeBluetoothMediaTransportClient() { |
92 for (auto& it : endpoint_to_transport_map_) | 101 STLDeleteValues(&endpoint_to_transport_map_); |
93 delete it.second; | |
94 endpoint_to_transport_map_.clear(); | |
95 } | 102 } |
96 | 103 |
97 // DBusClient override. | 104 // DBusClient override. |
98 void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) { | 105 void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) { |
99 } | 106 } |
100 | 107 |
101 void FakeBluetoothMediaTransportClient::AddObserver( | 108 void FakeBluetoothMediaTransportClient::AddObserver( |
102 BluetoothMediaTransportClient::Observer* observer) { | 109 BluetoothMediaTransportClient::Observer* observer) { |
103 observers_.AddObserver(observer); | 110 observers_.AddObserver(observer); |
104 } | 111 } |
105 | 112 |
106 void FakeBluetoothMediaTransportClient::RemoveObserver( | 113 void FakeBluetoothMediaTransportClient::RemoveObserver( |
107 BluetoothMediaTransportClient::Observer* observer) { | 114 BluetoothMediaTransportClient::Observer* observer) { |
108 observers_.RemoveObserver(observer); | 115 observers_.RemoveObserver(observer); |
109 } | 116 } |
110 | 117 |
111 FakeBluetoothMediaTransportClient::Properties* | 118 FakeBluetoothMediaTransportClient::Properties* |
112 FakeBluetoothMediaTransportClient::GetProperties( | 119 FakeBluetoothMediaTransportClient::GetProperties( |
113 const ObjectPath& object_path) { | 120 const ObjectPath& object_path) { |
114 ObjectPath endpoint_path = GetEndpointPath(object_path); | 121 ObjectPath endpoint_path = GetEndpointPath(object_path); |
115 if (!endpoint_path.IsValid() || | 122 Transport* transport = GetTransport(endpoint_path); |
116 !ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 123 if (!transport) |
117 return nullptr; | 124 return nullptr; |
118 return endpoint_to_transport_map_[endpoint_path]->properties.get(); | 125 return transport->properties.get(); |
119 } | 126 } |
120 | 127 |
121 void FakeBluetoothMediaTransportClient::Acquire( | 128 void FakeBluetoothMediaTransportClient::Acquire( |
122 const ObjectPath& object_path, | 129 const ObjectPath& object_path, |
123 const AcquireCallback& callback, | 130 const AcquireCallback& callback, |
124 const ErrorCallback& error_callback) { | 131 const ErrorCallback& error_callback) { |
125 error_callback.Run(kNotImplemented, ""); | 132 VLOG(1) << "Acquire - transport path: " << object_path.value(); |
133 | |
134 ObjectPath endpoint_path = GetEndpointPath(object_path); | |
armansito
2015/03/12 03:42:54
const ObjectPath&
Miao
2015/03/12 22:33:31
Done.
| |
135 Transport* transport = GetTransport(endpoint_path); | |
136 if (!transport) { | |
137 error_callback.Run(kFailed, ""); | |
138 return; | |
139 } | |
140 | |
141 std::string state = transport->properties->state.value(); | |
142 if (state == "active") { | |
143 error_callback.Run(kNotAuthorized, ""); | |
144 return; | |
145 } | |
146 if (state != "pending") { | |
147 error_callback.Run(kFailed, ""); | |
148 return; | |
149 } | |
150 | |
151 int fds[2]; | |
152 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { | |
153 transport->input_fd.reset(); | |
154 error_callback.Run(kFailed, ""); | |
155 return; | |
156 } | |
armansito
2015/03/12 03:42:54
Maybe add a DCHECK here that both fds[0] and fd[1]
Miao
2015/03/12 22:33:31
Done.
| |
157 transport->input_fd.reset(new base::File(fds[0])); | |
158 | |
159 callback.Run(fds[1], kReadMtu, kWriteMtu); | |
160 SetState(endpoint_path, "active"); | |
126 } | 161 } |
127 | 162 |
128 void FakeBluetoothMediaTransportClient::TryAcquire( | 163 void FakeBluetoothMediaTransportClient::TryAcquire( |
129 const ObjectPath& object_path, | 164 const ObjectPath& object_path, |
130 const AcquireCallback& callback, | 165 const AcquireCallback& callback, |
131 const ErrorCallback& error_callback) { | 166 const ErrorCallback& error_callback) { |
132 error_callback.Run(kNotImplemented, ""); | 167 VLOG(1) << "TryAcquire - transport path: " << object_path.value(); |
168 | |
169 ObjectPath endpoint_path = GetEndpointPath(object_path); | |
armansito
2015/03/12 03:42:54
const ObjectPath&
Miao
2015/03/12 22:33:31
Done.
| |
170 Transport* transport = GetTransport(endpoint_path); | |
armansito
2015/03/12 03:42:54
Maybe you want a helper like "GetTransportByPath"
| |
171 if (!transport) { | |
172 error_callback.Run(kFailed, ""); | |
173 return; | |
174 } | |
175 | |
176 std::string state = transport->properties->state.value(); | |
177 if (state == "active") { | |
178 error_callback.Run(kNotAuthorized, ""); | |
179 return; | |
180 } | |
181 | |
182 // NotAvailable error is an extra error type for TryAcquire. | |
183 if (state != "pending") { | |
184 error_callback.Run(kNotAvailable, ""); | |
185 return; | |
186 } | |
187 | |
188 int fds[2]; | |
189 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { | |
190 transport->input_fd.reset(); | |
191 error_callback.Run(kFailed, ""); | |
192 return; | |
193 } | |
194 transport->input_fd.reset(new base::File(fds[0])); | |
195 | |
196 callback.Run(fds[1], kReadMtu, kWriteMtu); | |
197 SetState(endpoint_path, "active"); | |
armansito
2015/03/12 03:42:54
A lot of the code between TryAcquire and Acquire i
Miao
2015/03/12 22:33:31
Acquire and TryAcquire have different error messag
armansito
2015/03/12 23:59:07
I don't think that's a good enough excuse to have
| |
133 } | 198 } |
134 | 199 |
135 void FakeBluetoothMediaTransportClient::Release( | 200 void FakeBluetoothMediaTransportClient::Release( |
136 const ObjectPath& object_path, | 201 const ObjectPath& object_path, |
137 const base::Closure& callback, | 202 const base::Closure& callback, |
138 const ErrorCallback& error_callback) { | 203 const ErrorCallback& error_callback) { |
139 error_callback.Run(kNotImplemented, ""); | 204 error_callback.Run(kNotImplemented, ""); |
140 } | 205 } |
141 | 206 |
142 void FakeBluetoothMediaTransportClient::SetValid( | 207 void FakeBluetoothMediaTransportClient::SetValid( |
(...skipping 24 matching lines...) Expand all Loading... | |
167 properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); | 232 properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); |
168 properties->delay.ReplaceValue(kTransportDelay); | 233 properties->delay.ReplaceValue(kTransportDelay); |
169 properties->volume.ReplaceValue(kTransportVolume); | 234 properties->volume.ReplaceValue(kTransportVolume); |
170 | 235 |
171 endpoint_to_transport_map_[endpoint_path] = | 236 endpoint_to_transport_map_[endpoint_path] = |
172 new Transport(transport_path, properties.release()); | 237 new Transport(transport_path, properties.release()); |
173 transport_to_endpoint_map_[transport_path] = endpoint_path; | 238 transport_to_endpoint_map_[transport_path] = endpoint_path; |
174 return; | 239 return; |
175 } | 240 } |
176 | 241 |
177 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 242 Transport* transport = GetTransport(endpoint_path); |
243 if (!transport) | |
178 return; | 244 return; |
armansito
2015/03/12 03:42:54
nit: new line after 'return'
| |
245 ObjectPath transport_path = transport->path; | |
armansito
2015/03/12 03:42:54
const ObjectPath&
Miao
2015/03/12 22:33:31
Done.
| |
179 | 246 |
180 // Notifies observers about the state change of the transport. | 247 // Notifies observers about the state change of the transport. |
181 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 248 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
182 MediaTransportRemoved(GetTransportPath(endpoint_path))); | 249 MediaTransportRemoved(transport_path)); |
183 | 250 |
184 endpoint->ClearConfiguration(GetTransportPath(endpoint_path)); | 251 endpoint->ClearConfiguration(transport_path); |
185 transport_to_endpoint_map_.erase(GetTransportPath(endpoint_path)); | 252 delete transport; |
186 delete endpoint_to_transport_map_[endpoint_path]; | |
187 endpoint_to_transport_map_.erase(endpoint_path); | 253 endpoint_to_transport_map_.erase(endpoint_path); |
254 transport_to_endpoint_map_.erase(transport_path); | |
188 } | 255 } |
189 | 256 |
190 void FakeBluetoothMediaTransportClient::SetState( | 257 void FakeBluetoothMediaTransportClient::SetState( |
191 const dbus::ObjectPath& endpoint_path, | 258 const ObjectPath& endpoint_path, |
192 const std::string& state) { | 259 const std::string& state) { |
193 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 260 VLOG(1) << "SetState - state: " << state; |
261 | |
262 Transport* transport = GetTransport(endpoint_path); | |
263 if (!transport) | |
194 return; | 264 return; |
195 | 265 |
196 endpoint_to_transport_map_[endpoint_path] | 266 transport->properties->state.ReplaceValue(state); |
197 ->properties->state.ReplaceValue(state); | |
198 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 267 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
199 MediaTransportPropertyChanged( | 268 MediaTransportPropertyChanged( |
200 GetTransportPath(endpoint_path), | 269 transport->path, |
201 BluetoothMediaTransportClient::kStateProperty)); | 270 BluetoothMediaTransportClient::kStateProperty)); |
202 } | 271 } |
203 | 272 |
204 void FakeBluetoothMediaTransportClient::SetVolume( | 273 void FakeBluetoothMediaTransportClient::SetVolume( |
205 const dbus::ObjectPath& endpoint_path, | 274 const ObjectPath& endpoint_path, |
206 const uint16_t& volume) { | 275 const uint16_t& volume) { |
207 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 276 Transport* transport = GetTransport(endpoint_path); |
277 if (!transport) | |
208 return; | 278 return; |
209 | 279 |
210 endpoint_to_transport_map_[endpoint_path]->properties->volume.ReplaceValue( | 280 transport->properties->volume.ReplaceValue(volume); |
211 volume); | |
212 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 281 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
213 MediaTransportPropertyChanged( | 282 MediaTransportPropertyChanged( |
214 GetTransportPath(endpoint_path), | 283 transport->path, |
215 BluetoothMediaTransportClient::kVolumeProperty)); | 284 BluetoothMediaTransportClient::kVolumeProperty)); |
216 } | 285 } |
217 | 286 |
287 void FakeBluetoothMediaTransportClient::WriteData( | |
288 const ObjectPath& endpoint_path, const std::vector<char>& bytes) { | |
289 VLOG(1) << "WriteData"; | |
armansito
2015/03/12 03:42:54
Maybe log the number of bytes here? Might be usefu
Miao
2015/03/12 22:33:31
Done.
| |
290 | |
291 Transport* transport = GetTransport(endpoint_path); | |
292 | |
293 if (!transport || transport->properties->state.value() != "active") { | |
294 VLOG(1) << "WriteData - write operation rejected on endpoint: " | |
armansito
2015/03/12 03:42:54
You should probably log here that this was rejecte
Miao
2015/03/12 22:33:31
Done.
| |
295 << endpoint_path.value(); | |
296 return; | |
297 } | |
298 | |
299 if (!transport->input_fd.get()) { | |
300 VLOG(1) << "WriteData - invalid file descriptors"; | |
armansito
2015/03/12 03:42:54
nit: say "invalid input file descriptor"?
Miao
2015/03/12 22:33:31
Done.
| |
301 return; | |
302 } | |
303 | |
304 ssize_t written_len = | |
305 write(transport->input_fd->GetPlatformFile(), bytes.data(), bytes.size()); | |
armansito
2015/03/12 03:42:54
I wonder if you should prevent sending more bytes
Miao
2015/03/12 22:33:31
I'll keep this for now.
armansito
2015/03/12 23:59:07
sgtm
| |
306 if (written_len < 0) { | |
307 VLOG(1) << "WriteData - failed to write to the socket"; | |
308 return; | |
309 } | |
310 | |
311 VLOG(1) << "WriteData - wrote " << written_len << " bytes to the socket"; | |
312 } | |
313 | |
314 FakeBluetoothMediaTransportClient::Transport* | |
315 FakeBluetoothMediaTransportClient::GetTransport( | |
316 const ObjectPath& endpoint_path) { | |
317 auto it = endpoint_to_transport_map_.find(endpoint_path); | |
armansito
2015/03/12 03:42:54
const auto& it
Miao
2015/03/12 22:33:31
Done.
Miao
2015/03/12 22:33:31
Done.
| |
318 return (it != endpoint_to_transport_map_.end()) ? it->second : nullptr; | |
319 } | |
320 | |
321 | |
218 ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( | 322 ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( |
219 const ObjectPath& endpoint_path) { | 323 const ObjectPath& endpoint_path) { |
220 if (ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 324 Transport* transport = GetTransport(endpoint_path); |
221 return endpoint_to_transport_map_[endpoint_path]->path; | 325 return transport ? transport->path : ObjectPath(""); |
222 return ObjectPath(""); | |
223 } | 326 } |
224 | 327 |
225 ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( | 328 ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( |
226 const ObjectPath& transport_path) { | 329 const ObjectPath& transport_path) { |
227 if (ContainsKey(transport_to_endpoint_map_, transport_path)) | 330 auto it = transport_to_endpoint_map_.find(transport_path); |
armansito
2015/03/12 03:42:54
const auto& it
Miao
2015/03/12 22:33:31
Done.
| |
228 return transport_to_endpoint_map_[transport_path]; | 331 return it != transport_to_endpoint_map_.end() ? it->second : ObjectPath(""); |
229 return ObjectPath(""); | |
230 } | 332 } |
231 | 333 |
232 void FakeBluetoothMediaTransportClient::OnPropertyChanged( | 334 void FakeBluetoothMediaTransportClient::OnPropertyChanged( |
233 const std::string& property_name) { | 335 const std::string& property_name) { |
234 VLOG(1) << "Property " << property_name << " changed"; | 336 VLOG(1) << "Property " << property_name << " changed"; |
235 } | 337 } |
236 | 338 |
237 } // namespace chromeos | 339 } // namespace chromeos |
OLD | NEW |