Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3f6b33a authored by Arman Uguray's avatar Arman Uguray
Browse files

service: Implement IBluetoothLowEnergy client registration

This CL adds support for the IBluetoothLowEnergy registerClient and
unregisterClient methods. A lot of the code added here deals with
asynchronous callback registration and can be generalized to other
interfaces that asynchronously associate and return client
interface IDs with callback binders.

Bug: 23793954
Change-Id: I82cf26e194c456f04363fe66f094bc803a5aa436
parent 75dd72d4
Loading
Loading
Loading
Loading
+105 −6
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#include <base/logging.h>

#include "service/adapter.h"

namespace ipc {
namespace binder {

@@ -32,20 +34,117 @@ BluetoothLowEnergyBinderServer::~BluetoothLowEnergyBinderServer() {
void BluetoothLowEnergyBinderServer::RegisterClient(
    const android::sp<IBluetoothLowEnergyCallback>& callback) {
  VLOG(2) << __func__;
  // TODO(armansito): Implement
  LOG(WARNING) << "Not implemented";
  if (!callback.get()) {
    LOG(ERROR) << "Cannot register a NULL callback";
    return;
  }

  bluetooth::LowEnergyClientFactory* ble_factory =
      adapter_->GetLowEnergyClientFactory();

  // Store the callback in the pending list. It will get removed later when the
  // stack notifies us asynchronously.
  bluetooth::UUID app_uuid = bluetooth::UUID::GetRandom();
  if (!pending_callbacks_.Register(app_uuid, callback)) {
    LOG(ERROR) << "Failed to store |callback| to map";
    return;
  }

  // Create a weak pointer and pass that to the callback to prevent an invalid
  // access later. Since this object is managed using Android's StrongPointer
  // (sp) we are using a wp here rather than std::weak_ptr.
  android::wp<BluetoothLowEnergyBinderServer> weak_ptr_to_this(this);

  bluetooth::LowEnergyClientFactory::ClientCallback client_cb =
      [weak_ptr_to_this](bluetooth::BLEStatus status,
                         const bluetooth::UUID& in_uuid,
                         std::unique_ptr<bluetooth::LowEnergyClient> client) {
        // If the weak pointer was invalidated then there's nothing we can do.
        android::sp<BluetoothLowEnergyBinderServer> strong_ptr_to_this =
            weak_ptr_to_this.promote();
        if (!strong_ptr_to_this.get()) {
          VLOG(2) << "BluetoothLowEnergyBinderServer was deleted before "
                  << "callback was registered";
          return;
        }

        strong_ptr_to_this->OnRegisterClient(
            status, in_uuid, std::move(client));
      };

  if (ble_factory->RegisterClient(app_uuid, client_cb))
    return;

  LOG(ERROR) << "Failed to register client";
  pending_callbacks_.Remove(app_uuid);
}

void BluetoothLowEnergyBinderServer::UnregisterClient(int client_if) {
  VLOG(2) << __func__;
  // TODO(armansito): Implement
  LOG(WARNING) << "Not implemented";
  std::lock_guard<std::mutex> lock(maps_lock_);

  cif_to_cb_.Remove(client_if);
  cif_to_client_.erase(client_if);
}

void BluetoothLowEnergyBinderServer::UnregisterAll() {
  VLOG(2) << __func__;
  // TODO(armansito): Implement
  LOG(WARNING) << "Not implemented";
  std::lock_guard<std::mutex> lock(maps_lock_);

  cif_to_cb_.Clear();
  cif_to_client_.clear();
}

void BluetoothLowEnergyBinderServer::OnRemoteCallbackRemoved(const int& key) {
  VLOG(2) << __func__ << " client_if: " << key;
  std::lock_guard<std::mutex> lock(maps_lock_);

  // No need to remove from the callback map as the entry should be already
  // removed when this callback gets called.
  cif_to_client_.erase(key);
}

void BluetoothLowEnergyBinderServer::OnRegisterClient(
    bluetooth::BLEStatus status,
    const bluetooth::UUID& uuid,
    std::unique_ptr<bluetooth::LowEnergyClient> client) {
  VLOG(2) << __func__ << " - status: " << status;

  // Simply remove the callback from |pending_callbacks_| as it no longer
  // belongs in there.
  sp<IBluetoothLowEnergyCallback> callback = pending_callbacks_.Remove(uuid);

  // |callback| might be NULL if it was removed from the pending list, e.g.
  // because the remote process that owns the callback died.
  if (!callback.get()) {
    VLOG(1) << "Callback was removed before the call to \"RegisterClient\" "
            << "returned; unregistering client";
    // Simply return here. |client| will unregister itself when it goes out of
    // scope.
    return;
  }

  if (status != bluetooth::BLE_STATUS_SUCCESS) {
    // The call wasn't successful. Log and return.
    LOG(ERROR) << "Failed to register Low Energy client: " << status;
    return;
  }

  std::lock_guard<std::mutex> lock(maps_lock_);
  CHECK(client->client_if());
  int client_if = client->client_if();
  if (!cif_to_cb_.Register(client_if, callback, this)) {
    LOG(ERROR) << "Failed to store callback";
    return;
  }

  VLOG(1) << "Registered BluetoothLowEnergy client: " << client_if;

  cif_to_client_[client_if] =
      std::shared_ptr<bluetooth::LowEnergyClient>(client.release());

  // Notify the client.
  callback->OnClientRegistered(static_cast<int>(status), client_if);
}

}  // namespace binder
+30 −1
Original line number Diff line number Diff line
@@ -16,10 +16,17 @@

#pragma once

#include <memory>
#include <unordered_map>

#include <base/macros.h>

#include "service/ipc/binder/IBluetoothLowEnergy.h"
#include "service/ipc/binder/IBluetoothLowEnergyCallback.h"
#include "service/ipc/binder/remote_callback_map.h"
#include "service/low_energy_client.h"
#include "service/low_energy_constants.h"
#include "service/uuid.h"

namespace bluetooth {
class Adapter;
@@ -29,7 +36,9 @@ namespace ipc {
namespace binder {

// Implements the server side of the IBluetoothLowEnergy interface.
class BluetoothLowEnergyBinderServer : public BnBluetoothLowEnergy {
class BluetoothLowEnergyBinderServer
    : public BnBluetoothLowEnergy,
      public RemoteCallbackMap<int, IBluetoothLowEnergyCallback>::Delegate {
 public:
  explicit BluetoothLowEnergyBinderServer(bluetooth::Adapter* adapter);
  ~BluetoothLowEnergyBinderServer() override;
@@ -41,8 +50,28 @@ class BluetoothLowEnergyBinderServer : public BnBluetoothLowEnergy {
  void UnregisterAll() override;

 private:
  // RemoteCallbackMap<int, IBluetoothLowEnergyCallback>::Delegate override:
  void OnRemoteCallbackRemoved(const int& key) override;

  // Called as a result of bluetooth::LowEnergyClientFactory::RegisterClient
  void OnRegisterClient(bluetooth::BLEStatus status,
                        const bluetooth::UUID& uuid,
                        std::unique_ptr<bluetooth::LowEnergyClient> client);

  bluetooth::Adapter* adapter_;  // weak

  // Clients that are pending registration. Once their registration is complete,
  // the entry will be removed from this map.
  RemoteCallbackMap<bluetooth::UUID, IBluetoothLowEnergyCallback>
      pending_callbacks_;

  // We keep two maps here: one from client_if IDs to callback Binders and one
  // from client_if IDs to LowEnergyClient instances.
  std::mutex maps_lock_;  // Needed for |cif_to_client_|.
  RemoteCallbackMap<int, IBluetoothLowEnergyCallback> cif_to_cb_;
  std::unordered_map<int, std::shared_ptr<bluetooth::LowEnergyClient>>
      cif_to_client_;

  DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyBinderServer);
};