1 // 2 // Copyright (C) 2015 Google, Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "service/ipc/binder/bluetooth_low_energy_binder_server.h" 18 19 #include <base/logging.h> 20 21 #include "service/adapter.h" 22 23 namespace ipc { 24 namespace binder { 25 26 namespace { 27 const int kInvalidInstanceId = -1; 28 } // namespace 29 30 BluetoothLowEnergyBinderServer::BluetoothLowEnergyBinderServer( 31 bluetooth::Adapter* adapter) : adapter_(adapter) { 32 CHECK(adapter_); 33 } 34 35 BluetoothLowEnergyBinderServer::~BluetoothLowEnergyBinderServer() { 36 } 37 38 bool BluetoothLowEnergyBinderServer::RegisterClient( 39 const android::sp<IBluetoothLowEnergyCallback>& callback) { 40 VLOG(2) << __func__; 41 bluetooth::LowEnergyClientFactory* ble_factory = 42 adapter_->GetLowEnergyClientFactory(); 43 44 return RegisterInstanceBase(callback, ble_factory); 45 } 46 47 void BluetoothLowEnergyBinderServer::UnregisterClient(int client_id) { 48 VLOG(2) << __func__; 49 UnregisterInstanceBase(client_id); 50 } 51 52 void BluetoothLowEnergyBinderServer::UnregisterAll() { 53 VLOG(2) << __func__; 54 UnregisterAllBase(); 55 } 56 57 bool BluetoothLowEnergyBinderServer::Connect(int client_id, 58 const char* address, 59 bool is_direct) { 60 VLOG(2) << __func__ << " client_id: " << client_id 61 << " address: " << address 62 << " is_direct: " << is_direct; 63 std::lock_guard<std::mutex> lock(*maps_lock()); 64 65 auto client = GetLEClient(client_id); 66 if (!client) { 67 LOG(ERROR) << "Unknown client_id: " << client_id; 68 return false; 69 } 70 71 return client->Connect(std::string(address), is_direct); 72 } 73 74 bool BluetoothLowEnergyBinderServer::Disconnect(int client_id, 75 const char* address) { 76 VLOG(2) << __func__ << " client_id: " << client_id 77 << " address: " << address; 78 std::lock_guard<std::mutex> lock(*maps_lock()); 79 80 auto client = GetLEClient(client_id); 81 if (!client) { 82 LOG(ERROR) << "Unknown client_id: " << client_id; 83 return false; 84 } 85 86 return client->Disconnect(std::string(address)); 87 } 88 89 bool BluetoothLowEnergyBinderServer::SetMtu(int client_id, 90 const char* address, 91 int mtu) { 92 VLOG(2) << __func__ << " client_id: " << client_id 93 << " address: " << address 94 << " mtu: " << mtu; 95 std::lock_guard<std::mutex> lock(*maps_lock()); 96 97 auto client = GetLEClient(client_id); 98 if (!client) { 99 LOG(ERROR) << "Unknown client_id: " << client_id; 100 return false; 101 } 102 103 return client->SetMtu(address, mtu); 104 } 105 106 bool BluetoothLowEnergyBinderServer::StartScan( 107 int client_id, 108 const bluetooth::ScanSettings& settings, 109 const std::vector<bluetooth::ScanFilter>& filters) { 110 VLOG(2) << __func__ << " client_id: " << client_id; 111 std::lock_guard<std::mutex> lock(*maps_lock()); 112 113 auto client = GetLEClient(client_id); 114 if (!client) { 115 LOG(ERROR) << "Unknown client_id: " << client_id; 116 return false; 117 } 118 119 return client->StartScan(settings, filters); 120 } 121 122 bool BluetoothLowEnergyBinderServer::StopScan(int client_id) { 123 VLOG(2) << __func__ << " client_id: " << client_id; 124 std::lock_guard<std::mutex> lock(*maps_lock()); 125 126 auto client = GetLEClient(client_id); 127 if (!client) { 128 LOG(ERROR) << "Unknown client_id: " << client_id; 129 return false; 130 } 131 132 return client->StopScan(); 133 } 134 135 bool BluetoothLowEnergyBinderServer::StartMultiAdvertising( 136 int client_id, 137 const bluetooth::AdvertiseData& advertise_data, 138 const bluetooth::AdvertiseData& scan_response, 139 const bluetooth::AdvertiseSettings& settings) { 140 VLOG(2) << __func__ << " client_id: " << client_id; 141 std::lock_guard<std::mutex> lock(*maps_lock()); 142 143 auto client = GetLEClient(client_id); 144 if (!client) { 145 LOG(ERROR) << "Unknown client_id: " << client_id; 146 return false; 147 } 148 149 // Create a weak pointer and pass that to the callback to prevent a potential 150 // use after free. 151 android::wp<BluetoothLowEnergyBinderServer> weak_ptr_to_this(this); 152 auto settings_copy = settings; 153 auto callback = [=](bluetooth::BLEStatus status) { 154 auto sp_to_this = weak_ptr_to_this.promote(); 155 if (!sp_to_this.get()) { 156 VLOG(2) << "BluetoothLowEnergyBinderServer was deleted"; 157 return; 158 } 159 160 std::lock_guard<std::mutex> lock(*maps_lock()); 161 162 auto cb = GetLECallback(client_id); 163 if (!cb.get()) { 164 VLOG(1) << "Client was removed before callback: " << client_id; 165 return; 166 } 167 168 cb->OnMultiAdvertiseCallback(status, true /* is_start */, settings_copy); 169 }; 170 171 if (!client->StartAdvertising( 172 settings, advertise_data, scan_response, callback)) { 173 LOG(ERROR) << "Failed to initiate call to start advertising"; 174 return false; 175 } 176 177 return true; 178 } 179 180 bool BluetoothLowEnergyBinderServer::StopMultiAdvertising(int client_id) { 181 VLOG(2) << __func__; 182 std::lock_guard<std::mutex> lock(*maps_lock()); 183 184 auto client = GetLEClient(client_id); 185 if (!client) { 186 LOG(ERROR) << "Unknown client_id: " << client_id; 187 return false; 188 } 189 190 // Create a weak pointer and pass that to the callback to prevent a potential 191 // use after free. 192 android::wp<BluetoothLowEnergyBinderServer> weak_ptr_to_this(this); 193 auto settings_copy = client->advertise_settings(); 194 auto callback = [=](bluetooth::BLEStatus status) { 195 auto sp_to_this = weak_ptr_to_this.promote(); 196 if (!sp_to_this.get()) { 197 VLOG(2) << "BluetoothLowEnergyBinderServer was deleted"; 198 return; 199 } 200 201 auto cb = GetLECallback(client_id); 202 if (!cb.get()) { 203 VLOG(2) << "Client was unregistered - client_id: " << client_id; 204 return; 205 } 206 207 std::lock_guard<std::mutex> lock(*maps_lock()); 208 209 cb->OnMultiAdvertiseCallback(status, false /* is_start */, settings_copy); 210 }; 211 212 if (!client->StopAdvertising(callback)) { 213 LOG(ERROR) << "Failed to initiate call to start advertising"; 214 return false; 215 } 216 217 return true; 218 } 219 220 void BluetoothLowEnergyBinderServer::OnConnectionState( 221 bluetooth::LowEnergyClient* client, int status, 222 const char* address, bool connected) { 223 VLOG(2) << __func__ << " address: " << address << " connected: " << connected; 224 225 int client_id = client->GetInstanceId(); 226 auto cb = GetLECallback(client->GetInstanceId()); 227 if (!cb.get()) { 228 VLOG(2) << "Client was unregistered - client_id: " << client_id; 229 return; 230 } 231 232 cb->OnConnectionState(status, client_id, address, connected); 233 } 234 235 void BluetoothLowEnergyBinderServer::OnMtuChanged( 236 bluetooth::LowEnergyClient* client, int status, const char* address, int mtu) { 237 VLOG(2) << __func__ << " address: " << address 238 << " status: " << status 239 << " mtu: " << mtu; 240 241 int client_id = client->GetInstanceId(); 242 auto cb = GetLECallback(client_id); 243 if (!cb.get()) { 244 VLOG(2) << "Client was unregistered - client_id: " << client_id; 245 return; 246 } 247 248 cb->OnMtuChanged(status, address, mtu); 249 } 250 251 void BluetoothLowEnergyBinderServer::OnScanResult( 252 bluetooth::LowEnergyClient* client, 253 const bluetooth::ScanResult& result) { 254 VLOG(2) << __func__; 255 std::lock_guard<std::mutex> lock(*maps_lock()); 256 257 int client_id = client->GetInstanceId(); 258 auto cb = GetLECallback(client->GetInstanceId()); 259 if (!cb.get()) { 260 VLOG(2) << "Client was unregistered - client_id: " << client_id; 261 return; 262 } 263 264 cb->OnScanResult(result); 265 } 266 267 android::sp<IBluetoothLowEnergyCallback> 268 BluetoothLowEnergyBinderServer::GetLECallback(int client_id) { 269 auto cb = GetCallback(client_id); 270 return android::sp<IBluetoothLowEnergyCallback>( 271 static_cast<IBluetoothLowEnergyCallback*>(cb.get())); 272 } 273 274 std::shared_ptr<bluetooth::LowEnergyClient> 275 BluetoothLowEnergyBinderServer::GetLEClient(int client_id) { 276 return std::static_pointer_cast<bluetooth::LowEnergyClient>( 277 GetInstance(client_id)); 278 } 279 280 void BluetoothLowEnergyBinderServer::OnRegisterInstanceImpl( 281 bluetooth::BLEStatus status, 282 android::sp<IInterface> callback, 283 bluetooth::BluetoothInstance* instance) { 284 VLOG(1) << __func__ << " status: " << status; 285 bluetooth::LowEnergyClient* le_client = 286 static_cast<bluetooth::LowEnergyClient*>(instance); 287 le_client->SetDelegate(this); 288 289 android::sp<IBluetoothLowEnergyCallback> cb( 290 static_cast<IBluetoothLowEnergyCallback*>(callback.get())); 291 cb->OnClientRegistered( 292 status, 293 (status == bluetooth::BLE_STATUS_SUCCESS) ? 294 instance->GetInstanceId() : kInvalidInstanceId); 295 } 296 297 } // namespace binder 298 } // namespace ipc 299