Home | History | Annotate | Download | only in dbus
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/weak_ptr.h"
      9 #include "base/observer_list.h"
     10 #include "dbus/bus.h"
     11 #include "dbus/object_manager.h"
     12 #include "third_party/cros_system_api/dbus/service_constants.h"
     13 
     14 namespace chromeos {
     15 
     16 namespace {
     17 
     18 // TODO(armansito): Move these to service_constants.h later.
     19 const char kNotifyingProperty[] = "Notifying";
     20 const char kStartNotify[] = "StartNotify";
     21 const char kStopNotify[] = "StopNotify";
     22 
     23 }  // namespace
     24 
     25 // static
     26 const char BluetoothGattCharacteristicClient::kNoResponseError[] =
     27     "org.chromium.Error.NoResponse";
     28 // static
     29 const char BluetoothGattCharacteristicClient::kUnknownCharacteristicError[] =
     30     "org.chromium.Error.UnknownCharacteristic";
     31 
     32 BluetoothGattCharacteristicClient::Properties::Properties(
     33     dbus::ObjectProxy* object_proxy,
     34     const std::string& interface_name,
     35     const PropertyChangedCallback& callback)
     36     : dbus::PropertySet(object_proxy, interface_name, callback) {
     37   RegisterProperty(bluetooth_gatt_characteristic::kUUIDProperty, &uuid);
     38   RegisterProperty(bluetooth_gatt_characteristic::kServiceProperty, &service);
     39   RegisterProperty(kNotifyingProperty, &notifying);
     40   RegisterProperty(bluetooth_gatt_characteristic::kFlagsProperty, &flags);
     41 }
     42 
     43 BluetoothGattCharacteristicClient::Properties::~Properties() {
     44 }
     45 
     46 // The BluetoothGattCharacteristicClient implementation used in production.
     47 class BluetoothGattCharacteristicClientImpl
     48     : public BluetoothGattCharacteristicClient,
     49       public dbus::ObjectManager::Interface {
     50  public:
     51   BluetoothGattCharacteristicClientImpl()
     52       : object_manager_(NULL),
     53         weak_ptr_factory_(this) {
     54   }
     55 
     56   virtual ~BluetoothGattCharacteristicClientImpl() {
     57     object_manager_->UnregisterInterface(
     58         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface);
     59   }
     60 
     61   // BluetoothGattCharacteristicClient override.
     62   virtual void AddObserver(
     63       BluetoothGattCharacteristicClient::Observer* observer) OVERRIDE {
     64     DCHECK(observer);
     65     observers_.AddObserver(observer);
     66   }
     67 
     68   // BluetoothGattCharacteristicClient override.
     69   virtual void RemoveObserver(
     70       BluetoothGattCharacteristicClient::Observer* observer) OVERRIDE {
     71     DCHECK(observer);
     72     observers_.RemoveObserver(observer);
     73   }
     74 
     75   // BluetoothGattCharacteristicClient override.
     76   virtual std::vector<dbus::ObjectPath> GetCharacteristics() OVERRIDE {
     77     DCHECK(object_manager_);
     78     return object_manager_->GetObjectsWithInterface(
     79         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface);
     80   }
     81 
     82   // BluetoothGattCharacteristicClient override.
     83   virtual Properties* GetProperties(
     84       const dbus::ObjectPath& object_path) OVERRIDE {
     85     DCHECK(object_manager_);
     86     return static_cast<Properties*>(
     87         object_manager_->GetProperties(
     88             object_path,
     89             bluetooth_gatt_characteristic::
     90                 kBluetoothGattCharacteristicInterface));
     91   }
     92 
     93   // BluetoothGattCharacteristicClient override.
     94   virtual void ReadValue(const dbus::ObjectPath& object_path,
     95                          const ValueCallback& callback,
     96                          const ErrorCallback& error_callback) OVERRIDE {
     97     dbus::ObjectProxy* object_proxy =
     98         object_manager_->GetObjectProxy(object_path);
     99     if (!object_proxy) {
    100       error_callback.Run(kUnknownCharacteristicError, "");
    101       return;
    102     }
    103 
    104     dbus::MethodCall method_call(
    105         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
    106         bluetooth_gatt_characteristic::kReadValue);
    107 
    108     object_proxy->CallMethodWithErrorCallback(
    109         &method_call,
    110         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    111         base::Bind(&BluetoothGattCharacteristicClientImpl::OnValueSuccess,
    112                    weak_ptr_factory_.GetWeakPtr(),
    113                    callback),
    114         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
    115                    weak_ptr_factory_.GetWeakPtr(),
    116                    error_callback));
    117   }
    118 
    119   // BluetoothGattCharacteristicClient override.
    120   virtual void WriteValue(const dbus::ObjectPath& object_path,
    121                           const std::vector<uint8>& value,
    122                           const base::Closure& callback,
    123                           const ErrorCallback& error_callback) OVERRIDE {
    124     dbus::ObjectProxy* object_proxy =
    125         object_manager_->GetObjectProxy(object_path);
    126     if (!object_proxy) {
    127       error_callback.Run(kUnknownCharacteristicError, "");
    128       return;
    129     }
    130 
    131     dbus::MethodCall method_call(
    132         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
    133         bluetooth_gatt_characteristic::kWriteValue);
    134     dbus::MessageWriter writer(&method_call);
    135     writer.AppendArrayOfBytes(value.data(), value.size());
    136 
    137     object_proxy->CallMethodWithErrorCallback(
    138         &method_call,
    139         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    140         base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess,
    141                    weak_ptr_factory_.GetWeakPtr(),
    142                    callback),
    143         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
    144                    weak_ptr_factory_.GetWeakPtr(),
    145                    error_callback));
    146   }
    147 
    148   // BluetoothGattCharacteristicClient override.
    149   virtual void StartNotify(const dbus::ObjectPath& object_path,
    150                            const base::Closure& callback,
    151                            const ErrorCallback& error_callback) OVERRIDE {
    152     dbus::ObjectProxy* object_proxy =
    153         object_manager_->GetObjectProxy(object_path);
    154     if (!object_proxy) {
    155       error_callback.Run(kUnknownCharacteristicError, "");
    156       return;
    157     }
    158 
    159     dbus::MethodCall method_call(
    160         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
    161         kStartNotify);
    162 
    163     object_proxy->CallMethodWithErrorCallback(
    164         &method_call,
    165         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    166         base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess,
    167                    weak_ptr_factory_.GetWeakPtr(),
    168                    callback),
    169         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
    170                    weak_ptr_factory_.GetWeakPtr(),
    171                    error_callback));
    172   }
    173 
    174   // BluetoothGattCharacteristicClient override.
    175   virtual void StopNotify(const dbus::ObjectPath& object_path,
    176                           const base::Closure& callback,
    177                           const ErrorCallback& error_callback) OVERRIDE {
    178     dbus::ObjectProxy* object_proxy =
    179         object_manager_->GetObjectProxy(object_path);
    180     if (!object_proxy) {
    181       error_callback.Run(kUnknownCharacteristicError, "");
    182       return;
    183     }
    184 
    185     dbus::MethodCall method_call(
    186         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
    187         kStopNotify);
    188 
    189     object_proxy->CallMethodWithErrorCallback(
    190         &method_call,
    191         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    192         base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess,
    193                    weak_ptr_factory_.GetWeakPtr(),
    194                    callback),
    195         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
    196                    weak_ptr_factory_.GetWeakPtr(),
    197                    error_callback));
    198   }
    199 
    200   // dbus::ObjectManager::Interface override.
    201   virtual dbus::PropertySet* CreateProperties(
    202       dbus::ObjectProxy *object_proxy,
    203       const dbus::ObjectPath& object_path,
    204       const std::string& interface_name) OVERRIDE {
    205     Properties* properties = new Properties(
    206         object_proxy,
    207         interface_name,
    208         base::Bind(&BluetoothGattCharacteristicClientImpl::OnPropertyChanged,
    209                    weak_ptr_factory_.GetWeakPtr(),
    210                    object_path));
    211     return static_cast<dbus::PropertySet*>(properties);
    212   }
    213 
    214   // dbus::ObjectManager::Interface override.
    215   virtual void ObjectAdded(const dbus::ObjectPath& object_path,
    216                            const std::string& interface_name) OVERRIDE {
    217     VLOG(2) << "Remote GATT characteristic added: " << object_path.value();
    218     FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
    219                       GattCharacteristicAdded(object_path));
    220 
    221     // Connect the "ValueUpdated" signal.
    222     dbus::ObjectProxy* object_proxy =
    223         object_manager_->GetObjectProxy(object_path);
    224     DCHECK(object_proxy);
    225 
    226     object_proxy->ConnectToSignal(
    227         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
    228         bluetooth_gatt_characteristic::kValueUpdatedSignal,
    229         base::Bind(&BluetoothGattCharacteristicClientImpl::ValueUpdatedReceived,
    230                    weak_ptr_factory_.GetWeakPtr(),
    231                    object_path),
    232         base::Bind(
    233             &BluetoothGattCharacteristicClientImpl::ValueUpdatedConnected,
    234             weak_ptr_factory_.GetWeakPtr()));
    235   }
    236 
    237   // dbus::ObjectManager::Interface override.
    238   virtual void ObjectRemoved(const dbus::ObjectPath& object_path,
    239                              const std::string& interface_name) OVERRIDE {
    240     VLOG(2) << "Remote GATT characteristic removed: " << object_path.value();
    241     FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
    242                       GattCharacteristicRemoved(object_path));
    243   }
    244 
    245  protected:
    246   // chromeos::DBusClient override.
    247   virtual void Init(dbus::Bus* bus) OVERRIDE {
    248     object_manager_ = bus->GetObjectManager(
    249         bluetooth_object_manager::kBluetoothObjectManagerServiceName,
    250         dbus::ObjectPath(
    251             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
    252     object_manager_->RegisterInterface(
    253         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
    254         this);
    255   }
    256 
    257  private:
    258   // Called by dbus::PropertySet when a property value is changed, either by
    259   // result of a signal or response to a GetAll() or Get() call. Informs
    260   // observers.
    261   virtual void OnPropertyChanged(const dbus::ObjectPath& object_path,
    262                                  const std::string& property_name) {
    263     VLOG(2) << "Remote GATT characteristic property changed: "
    264             << object_path.value() << ": " << property_name;
    265     FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
    266                       GattCharacteristicPropertyChanged(object_path,
    267                                                         property_name));
    268   }
    269 
    270   // Called by dbus:: when a "ValueUpdated" signal is received.
    271   void ValueUpdatedReceived(const dbus::ObjectPath& object_path,
    272                             dbus::Signal* signal) {
    273     DCHECK(signal);
    274     const uint8* bytes = NULL;
    275     size_t length = 0;
    276     dbus::MessageReader reader(signal);
    277     if (!reader.PopArrayOfBytes(&bytes, &length)) {
    278       LOG(WARNING) << "ValueUpdated signal has incorrect parameters: "
    279                    << signal->ToString();
    280       return;
    281     }
    282 
    283     std::vector<uint8> value;
    284     if (bytes)
    285       value.assign(bytes, bytes + length);
    286 
    287     FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer,
    288                       observers_,
    289                       GattCharacteristicValueUpdated(object_path, value));
    290   }
    291 
    292   // Called by dbus:: when the "ValueUpdated" signal is initially connected.
    293   void ValueUpdatedConnected(const std::string& interface_name,
    294                              const std::string& signal_name,
    295                              bool success) {
    296     LOG_IF(WARNING, !success) << "Failed to connect to the ValueUpdated signal";
    297   }
    298 
    299   // Called when a response for successful method call is received.
    300   void OnSuccess(const base::Closure& callback, dbus::Response* response) {
    301     DCHECK(response);
    302     callback.Run();
    303   }
    304 
    305   // Called when a characteristic value response for a successful method call
    306   // is received.
    307   void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) {
    308     DCHECK(response);
    309     dbus::MessageReader reader(response);
    310 
    311     const uint8* bytes = NULL;
    312     size_t length = 0;
    313 
    314     if (!reader.PopArrayOfBytes(&bytes, &length))
    315       VLOG(2) << "Error reading array of bytes in ValueCallback";
    316 
    317     std::vector<uint8> value;
    318 
    319     if (bytes)
    320       value.assign(bytes, bytes + length);
    321 
    322     callback.Run(value);
    323   }
    324 
    325   // Called when a response for a failed method call is received.
    326   void OnError(const ErrorCallback& error_callback,
    327                dbus::ErrorResponse* response) {
    328     // Error response has optional error message argument.
    329     std::string error_name;
    330     std::string error_message;
    331     if (response) {
    332       dbus::MessageReader reader(response);
    333       error_name = response->GetErrorName();
    334       reader.PopString(&error_message);
    335     } else {
    336       error_name = kNoResponseError;
    337       error_message = "";
    338     }
    339     error_callback.Run(error_name, error_message);
    340   }
    341 
    342   dbus::ObjectManager* object_manager_;
    343 
    344   // List of observers interested in event notifications from us.
    345   ObserverList<BluetoothGattCharacteristicClient::Observer> observers_;
    346 
    347   // Weak pointer factory for generating 'this' pointers that might live longer
    348   // than we do.
    349   // Note: This should remain the last member so it'll be destroyed and
    350   // invalidate its weak pointers before any other members are destroyed.
    351   base::WeakPtrFactory<BluetoothGattCharacteristicClientImpl>
    352       weak_ptr_factory_;
    353 
    354   DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClientImpl);
    355 };
    356 
    357 BluetoothGattCharacteristicClient::BluetoothGattCharacteristicClient() {
    358 }
    359 
    360 BluetoothGattCharacteristicClient::~BluetoothGattCharacteristicClient() {
    361 }
    362 
    363 // static
    364 BluetoothGattCharacteristicClient* BluetoothGattCharacteristicClient::Create() {
    365   return new BluetoothGattCharacteristicClientImpl();
    366 }
    367 
    368 }  // namespace chromeos
    369