Home | History | Annotate | Download | only in bluetooth
      1 // Copyright (c) 2012 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_adapter_win.h"
      6 
      7 #include <hash_set>
      8 #include <string>
      9 #include <utility>
     10 
     11 #include "base/logging.h"
     12 #include "base/sequenced_task_runner.h"
     13 #include "base/single_thread_task_runner.h"
     14 #include "base/stl_util.h"
     15 #include "base/thread_task_runner_handle.h"
     16 #include "device/bluetooth/bluetooth_device_win.h"
     17 #include "device/bluetooth/bluetooth_socket_thread.h"
     18 #include "device/bluetooth/bluetooth_socket_win.h"
     19 #include "device/bluetooth/bluetooth_task_manager_win.h"
     20 #include "device/bluetooth/bluetooth_uuid.h"
     21 
     22 namespace device {
     23 
     24 // static
     25 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
     26     const InitCallback& init_callback) {
     27   return BluetoothAdapterWin::CreateAdapter(init_callback);
     28 }
     29 
     30 // static
     31 base::WeakPtr<BluetoothAdapter> BluetoothAdapterWin::CreateAdapter(
     32     const InitCallback& init_callback) {
     33   BluetoothAdapterWin* adapter = new BluetoothAdapterWin(init_callback);
     34   adapter->Init();
     35   return adapter->weak_ptr_factory_.GetWeakPtr();
     36 }
     37 
     38 BluetoothAdapterWin::BluetoothAdapterWin(const InitCallback& init_callback)
     39     : BluetoothAdapter(),
     40       init_callback_(init_callback),
     41       initialized_(false),
     42       powered_(false),
     43       discovery_status_(NOT_DISCOVERING),
     44       num_discovery_listeners_(0),
     45       weak_ptr_factory_(this) {
     46 }
     47 
     48 BluetoothAdapterWin::~BluetoothAdapterWin() {
     49   if (task_manager_) {
     50     task_manager_->RemoveObserver(this);
     51     task_manager_->Shutdown();
     52   }
     53 }
     54 
     55 void BluetoothAdapterWin::AddObserver(BluetoothAdapter::Observer* observer) {
     56   DCHECK(observer);
     57   observers_.AddObserver(observer);
     58 }
     59 
     60 void BluetoothAdapterWin::RemoveObserver(BluetoothAdapter::Observer* observer) {
     61   DCHECK(observer);
     62   observers_.RemoveObserver(observer);
     63 }
     64 
     65 std::string BluetoothAdapterWin::GetAddress() const {
     66   return address_;
     67 }
     68 
     69 std::string BluetoothAdapterWin::GetName() const {
     70   return name_;
     71 }
     72 
     73 void BluetoothAdapterWin::SetName(const std::string& name,
     74                                   const base::Closure& callback,
     75                                   const ErrorCallback& error_callback) {
     76   NOTIMPLEMENTED();
     77 }
     78 
     79 // TODO(youngki): Return true when |task_manager_| initializes the adapter
     80 // state.
     81 bool BluetoothAdapterWin::IsInitialized() const {
     82   return initialized_;
     83 }
     84 
     85 bool BluetoothAdapterWin::IsPresent() const {
     86   return !address_.empty();
     87 }
     88 
     89 bool BluetoothAdapterWin::IsPowered() const {
     90   return powered_;
     91 }
     92 
     93 void BluetoothAdapterWin::SetPowered(
     94     bool powered,
     95     const base::Closure& callback,
     96     const ErrorCallback& error_callback) {
     97   task_manager_->PostSetPoweredBluetoothTask(powered, callback, error_callback);
     98 }
     99 
    100 bool BluetoothAdapterWin::IsDiscoverable() const {
    101   NOTIMPLEMENTED();
    102   return false;
    103 }
    104 
    105 void BluetoothAdapterWin::SetDiscoverable(
    106     bool discoverable,
    107     const base::Closure& callback,
    108     const ErrorCallback& error_callback) {
    109   NOTIMPLEMENTED();
    110 }
    111 
    112 bool BluetoothAdapterWin::IsDiscovering() const {
    113   return discovery_status_ == DISCOVERING ||
    114       discovery_status_ == DISCOVERY_STOPPING;
    115 }
    116 
    117 void BluetoothAdapterWin::DiscoveryStarted(bool success) {
    118   discovery_status_ = success ? DISCOVERING : NOT_DISCOVERING;
    119   for (std::vector<std::pair<base::Closure, ErrorCallback> >::const_iterator
    120        iter = on_start_discovery_callbacks_.begin();
    121        iter != on_start_discovery_callbacks_.end();
    122        ++iter) {
    123     if (success)
    124       ui_task_runner_->PostTask(FROM_HERE, iter->first);
    125     else
    126       ui_task_runner_->PostTask(FROM_HERE, iter->second);
    127   }
    128   num_discovery_listeners_ = on_start_discovery_callbacks_.size();
    129   on_start_discovery_callbacks_.clear();
    130 
    131   if (success) {
    132     FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
    133                       AdapterDiscoveringChanged(this, true));
    134 
    135     // If there are stop discovery requests, post the stop discovery again.
    136     MaybePostStopDiscoveryTask();
    137   } else if (!on_stop_discovery_callbacks_.empty()) {
    138     // If there are stop discovery requests but start discovery has failed,
    139     // notify that stop discovery has been complete.
    140     DiscoveryStopped();
    141   }
    142 }
    143 
    144 void BluetoothAdapterWin::DiscoveryStopped() {
    145   discovered_devices_.clear();
    146   bool was_discovering = IsDiscovering();
    147   discovery_status_ = NOT_DISCOVERING;
    148   for (std::vector<base::Closure>::const_iterator iter =
    149            on_stop_discovery_callbacks_.begin();
    150        iter != on_stop_discovery_callbacks_.end();
    151        ++iter) {
    152     ui_task_runner_->PostTask(FROM_HERE, *iter);
    153   }
    154   num_discovery_listeners_ = 0;
    155   on_stop_discovery_callbacks_.clear();
    156   if (was_discovering)
    157     FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
    158                       AdapterDiscoveringChanged(this, false));
    159 
    160   // If there are start discovery requests, post the start discovery again.
    161   MaybePostStartDiscoveryTask();
    162 }
    163 
    164 void BluetoothAdapterWin::CreateRfcommService(
    165     const BluetoothUUID& uuid,
    166     const ServiceOptions& options,
    167     const CreateServiceCallback& callback,
    168     const CreateServiceErrorCallback& error_callback) {
    169   scoped_refptr<BluetoothSocketWin> socket =
    170       BluetoothSocketWin::CreateBluetoothSocket(
    171           ui_task_runner_, socket_thread_);
    172   socket->Listen(this, uuid, options,
    173                  base::Bind(callback, socket),
    174                  error_callback);
    175 }
    176 
    177 void BluetoothAdapterWin::CreateL2capService(
    178     const BluetoothUUID& uuid,
    179     const ServiceOptions& options,
    180     const CreateServiceCallback& callback,
    181     const CreateServiceErrorCallback& error_callback) {
    182   // TODO(keybuk): implement.
    183   NOTIMPLEMENTED();
    184 }
    185 
    186 void BluetoothAdapterWin::RemovePairingDelegateInternal(
    187     BluetoothDevice::PairingDelegate* pairing_delegate) {
    188 }
    189 
    190 void BluetoothAdapterWin::AdapterStateChanged(
    191     const BluetoothTaskManagerWin::AdapterState& state) {
    192   DCHECK(thread_checker_.CalledOnValidThread());
    193   name_ = state.name;
    194   bool was_present = IsPresent();
    195   bool is_present = !state.address.empty();
    196   address_ = BluetoothDevice::CanonicalizeAddress(state.address);
    197   if (was_present != is_present) {
    198     FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
    199                       AdapterPresentChanged(this, is_present));
    200   }
    201   if (powered_ != state.powered) {
    202     powered_ = state.powered;
    203     FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
    204                       AdapterPoweredChanged(this, powered_));
    205   }
    206   if (!initialized_) {
    207     initialized_ = true;
    208     init_callback_.Run();
    209   }
    210 }
    211 
    212 void BluetoothAdapterWin::DevicesPolled(
    213     const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) {
    214   DCHECK(thread_checker_.CalledOnValidThread());
    215 
    216   // We are receiving a new list of all devices known to the system. Merge this
    217   // new list with the list we know of (|devices_|) and raise corresponding
    218   // DeviceAdded, DeviceRemoved and DeviceChanged events.
    219 
    220   typedef std::set<std::string> DeviceAddressSet;
    221   DeviceAddressSet known_devices;
    222   for (DevicesMap::const_iterator iter = devices_.begin();
    223        iter != devices_.end();
    224        ++iter) {
    225     known_devices.insert((*iter).first);
    226   }
    227 
    228   DeviceAddressSet new_devices;
    229   for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter =
    230            devices.begin();
    231        iter != devices.end();
    232        ++iter) {
    233     new_devices.insert((*iter)->address);
    234   }
    235 
    236   // Process device removal first
    237   DeviceAddressSet removed_devices =
    238       base::STLSetDifference<DeviceAddressSet>(known_devices, new_devices);
    239   for (DeviceAddressSet::const_iterator iter = removed_devices.begin();
    240        iter != removed_devices.end();
    241        ++iter) {
    242     BluetoothDevice* device_win = devices_[(*iter)];
    243     devices_.erase(*iter);
    244     FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
    245                       observers_,
    246                       DeviceRemoved(this, device_win));
    247     delete device_win;
    248   }
    249 
    250   // Process added and (maybe) changed devices in one pass
    251   DeviceAddressSet added_devices =
    252       base::STLSetDifference<DeviceAddressSet>(new_devices, known_devices);
    253   DeviceAddressSet changed_devices =
    254       base::STLSetIntersection<DeviceAddressSet>(known_devices, new_devices);
    255   for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter =
    256            devices.begin();
    257        iter != devices.end();
    258        ++iter) {
    259     BluetoothTaskManagerWin::DeviceState* device_state = (*iter);
    260     if (added_devices.find(device_state->address) != added_devices.end()) {
    261       BluetoothDeviceWin* device_win =
    262           new BluetoothDeviceWin(*device_state,
    263                                  ui_task_runner_,
    264                                  socket_thread_,
    265                                  NULL,
    266                                  net::NetLog::Source());
    267       devices_[device_state->address] = device_win;
    268       FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
    269                         observers_,
    270                         DeviceAdded(this, device_win));
    271     } else if (changed_devices.find(device_state->address) !=
    272                changed_devices.end()) {
    273       BluetoothDeviceWin* device_win =
    274           static_cast<BluetoothDeviceWin*>(devices_[device_state->address]);
    275       if (!device_win->IsEqual(*device_state)) {
    276         device_win->Update(*device_state);
    277         FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
    278                           observers_,
    279                           DeviceChanged(this, device_win));
    280       }
    281     }
    282   }
    283 }
    284 
    285 // If the method is called when |discovery_status_| is DISCOVERY_STOPPING,
    286 // starting again is handled by BluetoothAdapterWin::DiscoveryStopped().
    287 void BluetoothAdapterWin::AddDiscoverySession(
    288     const base::Closure& callback,
    289     const ErrorCallback& error_callback) {
    290   if (discovery_status_ == DISCOVERING) {
    291     num_discovery_listeners_++;
    292     callback.Run();
    293     return;
    294   }
    295   on_start_discovery_callbacks_.push_back(
    296       std::make_pair(callback, error_callback));
    297   MaybePostStartDiscoveryTask();
    298 }
    299 
    300 void BluetoothAdapterWin::RemoveDiscoverySession(
    301     const base::Closure& callback,
    302     const ErrorCallback& error_callback) {
    303   if (discovery_status_ == NOT_DISCOVERING) {
    304     error_callback.Run();
    305     return;
    306   }
    307   on_stop_discovery_callbacks_.push_back(callback);
    308   MaybePostStopDiscoveryTask();
    309 }
    310 
    311 void BluetoothAdapterWin::Init() {
    312   ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
    313   socket_thread_ = BluetoothSocketThread::Get();
    314   task_manager_ =
    315       new BluetoothTaskManagerWin(ui_task_runner_);
    316   task_manager_->AddObserver(this);
    317   task_manager_->Initialize();
    318 }
    319 
    320 void BluetoothAdapterWin::InitForTest(
    321     scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
    322     scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) {
    323   ui_task_runner_ = ui_task_runner;
    324   task_manager_ =
    325       new BluetoothTaskManagerWin(ui_task_runner_);
    326   task_manager_->AddObserver(this);
    327   task_manager_->InitializeWithBluetoothTaskRunner(bluetooth_task_runner);
    328 }
    329 
    330 void BluetoothAdapterWin::MaybePostStartDiscoveryTask() {
    331   if (discovery_status_ == NOT_DISCOVERING &&
    332       !on_start_discovery_callbacks_.empty()) {
    333     discovery_status_ = DISCOVERY_STARTING;
    334     task_manager_->PostStartDiscoveryTask();
    335   }
    336 }
    337 
    338 void BluetoothAdapterWin::MaybePostStopDiscoveryTask() {
    339   if (discovery_status_ != DISCOVERING)
    340     return;
    341 
    342   if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) {
    343     for (std::vector<base::Closure>::const_iterator iter =
    344              on_stop_discovery_callbacks_.begin();
    345          iter != on_stop_discovery_callbacks_.end();
    346          ++iter) {
    347       ui_task_runner_->PostTask(FROM_HERE, *iter);
    348     }
    349     num_discovery_listeners_ -= on_stop_discovery_callbacks_.size();
    350     on_stop_discovery_callbacks_.clear();
    351     return;
    352   }
    353 
    354   discovery_status_ = DISCOVERY_STOPPING;
    355   task_manager_->PostStopDiscoveryTask();
    356 }
    357 
    358 }  // namespace device
    359