Loading system/service/Android.mk +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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 Loading system/service/bluetooth_client_instance.h 0 → 100644 +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 system/service/ipc/binder/bluetooth_low_energy_binder_server.cpp +32 −106 Original line number Original line Diff line number Diff line Loading @@ -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( Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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(); Loading @@ -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); }; }; Loading @@ -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 Loading system/service/ipc/binder/bluetooth_low_energy_binder_server.h +14 −22 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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); }; }; Loading system/service/ipc/binder/interface_with_clients_base.cpp 0 → 100644 +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
system/service/Android.mk +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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 Loading
system/service/bluetooth_client_instance.h 0 → 100644 +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
system/service/ipc/binder/bluetooth_low_energy_binder_server.cpp +32 −106 Original line number Original line Diff line number Diff line Loading @@ -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( Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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(); Loading @@ -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); }; }; Loading @@ -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 Loading
system/service/ipc/binder/bluetooth_low_energy_binder_server.h +14 −22 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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); }; }; Loading
system/service/ipc/binder/interface_with_clients_base.cpp 0 → 100644 +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