From a6551079fe71b1c76505ada0e4f758f6faf651e0 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 26 Jan 2016 12:58:47 -0800 Subject: [PATCH] service: add SetMtu and OnMtuChanged Change-Id: I7a6c6cb46f4710b5d2c57b9d0e9cfac166d7cd62 --- service/client/main.cpp | 15 +++++++ .../bluetooth/binder/IBluetoothLowEnergy.cpp | 22 +++++++++ .../common/bluetooth/binder/IBluetoothLowEnergy.h | 5 +++ .../binder/IBluetoothLowEnergyCallback.cpp | 24 ++++++++++ .../bluetooth/binder/IBluetoothLowEnergyCallback.h | 3 ++ service/doc/IBluetoothLowEnergy.txt | 9 +++- service/doc/IBluetoothLowEnergyCallback.txt | 5 +++ service/example/heart_rate/heart_rate_server.cpp | 2 + .../binder/bluetooth_low_energy_binder_server.cpp | 33 ++++++++++++++ .../binder/bluetooth_low_energy_binder_server.h | 3 ++ service/low_energy_client.cpp | 52 ++++++++++++++++++++++ service/low_energy_client.h | 12 +++++ service/test/low_energy_client_unittest.cpp | 11 ++++- 13 files changed, 194 insertions(+), 2 deletions(-) diff --git a/service/client/main.cpp b/service/client/main.cpp index 6d0381a0f..71845311d 100644 --- a/service/client/main.cpp +++ b/service/client/main.cpp @@ -175,6 +175,21 @@ class CLIBluetoothLowEnergyCallback PrintPrompt(); } + void OnMtuChanged(int status, const char *address, int mtu) override { + if (showing_prompt.load()) + cout << endl; + + cout << COLOR_BOLDWHITE "MTU changed: " + << COLOR_BOLDYELLOW "[" << address << " ] " + << COLOR_BOLDWHITE " - status: " << status + << COLOR_BOLDWHITE " - mtu: " << mtu << COLOR_OFF; + + cout << endl << endl; + + if (showing_prompt.load()) + PrintPrompt(); + } + void OnScanResult(const bluetooth::ScanResult& scan_result) override { if (showing_prompt.load()) cout << endl; diff --git a/service/common/bluetooth/binder/IBluetoothLowEnergy.cpp b/service/common/bluetooth/binder/IBluetoothLowEnergy.cpp index 48d99560a..ae2237baa 100644 --- a/service/common/bluetooth/binder/IBluetoothLowEnergy.cpp +++ b/service/common/bluetooth/binder/IBluetoothLowEnergy.cpp @@ -84,6 +84,16 @@ status_t BnBluetoothLowEnergy::onTransact( return android::NO_ERROR; } + case SET_MTU_TRANSACTION: { + int client_id = data.readInt32(); + const char* address = data.readCString(); + int mtu = data.readInt32(); + + bool result = SetMtu(client_id, address, mtu); + reply->writeInt32(result); + + return android::NO_ERROR; + } case START_SCAN_TRANSACTION: { int client_id = data.readInt32(); auto settings = CreateScanSettingsFromParcel(data); @@ -209,6 +219,18 @@ bool BpBluetoothLowEnergy::Disconnect(int client_id, const char* address) { return reply.readInt32(); } +bool BpBluetoothLowEnergy::SetMtu(int client_id, const char* address, int mtu) { + Parcel data, reply; + + data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor()); + data.writeInt32(client_id); + data.writeCString(address); + data.writeInt32(mtu); + + remote()->transact(IBluetoothLowEnergy::SET_MTU_TRANSACTION, data, &reply); + return reply.readInt32(); +} + bool BpBluetoothLowEnergy::StartScan( int client_id, const bluetooth::ScanSettings& settings, diff --git a/service/common/bluetooth/binder/IBluetoothLowEnergy.h b/service/common/bluetooth/binder/IBluetoothLowEnergy.h index 78d7213c2..56f8c5174 100644 --- a/service/common/bluetooth/binder/IBluetoothLowEnergy.h +++ b/service/common/bluetooth/binder/IBluetoothLowEnergy.h @@ -59,6 +59,7 @@ class IBluetoothLowEnergy : public android::IInterface { CONNECT_TRANSACTION, DISCONNECT_TRANSACTION, + SET_MTU_TRANSACTION, READ_REMOTE_RSSI_TRANSACTION, CONFIGURE_ATT_MTU_TRANSACTION, CONNECTION_PARAMETER_UPDATE_TRANSACTION, @@ -75,6 +76,8 @@ class IBluetoothLowEnergy : public android::IInterface { virtual bool Connect(int client_id, const char* address, bool is_direct) = 0; virtual bool Disconnect(int client_id, const char* address) = 0; + virtual bool SetMtu(int client_id, const char* address, int mtu) = 0; + virtual bool StartScan( int client_id, const bluetooth::ScanSettings& settings, @@ -126,6 +129,8 @@ class BpBluetoothLowEnergy : public android::BpInterface { bool Connect(int client_id, const char* address, bool is_direct) override; bool Disconnect(int client_id, const char* address) override; + bool SetMtu(int client_id, const char* address, int mtu) override; + bool StartScan( int client_id, const bluetooth::ScanSettings& settings, diff --git a/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.cpp b/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.cpp index e2b729299..c887e5f9e 100644 --- a/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.cpp +++ b/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.cpp @@ -64,6 +64,14 @@ status_t BnBluetoothLowEnergyCallback::onTransact( OnConnectionState(status, client_id, address, connected); return android::NO_ERROR; } + case ON_MTU_CHANGED_TRANSACTION: { + int status = data.readInt32(); + const char *address = data.readCString(); + int mtu = data.readInt32(); + + OnMtuChanged(status, address, mtu); + return android::NO_ERROR; + } case ON_SCAN_RESULT_TRANSACTION: { auto scan_result = CreateScanResultFromParcel(data); CHECK(scan_result.get()); @@ -124,6 +132,22 @@ void BpBluetoothLowEnergyCallback::OnConnectionState( IBinder::FLAG_ONEWAY); } +void BpBluetoothLowEnergyCallback::OnMtuChanged( + int status, const char* address, int mtu) { + Parcel data; + + data.writeInterfaceToken( + IBluetoothLowEnergyCallback::getInterfaceDescriptor()); + data.writeInt32(status); + data.writeCString(address); + data.writeInt32(mtu); + + remote()->transact( + IBluetoothLowEnergyCallback::ON_MTU_CHANGED_TRANSACTION, + data, NULL, + IBinder::FLAG_ONEWAY); +} + void BpBluetoothLowEnergyCallback::OnScanResult( const bluetooth::ScanResult& scan_result) { Parcel data, reply; diff --git a/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.h b/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.h index 908e78b2e..6c52726dd 100644 --- a/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.h +++ b/service/common/bluetooth/binder/IBluetoothLowEnergyCallback.h @@ -44,6 +44,7 @@ namespace binder { enum { ON_CLIENT_REGISTERED_TRANSACTION = android::IBinder::FIRST_CALL_TRANSACTION, ON_CONNECTION_STATE_TRANSACTION, + ON_MTU_CHANGED_TRANSACTION, ON_SCAN_RESULT_TRANSACTION, ON_BATCH_SCAN_RESULTS_TRANSACTION, ON_READ_REMOTE_RSSI_TRANSACTION, @@ -57,6 +58,7 @@ namespace binder { virtual void OnClientRegistered(int status, int client_if) = 0; virtual void OnConnectionState(int status, int client_id, const char* address, bool connected) = 0; + virtual void OnMtuChanged(int status, const char* address, int mtu) = 0; virtual void OnScanResult(const bluetooth::ScanResult& scan_result) = 0; virtual void OnMultiAdvertiseCallback( int status, bool is_start, @@ -97,6 +99,7 @@ class BpBluetoothLowEnergyCallback void OnClientRegistered(int status, int client_if) override; void OnConnectionState(int status, int client_id, const char* address, bool connected) override; + void OnMtuChanged(int status, const char* address, int mtu) override; void OnScanResult(const bluetooth::ScanResult& scan_result) override; void OnMultiAdvertiseCallback( int status, bool is_start, diff --git a/service/doc/IBluetoothLowEnergy.txt b/service/doc/IBluetoothLowEnergy.txt index c05620e41..b7218cbe7 100644 --- a/service/doc/IBluetoothLowEnergy.txt +++ b/service/doc/IBluetoothLowEnergy.txt @@ -45,11 +45,18 @@ interface IBluetoothLowEnergy { in boolean is_direct); /* Disconnect from previously connected BLE device with address |address|. - * Return true on success, false otherwise. + * Returns true on success, false otherwise. */ boolean Disconnect(in int client_id, in const char* address); /** + * Sends request to set MTU to |mtu| for the device with address |address|. + * OnMtuChanged callback will be triggered as a result of this call. Returns + * true when the command was sent, false otherwise. + */ + boolean setMtu(in int client_id, in char* address, int mtu); + + /** * Initiates a BLE device scan for the scan client with ID |client_id|, using * the parameters defined in |settings|. Scan results that are reported to the * application with the associated IBluetoothLowEnergyCallback event will be diff --git a/service/doc/IBluetoothLowEnergyCallback.txt b/service/doc/IBluetoothLowEnergyCallback.txt index 4fa60bfac..1ced0aa1e 100644 --- a/service/doc/IBluetoothLowEnergyCallback.txt +++ b/service/doc/IBluetoothLowEnergyCallback.txt @@ -33,6 +33,11 @@ oneway interface IBluetoothLowEnergyCallback { void OnConnectionState(in int status, in int client_id, in const char* address, in bool connected); + /* Called to report current MTU value. Can be a result of calling + * IBluetoothLowEnergy.setMtu or remote device trying to change MTU. + */ + void OnMtuChanged(in int status, in const char* address, in int mtu); + /** * Called to report BLE device scan results once a scan session is started for * this client using IBluetoothLowEnergy.startScan. |scan_result| contains all diff --git a/service/example/heart_rate/heart_rate_server.cpp b/service/example/heart_rate/heart_rate_server.cpp index f1113620f..724ef295f 100644 --- a/service/example/heart_rate/heart_rate_server.cpp +++ b/service/example/heart_rate/heart_rate_server.cpp @@ -36,6 +36,8 @@ class CLIBluetoothLowEnergyCallback // IBluetoothLowEnergyCallback overrides: void OnConnectionState(int status, int client_id, const char* address, bool connected) override {} + void OnMtuChanged(int status, const char *address, int mtu) override {} + void OnScanResult(const bluetooth::ScanResult& scan_result) override {} void OnClientRegistered(int status, int client_id){ diff --git a/service/ipc/binder/bluetooth_low_energy_binder_server.cpp b/service/ipc/binder/bluetooth_low_energy_binder_server.cpp index f49d909d9..0e5d6ff9e 100644 --- a/service/ipc/binder/bluetooth_low_energy_binder_server.cpp +++ b/service/ipc/binder/bluetooth_low_energy_binder_server.cpp @@ -86,6 +86,23 @@ bool BluetoothLowEnergyBinderServer::Disconnect(int client_id, return client->Disconnect(std::string(address)); } +bool BluetoothLowEnergyBinderServer::SetMtu(int client_id, + const char* address, + int mtu) { + VLOG(2) << __func__ << " client_id: " << client_id + << " address: " << address + << " mtu: " << mtu; + std::lock_guard lock(*maps_lock()); + + auto client = GetLEClient(client_id); + if (!client) { + LOG(ERROR) << "Unknown client_id: " << client_id; + return false; + } + + return client->SetMtu(address, mtu); +} + bool BluetoothLowEnergyBinderServer::StartScan( int client_id, const bluetooth::ScanSettings& settings, @@ -215,6 +232,22 @@ void BluetoothLowEnergyBinderServer::OnConnectionState( cb->OnConnectionState(status, client_id, address, connected); } +void BluetoothLowEnergyBinderServer::OnMtuChanged( + bluetooth::LowEnergyClient* client, int status, const char* address, int mtu) { + VLOG(2) << __func__ << " address: " << address + << " status: " << status + << " mtu: " << mtu; + + int client_id = client->GetInstanceId(); + auto cb = GetLECallback(client_id); + if (!cb.get()) { + VLOG(2) << "Client was unregistered - client_id: " << client_id; + return; + } + + cb->OnMtuChanged(status, address, mtu); +} + void BluetoothLowEnergyBinderServer::OnScanResult( bluetooth::LowEnergyClient* client, const bluetooth::ScanResult& result) { diff --git a/service/ipc/binder/bluetooth_low_energy_binder_server.h b/service/ipc/binder/bluetooth_low_energy_binder_server.h index 48a4f7197..c060ef88f 100644 --- a/service/ipc/binder/bluetooth_low_energy_binder_server.h +++ b/service/ipc/binder/bluetooth_low_energy_binder_server.h @@ -49,6 +49,7 @@ class BluetoothLowEnergyBinderServer void UnregisterAll() override; bool Connect(int client_id, const char* address, bool is_direct) override; bool Disconnect(int client_id, const char* address) override; + bool SetMtu(int client_id, const char* address, int mtu) override; bool StartScan( int client_id, const bluetooth::ScanSettings& settings, @@ -64,6 +65,8 @@ class BluetoothLowEnergyBinderServer // bluetooth::LowEnergyClient::Delegate overrides: void OnConnectionState(bluetooth::LowEnergyClient* client, int status, const char* address, bool connected) override; + void OnMtuChanged(bluetooth::LowEnergyClient* client, int status, + const char* address, int mtu) override; void OnScanResult(bluetooth::LowEnergyClient* client, const bluetooth::ScanResult& result) override; diff --git a/service/low_energy_client.cpp b/service/low_energy_client.cpp index 4ec116e52..a6653b78c 100644 --- a/service/low_energy_client.cpp +++ b/service/low_energy_client.cpp @@ -378,6 +378,33 @@ bool LowEnergyClient::Disconnect(std::string address) { return true; } +bool LowEnergyClient::SetMtu(std::string address, int mtu) { + VLOG(2) << __func__ << "Address: " << address + << " MTU: " << mtu; + + bt_bdaddr_t bda; + util::BdAddrFromString(address, &bda); + + std::map::iterator conn_id; + { + lock_guard lock(connection_fields_lock_); + conn_id = connection_ids_.find(bda); + if (conn_id == connection_ids_.end()) { + LOG(WARNING) << "Can't set MTU, no existing connection to " << address; + return false; + } + } + + bt_status_t status = hal::BluetoothGattInterface::Get()-> + GetClientHALInterface()->configure_mtu(conn_id->second, mtu); + if (status != BT_STATUS_SUCCESS) { + LOG(ERROR) << "HAL call to set MTU failed"; + return false; + } + + return true; +} + void LowEnergyClient::SetDelegate(Delegate* delegate) { lock_guard lock(delegate_mutex_); delegate_ = delegate; @@ -597,6 +624,31 @@ void LowEnergyClient::DisconnectCallback( false); } +void LowEnergyClient::MtuChangedCallback( + hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, + int mtu) { + VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status + << " mtu: " << mtu; + + const bt_bdaddr_t *bda = nullptr; + { + lock_guard lock(connection_fields_lock_); + for (auto& connection: connection_ids_) { + if (connection.second == conn_id) { + bda = &connection.first; + break; + } + } + } + + if (!bda) + return; + + const char *addr = BtAddrString(bda).c_str(); + if (delegate_) + delegate_->OnMtuChanged(this, status, addr, mtu); +} + void LowEnergyClient::MultiAdvEnableCallback( hal::BluetoothGattInterface* gatt_iface, int client_id, int status) { diff --git a/service/low_energy_client.h b/service/low_energy_client.h index 700ad9cf7..45ff66224 100644 --- a/service/low_energy_client.h +++ b/service/low_energy_client.h @@ -65,6 +65,10 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, virtual void OnConnectionState(LowEnergyClient* client, int status, const char* address, bool connected) = 0; + // Called asynchronously to notify the delegate of mtu change + virtual void OnMtuChanged(LowEnergyClient* client, int status, const char* address, + int mtu) = 0; + private: DISALLOW_COPY_AND_ASSIGN(Delegate); }; @@ -89,6 +93,10 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, // Return true on success, false otherwise. bool Disconnect(std::string address); + // Sends request to set MTU to |mtu| for device with address |address|. + // Return true on success, false otherwise. + bool SetMtu(std::string address, int mtu); + // Initiates a BLE device scan for this client using the given |settings| and // |filters|. See the documentation for ScanSettings and ScanFilter for how // these parameters can be configured. Return true on success, false @@ -149,6 +157,9 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, void DisconnectCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int client_id, const bt_bdaddr_t& bda) override; + void MtuChangedCallback( + hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, + int mtu) override; void MultiAdvEnableCallback( hal::BluetoothGattInterface* gatt_iface, int client_id, int status) override; @@ -220,6 +231,7 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, std::mutex connection_fields_lock_; // Maps bluetooth address to connection id + //TODO(jpawlowski): change type to bimap std::map connection_ids_; DISALLOW_COPY_AND_ASSIGN(LowEnergyClient); diff --git a/service/test/low_energy_client_unittest.cpp b/service/test/low_energy_client_unittest.cpp index 70bbd2aac..cecdc8e47 100644 --- a/service/test/low_energy_client_unittest.cpp +++ b/service/test/low_energy_client_unittest.cpp @@ -77,7 +77,8 @@ class MockGattHandler class TestDelegate : public LowEnergyClient::Delegate { public: - TestDelegate() : scan_result_count_(0), connection_state_count_(0) { + TestDelegate() : scan_result_count_(0), connection_state_count_(0), + last_mtu_(0) { } ~TestDelegate() override = default; @@ -93,6 +94,12 @@ class TestDelegate : public LowEnergyClient::Delegate { connection_state_count_++; } + void OnMtuChanged(LowEnergyClient* client, int status, const char* address, + int mtu) { + ASSERT_TRUE(client); + last_mtu_ = mtu; + } + void OnScanResult(LowEnergyClient* client, const ScanResult& scan_result) { ASSERT_TRUE(client); scan_result_count_++; @@ -105,6 +112,8 @@ class TestDelegate : public LowEnergyClient::Delegate { int connection_state_count_; + int last_mtu_; + DISALLOW_COPY_AND_ASSIGN(TestDelegate); }; -- 2.11.0