Chromium Code Reviews| 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 | |
| 136 const ObjectPath& endpoint_path = GetEndpointPath(object_path); | |
| 137 Transport* transport = GetTransport(endpoint_path); | |
| 138 if (!transport) { | |
| 139 error_callback.Run(kFailed, ""); | |
| 140 return; | |
| 141 } | |
| 142 | |
| 143 std::string state = transport->properties->state.value(); | |
| 144 if (state == "active") { | |
| 145 error_callback.Run(kNotAuthorized, ""); | |
| 146 return; | |
| 147 } | |
| 148 if (state != "pending") { | |
| 149 error_callback.Run(kFailed, ""); | |
| 150 return; | |
| 151 } | |
| 152 | |
| 153 int fds[2]; | |
| 154 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { | |
| 155 transport->input_fd.reset(); | |
| 156 error_callback.Run(kFailed, ""); | |
| 157 return; | |
| 158 } | |
| 159 transport->input_fd.reset(new base::File(fds[0])); | |
| 160 | |
| 161 callback.Run(new dbus::FileDescriptor(fds[1]), kReadMtu, kWriteMtu); | |
| 162 SetState(endpoint_path, "active"); | |
| 126 } | 163 } |
| 127 | 164 |
| 128 void FakeBluetoothMediaTransportClient::TryAcquire( | 165 void FakeBluetoothMediaTransportClient::TryAcquire( |
| 129 const ObjectPath& object_path, | 166 const ObjectPath& object_path, |
| 130 const AcquireCallback& callback, | 167 const AcquireCallback& callback, |
| 131 const ErrorCallback& error_callback) { | 168 const ErrorCallback& error_callback) { |
| 132 error_callback.Run(kNotImplemented, ""); | 169 VLOG(1) << "TryAcquire - transport path: " << object_path.value(); |
| 170 | |
| 171 const ObjectPath& endpoint_path = GetEndpointPath(object_path); | |
| 172 Transport* transport = GetTransport(endpoint_path); | |
| 173 if (!transport) { | |
| 174 error_callback.Run(kFailed, ""); | |
| 175 return; | |
| 176 } | |
| 177 | |
| 178 std::string state = transport->properties->state.value(); | |
| 179 if (state == "active") { | |
| 180 error_callback.Run(kNotAuthorized, ""); | |
| 181 return; | |
| 182 } | |
| 183 | |
| 184 // NotAvailable error is an extra error type for TryAcquire. | |
| 185 if (state != "pending") { | |
| 186 error_callback.Run(kNotAvailable, ""); | |
| 187 return; | |
| 188 } | |
| 189 | |
| 190 int fds[2]; | |
| 191 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { | |
| 192 transport->input_fd.reset(); | |
| 193 error_callback.Run(kFailed, ""); | |
| 194 return; | |
| 195 } | |
| 196 DCHECK((fds[0] > kInvalidFd) && (fds[1] < kInvalidFd)); | |
| 197 transport->input_fd.reset(new base::File(fds[0])); | |
| 198 | |
| 199 callback.Run(new dbus::FileDescriptor(fds[1]), kReadMtu, kWriteMtu); | |
|
armansito
2015/03/13 00:00:31
You're potentially leaking memory here, don't do t
Miao
2015/03/13 00:41:41
Done.
| |
| 200 SetState(endpoint_path, "active"); | |
| 133 } | 201 } |
| 134 | 202 |
| 135 void FakeBluetoothMediaTransportClient::Release( | 203 void FakeBluetoothMediaTransportClient::Release( |
| 136 const ObjectPath& object_path, | 204 const ObjectPath& object_path, |
| 137 const base::Closure& callback, | 205 const base::Closure& callback, |
| 138 const ErrorCallback& error_callback) { | 206 const ErrorCallback& error_callback) { |
| 139 error_callback.Run(kNotImplemented, ""); | 207 error_callback.Run(kNotImplemented, ""); |
| 140 } | 208 } |
| 141 | 209 |
| 142 void FakeBluetoothMediaTransportClient::SetValid( | 210 void FakeBluetoothMediaTransportClient::SetValid( |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 167 properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); | 235 properties->state.ReplaceValue(BluetoothMediaTransportClient::kStateIdle); |
| 168 properties->delay.ReplaceValue(kTransportDelay); | 236 properties->delay.ReplaceValue(kTransportDelay); |
| 169 properties->volume.ReplaceValue(kTransportVolume); | 237 properties->volume.ReplaceValue(kTransportVolume); |
| 170 | 238 |
| 171 endpoint_to_transport_map_[endpoint_path] = | 239 endpoint_to_transport_map_[endpoint_path] = |
| 172 new Transport(transport_path, properties.release()); | 240 new Transport(transport_path, properties.release()); |
| 173 transport_to_endpoint_map_[transport_path] = endpoint_path; | 241 transport_to_endpoint_map_[transport_path] = endpoint_path; |
| 174 return; | 242 return; |
| 175 } | 243 } |
| 176 | 244 |
| 177 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 245 Transport* transport = GetTransport(endpoint_path); |
| 246 if (!transport) | |
| 178 return; | 247 return; |
| 248 ObjectPath transport_path = transport->path; | |
| 179 | 249 |
| 180 // Notifies observers about the state change of the transport. | 250 // Notifies observers about the state change of the transport. |
| 181 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 251 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
| 182 MediaTransportRemoved(GetTransportPath(endpoint_path))); | 252 MediaTransportRemoved(transport_path)); |
| 183 | 253 |
| 184 endpoint->ClearConfiguration(GetTransportPath(endpoint_path)); | 254 endpoint->ClearConfiguration(transport_path); |
| 185 transport_to_endpoint_map_.erase(GetTransportPath(endpoint_path)); | 255 delete transport; |
| 186 delete endpoint_to_transport_map_[endpoint_path]; | |
| 187 endpoint_to_transport_map_.erase(endpoint_path); | 256 endpoint_to_transport_map_.erase(endpoint_path); |
| 257 transport_to_endpoint_map_.erase(transport_path); | |
| 188 } | 258 } |
| 189 | 259 |
| 190 void FakeBluetoothMediaTransportClient::SetState( | 260 void FakeBluetoothMediaTransportClient::SetState( |
| 191 const dbus::ObjectPath& endpoint_path, | 261 const ObjectPath& endpoint_path, |
| 192 const std::string& state) { | 262 const std::string& state) { |
| 193 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 263 VLOG(1) << "SetState - state: " << state; |
| 264 | |
| 265 Transport* transport = GetTransport(endpoint_path); | |
| 266 if (!transport) | |
| 194 return; | 267 return; |
| 195 | 268 |
| 196 endpoint_to_transport_map_[endpoint_path] | 269 transport->properties->state.ReplaceValue(state); |
| 197 ->properties->state.ReplaceValue(state); | |
| 198 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 270 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
| 199 MediaTransportPropertyChanged( | 271 MediaTransportPropertyChanged( |
| 200 GetTransportPath(endpoint_path), | 272 transport->path, |
| 201 BluetoothMediaTransportClient::kStateProperty)); | 273 BluetoothMediaTransportClient::kStateProperty)); |
| 202 } | 274 } |
| 203 | 275 |
| 204 void FakeBluetoothMediaTransportClient::SetVolume( | 276 void FakeBluetoothMediaTransportClient::SetVolume( |
| 205 const dbus::ObjectPath& endpoint_path, | 277 const ObjectPath& endpoint_path, |
| 206 const uint16_t& volume) { | 278 const uint16_t& volume) { |
| 207 if (!ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 279 Transport* transport = GetTransport(endpoint_path); |
| 280 if (!transport) | |
| 208 return; | 281 return; |
| 209 | 282 |
| 210 endpoint_to_transport_map_[endpoint_path]->properties->volume.ReplaceValue( | 283 transport->properties->volume.ReplaceValue(volume); |
| 211 volume); | |
| 212 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, | 284 FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_, |
| 213 MediaTransportPropertyChanged( | 285 MediaTransportPropertyChanged( |
| 214 GetTransportPath(endpoint_path), | 286 transport->path, |
| 215 BluetoothMediaTransportClient::kVolumeProperty)); | 287 BluetoothMediaTransportClient::kVolumeProperty)); |
| 216 } | 288 } |
| 217 | 289 |
| 290 void FakeBluetoothMediaTransportClient::WriteData( | |
| 291 const ObjectPath& endpoint_path, const std::vector<char>& bytes) { | |
| 292 VLOG(1) << "WriteData - write " << bytes.size() << " bytes"; | |
| 293 | |
| 294 Transport* transport = GetTransport(endpoint_path); | |
| 295 | |
| 296 if (!transport || transport->properties->state.value() != "active") { | |
| 297 VLOG(1) << "WriteData - write operation rejected, since the state isn't " | |
| 298 "active for endpoint: " << endpoint_path.value(); | |
| 299 return; | |
| 300 } | |
| 301 | |
| 302 if (!transport->input_fd.get()) { | |
| 303 VLOG(1) << "WriteData - invalid input file descriptor"; | |
| 304 return; | |
| 305 } | |
| 306 | |
| 307 ssize_t written_len = | |
| 308 write(transport->input_fd->GetPlatformFile(), bytes.data(), bytes.size()); | |
| 309 if (written_len < 0) { | |
| 310 VLOG(1) << "WriteData - failed to write to the socket"; | |
| 311 return; | |
| 312 } | |
| 313 | |
| 314 VLOG(1) << "WriteData - wrote " << written_len << " bytes to the socket"; | |
| 315 } | |
| 316 | |
| 317 FakeBluetoothMediaTransportClient::Transport* | |
| 318 FakeBluetoothMediaTransportClient::GetTransport( | |
| 319 const ObjectPath& endpoint_path) { | |
| 320 const auto& it = endpoint_to_transport_map_.find(endpoint_path); | |
| 321 return (it != endpoint_to_transport_map_.end()) ? it->second : nullptr; | |
| 322 } | |
| 323 | |
| 324 | |
| 218 ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( | 325 ObjectPath FakeBluetoothMediaTransportClient::GetTransportPath( |
| 219 const ObjectPath& endpoint_path) { | 326 const ObjectPath& endpoint_path) { |
| 220 if (ContainsKey(endpoint_to_transport_map_, endpoint_path)) | 327 Transport* transport = GetTransport(endpoint_path); |
| 221 return endpoint_to_transport_map_[endpoint_path]->path; | 328 return transport ? transport->path : ObjectPath(""); |
| 222 return ObjectPath(""); | |
| 223 } | 329 } |
| 224 | 330 |
| 225 ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( | 331 ObjectPath FakeBluetoothMediaTransportClient::GetEndpointPath( |
| 226 const ObjectPath& transport_path) { | 332 const ObjectPath& transport_path) { |
| 227 if (ContainsKey(transport_to_endpoint_map_, transport_path)) | 333 const auto& it = transport_to_endpoint_map_.find(transport_path); |
| 228 return transport_to_endpoint_map_[transport_path]; | 334 return it != transport_to_endpoint_map_.end() ? it->second : ObjectPath(""); |
| 229 return ObjectPath(""); | |
| 230 } | 335 } |
| 231 | 336 |
| 232 void FakeBluetoothMediaTransportClient::OnPropertyChanged( | 337 void FakeBluetoothMediaTransportClient::OnPropertyChanged( |
| 233 const std::string& property_name) { | 338 const std::string& property_name) { |
| 234 VLOG(1) << "Property " << property_name << " changed"; | 339 VLOG(1) << "Property " << property_name << " changed"; |
| 235 } | 340 } |
| 236 | 341 |
| 237 } // namespace chromeos | 342 } // namespace chromeos |
| OLD | NEW |