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

Commit 10f603da authored by Arman Uguray's avatar Arman Uguray Committed by Android Git Automerger
Browse files

am f2268fec: service: Move client registration into base class

* commit 'f2268fec':
  service: Move client registration into base class
parents d24ea6a0 f2268fec
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ btserviceBinderSrc := \
	ipc/binder/IBluetoothCallback.cpp \
	ipc/binder/IBluetoothCallback.cpp \
	ipc/binder/IBluetoothLowEnergy.cpp \
	ipc/binder/IBluetoothLowEnergy.cpp \
	ipc/binder/IBluetoothLowEnergyCallback.cpp \
	ipc/binder/IBluetoothLowEnergyCallback.cpp \
	ipc/binder/interface_with_clients_base.cpp \
	ipc/binder/ipc_handler_binder.cpp \
	ipc/binder/ipc_handler_binder.cpp \
	ipc/binder/parcel_helpers.cpp
	ipc/binder/parcel_helpers.cpp


+75 −0
Original line number Original line Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#pragma once

#include <functional>
#include <memory>

#include <base/macros.h>

#include "service/low_energy_constants.h"
#include "service/uuid.h"

namespace bluetooth {

// A BluetoothClientInstance represents an application's handle to an instance
// that is registered with the underlying Bluetooth stack using a UUID and has a
// stack-assigned integer "client_if" ID associated with it.
class BluetoothClientInstance {
 public:
  virtual ~BluetoothClientInstance() = default;

  // Returns the app-specific unique ID used while registering this client.
  virtual const UUID& GetAppIdentifier() const = 0;

  // Returns the HAL "interface ID" assigned to this instance by the stack.
  virtual int GetClientId() const = 0;

 protected:
  // Constructor shouldn't be called directly as instances are meant to be
  // obtained from the factory.
  BluetoothClientInstance() = default;

 private:
  DISALLOW_COPY_AND_ASSIGN(BluetoothClientInstance);
};

// A BluetoothClientInstanceFactory provides a common interface for factory
// classes that handle asynchronously registering a per-application instance of
// a BluetoothClientInstance with the underlying stack.
class BluetoothClientInstanceFactory {
 public:
  BluetoothClientInstanceFactory() = default;
  virtual ~BluetoothClientInstanceFactory() = default;

  // Callback invoked as a result of a call to RegisterClient.
  using RegisterCallback = std::function<void(
      BLEStatus status, const UUID& app_uuid,
      std::unique_ptr<BluetoothClientInstance> client)>;

