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