bluetooth_device_chromeos.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1// Copyright 2013 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 "device/bluetooth/bluetooth_device_chromeos.h" 6 7#include <stdio.h> 8 9#include "base/bind.h" 10#include "base/metrics/histogram.h" 11#include "base/strings/string_number_conversions.h" 12#include "base/strings/string_util.h" 13#include "chromeos/dbus/bluetooth_adapter_client.h" 14#include "chromeos/dbus/bluetooth_device_client.h" 15#include "chromeos/dbus/bluetooth_gatt_service_client.h" 16#include "chromeos/dbus/bluetooth_input_client.h" 17#include "chromeos/dbus/dbus_thread_manager.h" 18#include "dbus/bus.h" 19#include "device/bluetooth/bluetooth_adapter_chromeos.h" 20#include "device/bluetooth/bluetooth_pairing_chromeos.h" 21#include "device/bluetooth/bluetooth_profile_chromeos.h" 22#include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h" 23#include "device/bluetooth/bluetooth_socket.h" 24#include "third_party/cros_system_api/dbus/service_constants.h" 25 26using device::BluetoothDevice; 27 28namespace { 29 30// Histogram enumerations for pairing results. 31enum UMAPairingResult { 32 UMA_PAIRING_RESULT_SUCCESS, 33 UMA_PAIRING_RESULT_INPROGRESS, 34 UMA_PAIRING_RESULT_FAILED, 35 UMA_PAIRING_RESULT_AUTH_FAILED, 36 UMA_PAIRING_RESULT_AUTH_CANCELED, 37 UMA_PAIRING_RESULT_AUTH_REJECTED, 38 UMA_PAIRING_RESULT_AUTH_TIMEOUT, 39 UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE, 40 UMA_PAIRING_RESULT_UNKNOWN_ERROR, 41 // NOTE: Add new pairing results immediately above this line. Make sure to 42 // update the enum list in tools/histogram/histograms.xml accordinly. 43 UMA_PAIRING_RESULT_COUNT 44}; 45 46void ParseModalias(const dbus::ObjectPath& object_path, 47 BluetoothDevice::VendorIDSource* vendor_id_source, 48 uint16* vendor_id, 49 uint16* product_id, 50 uint16* device_id) { 51 chromeos::BluetoothDeviceClient::Properties* properties = 52 chromeos::DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 53 GetProperties(object_path); 54 DCHECK(properties); 55 56 std::string modalias = properties->modalias.value(); 57 BluetoothDevice::VendorIDSource source_value; 58 int vendor_value, product_value, device_value; 59 60 if (sscanf(modalias.c_str(), "bluetooth:v%04xp%04xd%04x", 61 &vendor_value, &product_value, &device_value) == 3) { 62 source_value = BluetoothDevice::VENDOR_ID_BLUETOOTH; 63 } else if (sscanf(modalias.c_str(), "usb:v%04xp%04xd%04x", 64 &vendor_value, &product_value, &device_value) == 3) { 65 source_value = BluetoothDevice::VENDOR_ID_USB; 66 } else { 67 return; 68 } 69 70 if (vendor_id_source != NULL) 71 *vendor_id_source = source_value; 72 if (vendor_id != NULL) 73 *vendor_id = vendor_value; 74 if (product_id != NULL) 75 *product_id = product_value; 76 if (device_id != NULL) 77 *device_id = device_value; 78} 79 80void RecordPairingResult(BluetoothDevice::ConnectErrorCode error_code) { 81 UMAPairingResult pairing_result; 82 switch (error_code) { 83 case BluetoothDevice::ERROR_INPROGRESS: 84 pairing_result = UMA_PAIRING_RESULT_INPROGRESS; 85 break; 86 case BluetoothDevice::ERROR_FAILED: 87 pairing_result = UMA_PAIRING_RESULT_FAILED; 88 break; 89 case BluetoothDevice::ERROR_AUTH_FAILED: 90 pairing_result = UMA_PAIRING_RESULT_AUTH_FAILED; 91 break; 92 case BluetoothDevice::ERROR_AUTH_CANCELED: 93 pairing_result = UMA_PAIRING_RESULT_AUTH_CANCELED; 94 break; 95 case BluetoothDevice::ERROR_AUTH_REJECTED: 96 pairing_result = UMA_PAIRING_RESULT_AUTH_REJECTED; 97 break; 98 case BluetoothDevice::ERROR_AUTH_TIMEOUT: 99 pairing_result = UMA_PAIRING_RESULT_AUTH_TIMEOUT; 100 break; 101 case BluetoothDevice::ERROR_UNSUPPORTED_DEVICE: 102 pairing_result = UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE; 103 break; 104 default: 105 pairing_result = UMA_PAIRING_RESULT_UNKNOWN_ERROR; 106 } 107 108 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult", 109 pairing_result, 110 UMA_PAIRING_RESULT_COUNT); 111} 112 113} // namespace 114 115namespace chromeos { 116 117BluetoothDeviceChromeOS::BluetoothDeviceChromeOS( 118 BluetoothAdapterChromeOS* adapter, 119 const dbus::ObjectPath& object_path) 120 : adapter_(adapter), 121 object_path_(object_path), 122 num_connecting_calls_(0), 123 weak_ptr_factory_(this) { 124 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this); 125 126 // Add all known GATT services. 127 const std::vector<dbus::ObjectPath> gatt_services = 128 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetServices(); 129 for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin(); 130 it != gatt_services.end(); ++it) { 131 GattServiceAdded(*it); 132 } 133} 134 135BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { 136 DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> 137 RemoveObserver(this); 138 139 // Copy the GATT services list here and clear the original so that when we 140 // send GattServiceRemoved(), GetGattServices() returns no services. 141 GattServiceMap gatt_services = gatt_services_; 142 gatt_services_.clear(); 143 for (GattServiceMap::iterator iter = gatt_services.begin(); 144 iter != gatt_services.end(); ++iter) { 145 FOR_EACH_OBSERVER(BluetoothDevice::Observer, observers_, 146 GattServiceRemoved(this, iter->second)); 147 delete iter->second; 148 } 149} 150 151void BluetoothDeviceChromeOS::AddObserver( 152 device::BluetoothDevice::Observer* observer) { 153 DCHECK(observer); 154 observers_.AddObserver(observer); 155} 156 157void BluetoothDeviceChromeOS::RemoveObserver( 158 device::BluetoothDevice::Observer* observer) { 159 DCHECK(observer); 160 observers_.RemoveObserver(observer); 161} 162 163uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const { 164 BluetoothDeviceClient::Properties* properties = 165 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 166 GetProperties(object_path_); 167 DCHECK(properties); 168 169 return properties->bluetooth_class.value(); 170} 171 172std::string BluetoothDeviceChromeOS::GetDeviceName() const { 173 BluetoothDeviceClient::Properties* properties = 174 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 175 GetProperties(object_path_); 176 DCHECK(properties); 177 178 return properties->alias.value(); 179} 180 181std::string BluetoothDeviceChromeOS::GetAddress() const { 182 BluetoothDeviceClient::Properties* properties = 183 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 184 GetProperties(object_path_); 185 DCHECK(properties); 186 187 return properties->address.value(); 188} 189 190BluetoothDevice::VendorIDSource 191BluetoothDeviceChromeOS::GetVendorIDSource() const { 192 VendorIDSource vendor_id_source = VENDOR_ID_UNKNOWN; 193 ParseModalias(object_path_, &vendor_id_source, NULL, NULL, NULL); 194 return vendor_id_source; 195} 196 197uint16 BluetoothDeviceChromeOS::GetVendorID() const { 198 uint16 vendor_id = 0; 199 ParseModalias(object_path_, NULL, &vendor_id, NULL, NULL); 200 return vendor_id; 201} 202 203uint16 BluetoothDeviceChromeOS::GetProductID() const { 204 uint16 product_id = 0; 205 ParseModalias(object_path_, NULL, NULL, &product_id, NULL); 206 return product_id; 207} 208 209uint16 BluetoothDeviceChromeOS::GetDeviceID() const { 210 uint16 device_id = 0; 211 ParseModalias(object_path_, NULL, NULL, NULL, &device_id); 212 return device_id; 213} 214 215bool BluetoothDeviceChromeOS::IsPaired() const { 216 BluetoothDeviceClient::Properties* properties = 217 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 218 GetProperties(object_path_); 219 DCHECK(properties); 220 221 // Trusted devices are devices that don't support pairing but that the 222 // user has explicitly connected; it makes no sense for UI purposes to 223 // treat them differently from each other. 224 return properties->paired.value() || properties->trusted.value(); 225} 226 227bool BluetoothDeviceChromeOS::IsConnected() const { 228 BluetoothDeviceClient::Properties* properties = 229 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 230 GetProperties(object_path_); 231 DCHECK(properties); 232 233 return properties->connected.value(); 234} 235 236bool BluetoothDeviceChromeOS::IsConnectable() const { 237 BluetoothInputClient::Properties* input_properties = 238 DBusThreadManager::Get()->GetBluetoothInputClient()-> 239 GetProperties(object_path_); 240 // GetProperties returns NULL when the device does not implement the given 241 // interface. Non HID devices are normally connectable. 242 if (!input_properties) 243 return true; 244 245 return input_properties->reconnect_mode.value() != "device"; 246} 247 248bool BluetoothDeviceChromeOS::IsConnecting() const { 249 return num_connecting_calls_ > 0; 250} 251 252BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const { 253 BluetoothDeviceClient::Properties* properties = 254 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 255 GetProperties(object_path_); 256 DCHECK(properties); 257 258 std::vector<device::BluetoothUUID> uuids; 259 const std::vector<std::string> &dbus_uuids = properties->uuids.value(); 260 for (std::vector<std::string>::const_iterator iter = dbus_uuids.begin(); 261 iter != dbus_uuids.end(); ++iter) { 262 device::BluetoothUUID uuid(*iter); 263 DCHECK(uuid.IsValid()); 264 uuids.push_back(uuid); 265 } 266 return uuids; 267} 268 269bool BluetoothDeviceChromeOS::ExpectingPinCode() const { 270 return pairing_.get() && pairing_->ExpectingPinCode(); 271} 272 273bool BluetoothDeviceChromeOS::ExpectingPasskey() const { 274 return pairing_.get() && pairing_->ExpectingPasskey(); 275} 276 277bool BluetoothDeviceChromeOS::ExpectingConfirmation() const { 278 return pairing_.get() && pairing_->ExpectingConfirmation(); 279} 280 281void BluetoothDeviceChromeOS::Connect( 282 BluetoothDevice::PairingDelegate* pairing_delegate, 283 const base::Closure& callback, 284 const ConnectErrorCallback& error_callback) { 285 if (num_connecting_calls_++ == 0) 286 adapter_->NotifyDeviceChanged(this); 287 288 VLOG(1) << object_path_.value() << ": Connecting, " << num_connecting_calls_ 289 << " in progress"; 290 291 if (IsPaired() || !pairing_delegate || !IsPairable()) { 292 // No need to pair, or unable to, skip straight to connection. 293 ConnectInternal(false, callback, error_callback); 294 } else { 295 // Initiate high-security connection with pairing. 296 BeginPairing(pairing_delegate); 297 298 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 299 Pair(object_path_, 300 base::Bind(&BluetoothDeviceChromeOS::OnPair, 301 weak_ptr_factory_.GetWeakPtr(), 302 callback, error_callback), 303 base::Bind(&BluetoothDeviceChromeOS::OnPairError, 304 weak_ptr_factory_.GetWeakPtr(), 305 error_callback)); 306 } 307} 308 309void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) { 310 if (!pairing_.get()) 311 return; 312 313 pairing_->SetPinCode(pincode); 314} 315 316void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) { 317 if (!pairing_.get()) 318 return; 319 320 pairing_->SetPasskey(passkey); 321} 322 323void BluetoothDeviceChromeOS::ConfirmPairing() { 324 if (!pairing_.get()) 325 return; 326 327 pairing_->ConfirmPairing(); 328} 329 330void BluetoothDeviceChromeOS::RejectPairing() { 331 if (!pairing_.get()) 332 return; 333 334 pairing_->RejectPairing(); 335} 336 337void BluetoothDeviceChromeOS::CancelPairing() { 338 bool canceled = false; 339 340 // If there is a callback in progress that we can reply to then use that 341 // to cancel the current pairing request. 342 if (pairing_.get() && pairing_->CancelPairing()) 343 canceled = true; 344 345 // If not we have to send an explicit CancelPairing() to the device instead. 346 if (!canceled) { 347 VLOG(1) << object_path_.value() << ": No pairing context or callback. " 348 << "Sending explicit cancel"; 349 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 350 CancelPairing( 351 object_path_, 352 base::Bind(&base::DoNothing), 353 base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError, 354 weak_ptr_factory_.GetWeakPtr())); 355 } 356 357 // Since there is no callback to this method it's possible that the pairing 358 // delegate is going to be freed before things complete (indeed it's 359 // documented that this is the method you should call while freeing the 360 // pairing delegate), so clear our the context holding on to it. 361 EndPairing(); 362} 363 364void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback, 365 const ErrorCallback& error_callback) { 366 VLOG(1) << object_path_.value() << ": Disconnecting"; 367 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 368 Disconnect( 369 object_path_, 370 base::Bind(&BluetoothDeviceChromeOS::OnDisconnect, 371 weak_ptr_factory_.GetWeakPtr(), 372 callback), 373 base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError, 374 weak_ptr_factory_.GetWeakPtr(), 375 error_callback)); 376} 377 378void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) { 379 VLOG(1) << object_path_.value() << ": Removing device"; 380 DBusThreadManager::Get()->GetBluetoothAdapterClient()-> 381 RemoveDevice( 382 adapter_->object_path_, 383 object_path_, 384 base::Bind(&base::DoNothing), 385 base::Bind(&BluetoothDeviceChromeOS::OnForgetError, 386 weak_ptr_factory_.GetWeakPtr(), 387 error_callback)); 388} 389 390void BluetoothDeviceChromeOS::ConnectToService( 391 const device::BluetoothUUID& service_uuid, 392 const SocketCallback& callback) { 393 // TODO(keybuk): implement 394 callback.Run(scoped_refptr<device::BluetoothSocket>()); 395} 396 397void BluetoothDeviceChromeOS::ConnectToProfile( 398 device::BluetoothProfile* profile, 399 const base::Closure& callback, 400 const ConnectToProfileErrorCallback& error_callback) { 401 BluetoothProfileChromeOS* profile_chromeos = 402 static_cast<BluetoothProfileChromeOS*>(profile); 403 VLOG(1) << object_path_.value() << ": Connecting profile: " 404 << profile_chromeos->uuid().canonical_value(); 405 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 406 ConnectProfile( 407 object_path_, 408 profile_chromeos->uuid().canonical_value(), 409 base::Bind( 410 &BluetoothDeviceChromeOS::OnConnectProfile, 411 weak_ptr_factory_.GetWeakPtr(), 412 profile, 413 callback), 414 base::Bind( 415 &BluetoothDeviceChromeOS::OnConnectProfileError, 416 weak_ptr_factory_.GetWeakPtr(), 417 profile, 418 error_callback)); 419} 420 421void BluetoothDeviceChromeOS::SetOutOfBandPairingData( 422 const device::BluetoothOutOfBandPairingData& data, 423 const base::Closure& callback, 424 const ErrorCallback& error_callback) { 425 // TODO(keybuk): implement 426 error_callback.Run(); 427} 428 429void BluetoothDeviceChromeOS::ClearOutOfBandPairingData( 430 const base::Closure& callback, 431 const ErrorCallback& error_callback) { 432 // TODO(keybuk): implement 433 error_callback.Run(); 434} 435 436BluetoothPairingChromeOS* BluetoothDeviceChromeOS::BeginPairing( 437 BluetoothDevice::PairingDelegate* pairing_delegate) { 438 pairing_.reset(new BluetoothPairingChromeOS(this, pairing_delegate)); 439 return pairing_.get(); 440} 441 442void BluetoothDeviceChromeOS::EndPairing() { 443 pairing_.reset(); 444} 445 446BluetoothPairingChromeOS* BluetoothDeviceChromeOS::GetPairing() const { 447 return pairing_.get(); 448} 449 450void BluetoothDeviceChromeOS::GattServiceAdded( 451 const dbus::ObjectPath& object_path) { 452 if (GetGattService(object_path.value())) { 453 VLOG(1) << "Remote GATT service already exists: " << object_path.value(); 454 return; 455 } 456 457 BluetoothGattServiceClient::Properties* properties = 458 DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> 459 GetProperties(object_path); 460 DCHECK(properties); 461 if (properties->device.value() != object_path_) { 462 VLOG(2) << "Remote GATT service does not belong to this device."; 463 return; 464 } 465 466 VLOG(1) << "Adding new remote GATT service for device: " << GetAddress(); 467 468 BluetoothRemoteGattServiceChromeOS* service = 469 new BluetoothRemoteGattServiceChromeOS(this, object_path); 470 gatt_services_[service->GetIdentifier()] = service; 471 DCHECK(service->object_path() == object_path); 472 DCHECK(service->GetUUID().IsValid()); 473 474 FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_, 475 GattServiceAdded(this, service)); 476} 477 478void BluetoothDeviceChromeOS::GattServiceRemoved( 479 const dbus::ObjectPath& object_path) { 480 GattServiceMap::iterator iter = gatt_services_.find(object_path.value()); 481 if (iter == gatt_services_.end()) { 482 VLOG(2) << "Unknown GATT service removed: " << object_path.value(); 483 return; 484 } 485 486 VLOG(1) << "Removing remote GATT service from device: " << GetAddress(); 487 488 BluetoothRemoteGattServiceChromeOS* service = 489 static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second); 490 DCHECK(service->object_path() == object_path); 491 gatt_services_.erase(iter); 492 FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_, 493 GattServiceRemoved(this, service)); 494 delete service; 495} 496 497void BluetoothDeviceChromeOS::ConnectInternal( 498 bool after_pairing, 499 const base::Closure& callback, 500 const ConnectErrorCallback& error_callback) { 501 VLOG(1) << object_path_.value() << ": Connecting"; 502 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 503 Connect( 504 object_path_, 505 base::Bind(&BluetoothDeviceChromeOS::OnConnect, 506 weak_ptr_factory_.GetWeakPtr(), 507 after_pairing, 508 callback), 509 base::Bind(&BluetoothDeviceChromeOS::OnConnectError, 510 weak_ptr_factory_.GetWeakPtr(), 511 after_pairing, 512 error_callback)); 513} 514 515void BluetoothDeviceChromeOS::OnConnect(bool after_pairing, 516 const base::Closure& callback) { 517 if (--num_connecting_calls_ == 0) 518 adapter_->NotifyDeviceChanged(this); 519 520 DCHECK(num_connecting_calls_ >= 0); 521 VLOG(1) << object_path_.value() << ": Connected, " << num_connecting_calls_ 522 << " still in progress"; 523 524 SetTrusted(); 525 526 if (after_pairing) 527 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult", 528 UMA_PAIRING_RESULT_SUCCESS, 529 UMA_PAIRING_RESULT_COUNT); 530 531 callback.Run(); 532} 533 534void BluetoothDeviceChromeOS::OnConnectError( 535 bool after_pairing, 536 const ConnectErrorCallback& error_callback, 537 const std::string& error_name, 538 const std::string& error_message) { 539 if (--num_connecting_calls_ == 0) 540 adapter_->NotifyDeviceChanged(this); 541 542 DCHECK(num_connecting_calls_ >= 0); 543 LOG(WARNING) << object_path_.value() << ": Failed to connect device: " 544 << error_name << ": " << error_message; 545 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_ 546 << " still in progress"; 547 548 // Determine the error code from error_name. 549 ConnectErrorCode error_code = ERROR_UNKNOWN; 550 if (error_name == bluetooth_device::kErrorFailed) { 551 error_code = ERROR_FAILED; 552 } else if (error_name == bluetooth_device::kErrorInProgress) { 553 error_code = ERROR_INPROGRESS; 554 } else if (error_name == bluetooth_device::kErrorNotSupported) { 555 error_code = ERROR_UNSUPPORTED_DEVICE; 556 } 557 558 if (after_pairing) 559 RecordPairingResult(error_code); 560 error_callback.Run(error_code); 561} 562 563void BluetoothDeviceChromeOS::OnPair( 564 const base::Closure& callback, 565 const ConnectErrorCallback& error_callback) { 566 VLOG(1) << object_path_.value() << ": Paired"; 567 568 EndPairing(); 569 570 ConnectInternal(true, callback, error_callback); 571} 572 573void BluetoothDeviceChromeOS::OnPairError( 574 const ConnectErrorCallback& error_callback, 575 const std::string& error_name, 576 const std::string& error_message) { 577 if (--num_connecting_calls_ == 0) 578 adapter_->NotifyDeviceChanged(this); 579 580 DCHECK(num_connecting_calls_ >= 0); 581 LOG(WARNING) << object_path_.value() << ": Failed to pair device: " 582 << error_name << ": " << error_message; 583 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_ 584 << " still in progress"; 585 586 EndPairing(); 587 588 // Determine the error code from error_name. 589 ConnectErrorCode error_code = ERROR_UNKNOWN; 590 if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) { 591 error_code = ERROR_FAILED; 592 } else if (error_name == bluetooth_device::kErrorFailed) { 593 error_code = ERROR_FAILED; 594 } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) { 595 error_code = ERROR_AUTH_FAILED; 596 } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) { 597 error_code = ERROR_AUTH_CANCELED; 598 } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) { 599 error_code = ERROR_AUTH_REJECTED; 600 } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) { 601 error_code = ERROR_AUTH_TIMEOUT; 602 } 603 604 RecordPairingResult(error_code); 605 error_callback.Run(error_code); 606} 607 608void BluetoothDeviceChromeOS::OnCancelPairingError( 609 const std::string& error_name, 610 const std::string& error_message) { 611 LOG(WARNING) << object_path_.value() << ": Failed to cancel pairing: " 612 << error_name << ": " << error_message; 613} 614 615void BluetoothDeviceChromeOS::SetTrusted() { 616 // Unconditionally send the property change, rather than checking the value 617 // first; there's no harm in doing this and it solves any race conditions 618 // with the property becoming true or false and this call happening before 619 // we get the D-Bus signal about the earlier change. 620 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 621 GetProperties(object_path_)->trusted.Set( 622 true, 623 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted, 624 weak_ptr_factory_.GetWeakPtr())); 625} 626 627void BluetoothDeviceChromeOS::OnSetTrusted(bool success) { 628 LOG_IF(WARNING, !success) << object_path_.value() 629 << ": Failed to set device as trusted"; 630} 631 632void BluetoothDeviceChromeOS::OnDisconnect(const base::Closure& callback) { 633 VLOG(1) << object_path_.value() << ": Disconnected"; 634 callback.Run(); 635} 636 637void BluetoothDeviceChromeOS::OnDisconnectError( 638 const ErrorCallback& error_callback, 639 const std::string& error_name, 640 const std::string& error_message) { 641 LOG(WARNING) << object_path_.value() << ": Failed to disconnect device: " 642 << error_name << ": " << error_message; 643 error_callback.Run(); 644} 645 646void BluetoothDeviceChromeOS::OnForgetError( 647 const ErrorCallback& error_callback, 648 const std::string& error_name, 649 const std::string& error_message) { 650 LOG(WARNING) << object_path_.value() << ": Failed to remove device: " 651 << error_name << ": " << error_message; 652 error_callback.Run(); 653} 654 655void BluetoothDeviceChromeOS::OnConnectProfile( 656 device::BluetoothProfile* profile, 657 const base::Closure& callback) { 658 BluetoothProfileChromeOS* profile_chromeos = 659 static_cast<BluetoothProfileChromeOS*>(profile); 660 VLOG(1) << object_path_.value() << ": Profile connected: " 661 << profile_chromeos->uuid().canonical_value(); 662 callback.Run(); 663} 664 665void BluetoothDeviceChromeOS::OnConnectProfileError( 666 device::BluetoothProfile* profile, 667 const ConnectToProfileErrorCallback& error_callback, 668 const std::string& error_name, 669 const std::string& error_message) { 670 BluetoothProfileChromeOS* profile_chromeos = 671 static_cast<BluetoothProfileChromeOS*>(profile); 672 VLOG(1) << object_path_.value() << ": Profile connection failed: " 673 << profile_chromeos->uuid().canonical_value() << ": " 674 << error_name << ": " << error_message; 675 error_callback.Run(error_message); 676} 677 678} // namespace chromeos 679