  // Registers a client of type T for the given unique identifier |app_uuid|.
  // On success, this asynchronously invokes |callback| with a unique pointer
  // to an instance of type T whose ownership can be taken by the caller. In
  // the case of an error, the pointer will contain nullptr.
  virtual bool RegisterClient(const UUID& app_uuid,
                              const RegisterCallback& callback) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(BluetoothClientInstanceFactory);
};

}  // namespace bluetooth
+32 −106
Original line number Original line Diff line number Diff line
@@ -34,65 +34,20 @@ BluetoothLowEnergyBinderServer::~BluetoothLowEnergyBinderServer() {
void BluetoothLowEnergyBinderServer::RegisterClient(
void BluetoothLowEnergyBinderServer::RegisterClient(
    const android::sp<IBluetoothLowEnergyCallback>& callback) {
    const android::sp<IBluetoothLowEnergyCallback>& callback) {
  VLOG(2) << __func__;
  VLOG(2) << __func__;
  if (!callback.get()) {
    LOG(ERROR) << "Cannot register a NULL callback";
    return;
  }

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


  // Store the callback in the pending list. It will get removed later when the
  RegisterClientBase(callback, ble_factory);
  // 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) {
void BluetoothLowEnergyBinderServer::UnregisterClient(int client_if) {
  VLOG(2) << __func__;
  VLOG(2) << __func__;
  std::lock_guard<std::mutex> lock(maps_lock_);
  UnregisterClientBase(client_if);

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


void BluetoothLowEnergyBinderServer::UnregisterAll() {
void BluetoothLowEnergyBinderServer::UnregisterAll() {
  VLOG(2) << __func__;
  VLOG(2) << __func__;
  std::lock_guard<std::mutex> lock(maps_lock_);
  UnregisterAllBase();

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


void BluetoothLowEnergyBinderServer::StartMultiAdvertising(
void BluetoothLowEnergyBinderServer::StartMultiAdvertising(
@@ -101,15 +56,15 @@ void BluetoothLowEnergyBinderServer::StartMultiAdvertising(
    const bluetooth::AdvertiseData& scan_response,
    const bluetooth::AdvertiseData& scan_response,
    const bluetooth::AdvertiseSettings& settings) {
    const bluetooth::AdvertiseSettings& settings) {
  VLOG(2) << __func__;
  VLOG(2) << __func__;
  std::lock_guard<std::mutex> lock(maps_lock_);
  std::lock_guard<std::mutex> lock(*maps_lock());


  auto iter = cif_to_client_.find(client_if);
  auto client = GetLEClient(client_if);
  if (iter == cif_to_client_.end()) {
  if (!client) {
    LOG(ERROR) << "Unknown client_if: " << client_if;
    LOG(ERROR) << "Unknown client_if: " << client_if;
    return;
    return;
  }
  }


  android::sp<IBluetoothLowEnergyCallback> cb = cif_to_cb_.Get(client_if);
  auto cb = GetLECallback(client_if);
  if (!cb.get()) {
  if (!cb.get()) {
    LOG(ERROR) << "Client was unregistered - client_if: " << client_if;
    LOG(ERROR) << "Client was unregistered - client_if: " << client_if;
    return;
    return;
@@ -126,12 +81,11 @@ void BluetoothLowEnergyBinderServer::StartMultiAdvertising(
      return;
      return;
    }
    }


    std::lock_guard<std::mutex> lock(maps_lock_);
    std::lock_guard<std::mutex> lock(*maps_lock());


    cb->OnMultiAdvertiseCallback(status, true /* is_start */, settings_copy);
    cb->OnMultiAdvertiseCallback(status, true /* is_start */, settings_copy);
  };
  };


  std::shared_ptr<bluetooth::LowEnergyClient> client = iter->second;
  if (client->StartAdvertising(
  if (client->StartAdvertising(
      settings, advertise_data, scan_response, callback))
      settings, advertise_data, scan_response, callback))
    return;
    return;
@@ -145,15 +99,15 @@ void BluetoothLowEnergyBinderServer::StartMultiAdvertising(


void BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_if) {
void BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_if) {
  VLOG(2) << __func__;
  VLOG(2) << __func__;
  std::lock_guard<std::mutex> lock(maps_lock_);
  std::lock_guard<std::mutex> lock(*maps_lock());


  auto iter = cif_to_client_.find(client_if);
  auto client = GetLEClient(client_if);
  if (iter == cif_to_client_.end()) {
  if (!client) {
    LOG(ERROR) << "Unknown client_if: " << client_if;
    LOG(ERROR) << "Unknown client_if: " << client_if;
    return;
    return;
  }
  }


  android::sp<IBluetoothLowEnergyCallback> cb = cif_to_cb_.Get(client_if);
  auto cb = GetLECallback(client_if);
  if (!cb.get()) {
  if (!cb.get()) {
    LOG(ERROR) << "Client was unregistered - client_if: " << client_if;
    LOG(ERROR) << "Client was unregistered - client_if: " << client_if;
    return;
    return;
@@ -162,7 +116,6 @@ void BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_if) {
  // Create a weak pointer and pass that to the callback to prevent a potential
  // Create a weak pointer and pass that to the callback to prevent a potential
  // use after free.
  // use after free.
  android::wp<BluetoothLowEnergyBinderServer> weak_ptr_to_this(this);
  android::wp<BluetoothLowEnergyBinderServer> weak_ptr_to_this(this);
  std::shared_ptr<bluetooth::LowEnergyClient> client = iter->second;
  bluetooth::AdvertiseSettings settings_copy = client->settings();
  bluetooth::AdvertiseSettings settings_copy = client->settings();
  auto callback = [&](bluetooth::BLEStatus status) {
  auto callback = [&](bluetooth::BLEStatus status) {
    auto sp_to_this = weak_ptr_to_this.promote();
    auto sp_to_this = weak_ptr_to_this.promote();
@@ -171,7 +124,7 @@ void BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_if) {
      return;
      return;
    }
    }


    std::lock_guard<std::mutex> lock(maps_lock_);
    std::lock_guard<std::mutex> lock(*maps_lock());


    cb->OnMultiAdvertiseCallback(status, false /* is_start */, settings_copy);
    cb->OnMultiAdvertiseCallback(status, false /* is_start */, settings_copy);
  };
  };
@@ -186,56 +139,29 @@ void BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_if) {
      bluetooth::BLE_STATUS_FAILURE, false/* is_start */, settings_copy);
      bluetooth::BLE_STATUS_FAILURE, false/* is_start */, settings_copy);
}
}


void BluetoothLowEnergyBinderServer::OnRemoteCallbackRemoved(const int& key) {
android::sp<IBluetoothLowEnergyCallback>
  VLOG(2) << __func__ << " client_if: " << key;
BluetoothLowEnergyBinderServer::GetLECallback(int client_if) {
  std::lock_guard<std::mutex> lock(maps_lock_);
  auto cb = GetCallback(client_if);

  return android::sp<IBluetoothLowEnergyCallback>(
  // No need to remove from the callback map as the entry should be already
      static_cast<IBluetoothLowEnergyCallback*>(cb.get()));
  // 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_);
std::shared_ptr<bluetooth::LowEnergyClient>
  CHECK(client->client_if());
BluetoothLowEnergyBinderServer::GetLEClient(int client_if) {
  int client_if = client->client_if();
  return std::static_pointer_cast<bluetooth::LowEnergyClient>(
  if (!cif_to_cb_.Register(client_if, callback, this)) {
      GetClientInstance(client_if));
    LOG(ERROR) << "Failed to store callback";
    return;
}
}


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

    bluetooth::BLEStatus status,
  cif_to_client_[client_if] =
    android::sp<IInterface> callback,
      std::shared_ptr<bluetooth::LowEnergyClient>(client.release());
    bluetooth::BluetoothClientInstance* client) {

  VLOG(1) << __func__ << " status: " << status;
  // Notify the client.
  android::sp<IBluetoothLowEnergyCallback> cb(
  callback->OnClientRegistered(static_cast<int>(status), client_if);
      static_cast<IBluetoothLowEnergyCallback*>(callback.get()));
  cb->OnClientRegistered(
      status,
      (status == bluetooth::BLE_STATUS_SUCCESS) ? client->GetClientId() : -1);
}
}


}  // namespace binder
}  // namespace binder
+14 −22
Original line number Original line Diff line number Diff line
@@ -17,16 +17,14 @@
#pragma once
#pragma once


#include <memory>
#include <memory>
#include <unordered_map>


#include <base/macros.h>
#include <base/macros.h>


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


namespace bluetooth {
namespace bluetooth {
class Adapter;
class Adapter;
@@ -38,7 +36,7 @@ namespace binder {
// Implements the server side of the IBluetoothLowEnergy interface.
// Implements the server side of the IBluetoothLowEnergy interface.
class BluetoothLowEnergyBinderServer
class BluetoothLowEnergyBinderServer
    : public BnBluetoothLowEnergy,
    : public BnBluetoothLowEnergy,
      public RemoteCallbackMap<int, IBluetoothLowEnergyCallback>::Delegate {
      public InterfaceWithClientsBase {
 public:
 public:
  explicit BluetoothLowEnergyBinderServer(bluetooth::Adapter* adapter);
  explicit BluetoothLowEnergyBinderServer(bluetooth::Adapter* adapter);
  ~BluetoothLowEnergyBinderServer() override;
  ~BluetoothLowEnergyBinderServer() override;
@@ -56,27 +54,21 @@ class BluetoothLowEnergyBinderServer
  void StopMultiAdvertising(int client_if) override;
  void StopMultiAdvertising(int client_if) override;


 private:
 private:
  // RemoteCallbackMap<int, IBluetoothLowEnergyCallback>::Delegate override:
  // Returns a pointer to the IBluetoothLowEnergyCallback instance associated
  void OnRemoteCallbackRemoved(const int& key) override;
  // with |client_if|. Returns NULL if such a callback cannot be found.
  android::sp<IBluetoothLowEnergyCallback> GetLECallback(int client_if);


  // Called as a result of bluetooth::LowEnergyClientFactory::RegisterClient
  // Returns a pointer to the LowEnergyClient instance associated with
  void OnRegisterClient(bluetooth::BLEStatus status,
  // |client_if|. Returns NULL if such a client cannot be found.
                        const bluetooth::UUID& uuid,
  std::shared_ptr<bluetooth::LowEnergyClient> GetLEClient(int client_if);
                        std::unique_ptr<bluetooth::LowEnergyClient> client);


  bluetooth::Adapter* adapter_;  // weak
  // InterfaceWithClientsBase override:

  void OnRegisterClientImpl(
  // Clients that are pending registration. Once their registration is complete,
      bluetooth::BLEStatus status,
  // the entry will be removed from this map.
      android::sp<IInterface> callback,
  RemoteCallbackMap<bluetooth::UUID, IBluetoothLowEnergyCallback>
      bluetooth::BluetoothClientInstance* client) override;
      pending_callbacks_;


  // We keep two maps here: one from client_if IDs to callback Binders and one
  bluetooth::Adapter* adapter_;  // weak
  // 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);
  DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyBinderServer);
};
};
+156 −0
Original line number Original line Diff line number Diff line
//
//  Copyright (C) 2015 Google, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#include "service/ipc/binder/interface_with_clients_base.h"

#include <base/logging.h>

namespace ipc {
namespace binder {

bool InterfaceWithClientsBase::RegisterClientBase(
    const android::sp<IInterface>& callback,
    bluetooth::BluetoothClientInstanceFactory* factory) {
  VLOG(2) << __func__;
  CHECK(factory);

  if (!callback.get()) {
    LOG(ERROR) << "Cannot register a NULL callback";
    return false;
  }

  // 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 false;
  }

  // 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<InterfaceWithClientsBase> weak_ptr_to_this(this);

  bluetooth::BluetoothClientInstanceFactory::RegisterCallback cb =
      [weak_ptr_to_this](
          bluetooth::BLEStatus status,
          const bluetooth::UUID& in_uuid,
          std::unique_ptr<bluetooth::BluetoothClientInstance> client) {
        // If the weak pointer was invalidated then there is nothing we can do.
        android::sp<InterfaceWithClientsBase> strong_ptr_to_this =
            weak_ptr_to_this.promote();
        if (!strong_ptr_to_this.get()) {
          VLOG(2) << "InterfaceWithClientsBase was deleted while client was "
                  << "being registered";
          return;
        }

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

  if (factory->RegisterClient(app_uuid, cb))
    return true;

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

  return false;
}

void InterfaceWithClientsBase::UnregisterClientBase(int client_if) {
  VLOG(2) << __func__;
  std::lock_guard<std::mutex> lock(maps_lock_);

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

void InterfaceWithClientsBase::UnregisterAllBase() {
  VLOG(2) << __func__;
  std::lock_guard<std::mutex> lock(maps_lock_);

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

android::sp<IInterface> InterfaceWithClientsBase::GetCallback(int client_if) {
  return cif_to_cb_.Get(client_if);
}

std::shared_ptr<bluetooth::BluetoothClientInstance>
InterfaceWithClientsBase::GetClientInstance(int client_if) {
  auto iter = cif_to_client_.find(client_if);
  if (iter == cif_to_client_.end())
    return std::shared_ptr<bluetooth::BluetoothClientInstance>();
  return iter->second;
}

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

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

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

  if (status != bluetooth::BLE_STATUS_SUCCESS) {
    // The call wasn't successful. Notify the implementation and return.
    LOG(ERROR) << "Failed to register client: " << status;
    OnRegisterClientImpl(status, callback, nullptr);
    return;
  }

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

  VLOG(1) << "Registered BluetoothClientInstance - ID: " << client_if;

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

  OnRegisterClientImpl(status, callback, shared_client.get());
}

void InterfaceWithClientsBase::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);
}

}  // namespace binder
}  // namespace ipc
Loading