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" |
| 19 #include "dbus/file_descriptor.h" |
16 | 20 |
17 using dbus::ObjectPath; | 21 using dbus::ObjectPath; |
18 | 22 |
19 namespace { | 23 namespace { |
20 | 24 |
21 // TODO(mcchou): Remove this constants once it is in cros_system_api. | 25 // TODO(mcchou): Remove this constants once it is in cros_system_api. |
22 const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; | 26 const char kBluetoothMediaTransportInterface[] = "org.bluez.MediaTransport1"; |
23 const char kNotImplemented[] = "org.bluez.NotImplemented"; | 27 const char kNotImplemented[] = "org.bluez.NotImplemented"; |
| 28 const char kNotAuthorized[] = "org.bluez.NotAuthorized"; |
| 29 const char kFailed[] = "org.bluez.Failed"; |
| 30 const char kNotAvailable[] = "org.bluez.NotAvailable"; |
| 31 |
| 32 const int kInvalidFd = -1; |
| 33 const uint16_t kReadMtu = 20; |
| 34 const uint16_t kWriteMtu = 25; |
24 | 35 |
25 ObjectPath GenerateTransportPath() { | 36 ObjectPath GenerateTransportPath() { |
26 static unsigned int sequence_number = 0; | 37 static unsigned int sequence_number = 0; |
27 ++sequence_number; | 38 ++sequence_number; |
28 std::stringstream path; | 39 std::stringstream path; |
29 path << chromeos::FakeBluetoothAdapterClient::kAdapterPath | 40 path << chromeos::FakeBluetoothAdapterClient::kAdapterPath |
30 << chromeos::FakeBluetoothMediaTransportClient::kTransportDevicePath | 41 << chromeos::FakeBluetoothMediaTransportClient::kTransportDevicePath |
31 << "/fd" << sequence_number; | 42 << "/fd" << sequence_number; |
32 return ObjectPath(path.str()); | 43 return ObjectPath(path.str()); |
33 } | 44 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 properties.reset(transport_properties); | 93 properties.reset(transport_properties); |
83 } | 94 } |
84 | 95 |
85 FakeBluetoothMediaTransportClient::Transport::~Transport() { | 96 FakeBluetoothMediaTransportClient::Transport::~Transport() { |
86 } | 97 } |
87 | 98 |
88 FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() { | 99 FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() { |
89 } | 100 } |
90 | 101 |
91 FakeBluetoothMediaTransportClient::~FakeBluetoothMediaTransportClient() { | 102 FakeBluetoothMediaTransportClient::~FakeBluetoothMediaTransportClient() { |
92 for (auto& it : endpoint_to_transport_map_) | 103 STLDeleteValues(&endpoint_to_transport_map_); |
93 delete it.second; | |
94 endpoint_to_transport_map_.clear(); | |
95 } | 104 } |
96 | 105 |
97 // DBusClient override. | 106 // DBusClient override. |
98 void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) { | 107 void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) { |
99 } | 108 } |
100 | 109 |
101 void FakeBluetoothMediaTransportClient::AddObserver( | 110 void FakeBluetoothMediaTransportClient::AddObserver( |
102 BluetoothMediaTransportClient::Observer* observer) { | 111 BluetoothMediaTransportClient::Observer* observer) { |
103 observers_.AddObserver(observer); | 112 observers_.AddObserver(observer); |
104 } | 113 } |
105 | 114 |
106 void FakeBluetoothMediaTransportClient::RemoveObserver( | 115 void FakeBluetoothMediaTransportClient::RemoveObserver( |
107 BluetoothMediaTransportClient::Observer* observer) { | 116 BluetoothMediaTransportClient::Observer* observer) { |
108 observers_.RemoveObserver(observer); | 117 observers_.RemoveObserver(observer); |
109 } | 118 } |
110 | 119 |
111 FakeBluetoothMediaTransportClient::Properties* | 120 FakeBluetoothMediaTransportClient::Properties* |
112 FakeBluetoothMediaTransportClient::GetProperties( | 121 FakeBluetoothMediaTransportClient::GetProperties( |
113 const ObjectPath& object_path) { | 122 const ObjectPath& object_path) { |
114 ObjectPath endpoint_path = GetEndpointPath(object_path); | 123 const ObjectPath& endpoint_path = GetEndpointPath(object_path); |
115 if (!endpoint_path.IsValid() || | 124 Transport* transport = GetTransport(endpoint_path); |
116 !ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 125 if (!transport) |
117 return nullptr; | 126 return nullptr; |
118 return endpoint_to_transport_map_[endpoint_path]->properties.get(); | 127 return transport->properties.get(); |
119 } | 128 } |
120 | 129 |
121 void FakeBluetoothMediaTransportClient::Acquire( | 130 void FakeBluetoothMediaTransportClient::Acquire( |
122 const ObjectPath& object_path, | 131 const ObjectPath& object_path, |
123 const AcquireCallback& callback, | 132 const AcquireCallback& callback, |
124 const ErrorCallback& error_callback) { | 133 const ErrorCallback& error_callback) { |
125 error_callback.Run(kNotImplemented, ""); | 134 VLOG(1) << "Acquire - transport path: " << object_path.value(); |
| 135 AcquireInternal(false, object_path, callback, error_callback); |
126 } | 136 } |
127 | 137 |
128 void FakeBluetoothMediaTransportClient::TryAcquire( | 138 void FakeBluetoothMediaTransportClient::TryAcquire( |
129 const ObjectPath& object_path, | 139 const ObjectPath& object_path, |
130 const AcquireCallback& callback, | 140 const AcquireCallback& callback, |
131 const ErrorCallback& error_callback) { | 141 const ErrorCallback& error_callback) { |
132 error_callback.Run(kNotImplemented, ""); | 142 VLOG(1) << "TryAcquire - transport path: " << object_path.value(); |
| 143 AcquireInternal(true, object_path, callback, error_callback); |
133 } | 144 } |
134 | 145 |
135 void FakeBluetoothMediaTransportClient::Release( | 146 void FakeBluetoothMediaTransportClient::Release( |
136 const ObjectPath& object_path, | 147 const ObjectPath& object_path, |
137 const base::Closure& callback, | 148 const base::Closure& callback, |
138 const ErrorCallback& error_callback) { | 149 const ErrorCallback& error_callback) { |
139 error_callback.Run(kNotImplemented, ""); | 150 error_callback.Run(kNotImplemented, ""); |
140 } | 151 } |
141 | 152 |
142 void FakeBluetoothMediaTransportClient::SetValid( | 153 void FakeBluetoothMediaTransportClient::SetValid( |
(...skipping 24 matching lines...) Expand all Loading... |
167 properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); | 178 properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); |
168 properties->delay.ReplaceValue(kTransportDelay); | 179 properties->delay.ReplaceValue(kTransportDelay); |
169 properties->volume.ReplaceValue(kTransportVolume); | 180 properties->volume.ReplaceValue(kTransportVolume); |
170 | 181 |
171 endpoint_to_transport_map_[endpoint_path] = | 182 endpoint_to_transport_map_[endpoint_path] = |
172 new Transport(transport_path, properties.release()); | 183 new Transport(transport_path, properties.release()); |
173 transport_to_endpoint_map_[transport_path] = endpoint_path; | 184 transport_to_endpoint_map_[transport_path] = endpoint_path; |
174 return; | 185 return; |
175 } | 186 } |
176 | 187 |
177 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 188 Transport* transport = GetTransport(endpoint_path); |
| 189 if (!transport) |
178 return; | 190 return; |
| 191 ObjectPath transport_path = transport->path; |
179 | 192 |
180 // Notifies observers about the state change of the transport. | 193 // Notifies observers about the state change of the transport. |
181 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 194 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
182 MediaTransportRemoved(GetTransportPath(endpoint_path))); | 195 MediaTransportRemoved(transport_path)); |
183 | 196 |
184 endpoint->ClearConfiguration(GetTransportPath(endpoint_path)); | 197 endpoint->ClearConfiguration(transport_path); |
185 transport_to_endpoint_map_.erase(GetTransportPath(endpoint_path)); | 198 delete transport; |
186 delete endpoint_to_transport_map_[endpoint_path]; | |
187 endpoint_to_transport_map_.erase(endpoint_path); | 199 endpoint_to_transport_map_.erase(endpoint_path); |
| 200 transport_to_endpoint_map_.erase(transport_path); |
188 } | 201 } |
189 | 202 |
190 void FakeBluetoothMediaTransportClient::SetState( | 203 void FakeBluetoothMediaTransportClient::SetState( |
191 const dbus::ObjectPath& endpoint_path, | 204 const ObjectPath& endpoint_path, |
192 const std::string& state) { | 205 const std::string& state) { |
193 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 206 VLOG(1) << "SetState - state: " << state; |
| 207 |
| 208 Transport* transport = GetTransport(endpoint_path); |
| 209 if (!transport) |
194 return; | 210 return; |
195 | 211 |
196 endpoint_to_transport_map_[endpoint_path] | 212 transport->properties->state.ReplaceValue(state); |
197 ->properties->state.ReplaceValue(state); | |
198 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 213 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
199 MediaTransportPropertyChanged( | 214 MediaTransportPropertyChanged( |
200 GetTransportPath(endpoint_path), | 215 transport->path, |
201 BluetoothMediaTransportClient::kStateProperty)); | 216 BluetoothMediaTransportClient::kStateProperty)); |
202 } | 217 } |
203 | 218 |
204 void FakeBluetoothMediaTransportClient::SetVolume( | 219 void FakeBluetoothMediaTransportClient::SetVolume( |
205 const dbus::ObjectPath& endpoint_path, | 220 const ObjectPath& endpoint_path, |
206 const uint16_t& volume) { | 221 const uint16_t& volume) { |
207 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 222 Transport* transport = GetTransport(endpoint_path); |
| 223 if (!transport) |
208 return; | 224 return; |
209 | 225 |
210 endpoint_to_transport_map_[endpoint_path]->properties->volume.ReplaceValue( | 226 transport->properties->volume.ReplaceValue(volume); |
211 volume); | |
212 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 227 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
213 MediaTransportPropertyChanged( | 228 MediaTransportPropertyChanged( |
214 GetTransportPath(endpoint_path), | 229 transport->path, |
215 BluetoothMediaTransportClient::kVolumeProperty)); | 230 BluetoothMediaTransportClient::kVolumeProperty)); |
216 } | 231 } |
217 | 232 |
| 233 void FakeBluetoothMediaTransportClient::WriteData( |
| 234 const ObjectPath& endpoint_path, const std::vector<char>& bytes) { |
| 235 VLOG(1) << "WriteData - write " << bytes.size() << " bytes"; |
| 236 |
| 237 Transport* transport = GetTransport(endpoint_path); |
| 238 |
| 239 if (!transport || transport->properties->state.value() != "active") { |
| 240 VLOG(1) << "WriteData - write operation rejected, since the state isn't " |
| 241 "active for endpoint: " << endpoint_path.value(); |
| 242 return; |
| 243 } |
| 244 |
| 245 if (!transport->input_fd.get()) { |
| 246 VLOG(1) << "WriteData - invalid input file descriptor"; |
| 247 return; |
| 248 } |
| 249 |
| 250 ssize_t written_len = |
| 251 write(transport->input_fd->GetPlatformFile(), bytes.data(), bytes.size()); |
| 252 if (written_len < 0) { |
| 253 VLOG(1) << "WriteData - failed to write to the socket"; |
| 254 return; |
| 255 } |
| 256 |
| 257 VLOG(1) << "WriteData - wrote " << written_len << " bytes to the socket"; |
| 258 } |
| 259 |
218 ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( | 260 ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( |
219 const ObjectPath& endpoint_path) { | 261 const ObjectPath& endpoint_path) { |
220 if (ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 262 Transport* transport = GetTransport(endpoint_path); |
221 return endpoint_to_transport_map_[endpoint_path]->path; | 263 return transport ? transport->path : ObjectPath(""); |
222 return ObjectPath(""); | |
223 } | |
224 | |
225 ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( | |
226 const ObjectPath& transport_path) { | |
227 if (ContainsKey(transport_to_endpoint_map_, transport_path)) | |
228 return transport_to_endpoint_map_[transport_path]; | |
229 return ObjectPath(""); | |
230 } | 264 } |
231 | 265 |
232 void FakeBluetoothMediaTransportClient::OnPropertyChanged( | 266 void FakeBluetoothMediaTransportClient::OnPropertyChanged( |
233 const std::string& property_name) { | 267 const std::string& property_name) { |
234 VLOG(1) << "Property " << property_name << " changed"; | 268 VLOG(1) << "Property " << property_name << " changed"; |
235 } | 269 } |
236 | 270 |
| 271 ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( |
| 272 const ObjectPath& transport_path) { |
| 273 const auto& it = transport_to_endpoint_map_.find(transport_path); |
| 274 return it != transport_to_endpoint_map_.end() ? it->second : ObjectPath(""); |
| 275 } |
| 276 |
| 277 FakeBluetoothMediaTransportClient::Transport* |
| 278 FakeBluetoothMediaTransportClient::GetTransport( |
| 279 const ObjectPath& endpoint_path) { |
| 280 const auto& it = endpoint_to_transport_map_.find(endpoint_path); |
| 281 return (it != endpoint_to_transport_map_.end()) ? it->second : nullptr; |
| 282 } |
| 283 |
| 284 FakeBluetoothMediaTransportClient::Transport* |
| 285 FakeBluetoothMediaTransportClient::GetTransportByPath( |
| 286 const dbus::ObjectPath& transport_path) { |
| 287 return GetTransport(GetEndpointPath(transport_path)); |
| 288 } |
| 289 |
| 290 void FakeBluetoothMediaTransportClient::AcquireInternal( |
| 291 bool try_flag, |
| 292 const ObjectPath& object_path, |
| 293 const AcquireCallback& callback, |
| 294 const ErrorCallback& error_callback) { |
| 295 const ObjectPath& endpoint_path = GetEndpointPath(object_path); |
| 296 Transport* transport = GetTransport(endpoint_path); |
| 297 if (!transport) { |
| 298 error_callback.Run(kFailed, ""); |
| 299 return; |
| 300 } |
| 301 |
| 302 std::string state = transport->properties->state.value(); |
| 303 if (state == "active") { |
| 304 error_callback.Run(kNotAuthorized, ""); |
| 305 return; |
| 306 } |
| 307 if (state != "pending") { |
| 308 error_callback.Run(try_flag ? kNotAvailable : kFailed, ""); |
| 309 return; |
| 310 } |
| 311 |
| 312 int fds[2]; |
| 313 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { |
| 314 transport->input_fd.reset(); |
| 315 error_callback.Run(kFailed, ""); |
| 316 return; |
| 317 } |
| 318 DCHECK((fds[0] > kInvalidFd) && (fds[1] > kInvalidFd)); |
| 319 transport->input_fd.reset(new base::File(fds[0])); |
| 320 |
| 321 dbus::FileDescriptor out_fd(fds[1]); |
| 322 callback.Run(&out_fd, kReadMtu, kWriteMtu); |
| 323 SetState(endpoint_path, "active"); |
| 324 } |
| 325 |
237 } // namespace chromeos | 326 } // namespace chromeos |
OLD | NEW |