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
BluetoothLowEnergyBinderServer(bluetooth::Adapter * adapter)30 BluetoothLowEnergyBinderServer::BluetoothLowEnergyBinderServer(
31 bluetooth::Adapter* adapter) : adapter_(adapter) {
32 CHECK(adapter_);
33 }
34
~BluetoothLowEnergyBinderServer()35 BluetoothLowEnergyBinderServer::~BluetoothLowEnergyBinderServer() {
36 }
37
RegisterClient(const android::sp<IBluetoothLowEnergyCallback> & callback)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
UnregisterClient(int client_id)47 void BluetoothLowEnergyBinderServer::UnregisterClient(int client_id) {
48 VLOG(2) << __func__;
49 UnregisterInstanceBase(client_id);
50 }
51
UnregisterAll()52 void BluetoothLowEnergyBinderServer::UnregisterAll() {
53 VLOG(2) << __func__;
54 UnregisterAllBase();
55 }
56
Connect(int client_id,const char * address,bool is_direct)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
Disconnect(int client_id,const char * address)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
SetMtu(int client_id,const char * address,int mtu)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
StartScan(int client_id,const bluetooth::ScanSettings & settings,const std::vector<bluetooth::ScanFilter> & filters)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
StopScan(int client_id)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
StartMultiAdvertising(int client_id,const bluetooth::AdvertiseData & advertise_data,const bluetooth::AdvertiseData & scan_response,const bluetooth::AdvertiseSettings & settings)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
StopMultiAdvertising(int client_id)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
OnConnectionState(bluetooth::LowEnergyClient * client,int status,const char * address,bool connected)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
OnMtuChanged(bluetooth::LowEnergyClient * client,int status,const char * address,int mtu)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
OnScanResult(bluetooth::LowEnergyClient * client,const bluetooth::ScanResult & result)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>
GetLECallback(int client_id)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>
GetLEClient(int client_id)275 BluetoothLowEnergyBinderServer::GetLEClient(int client_id) {
276 return std::static_pointer_cast<bluetooth::LowEnergyClient>(
277 GetInstance(client_id));
278 }
279
OnRegisterInstanceImpl(bluetooth::BLEStatus status,android::sp<IInterface> callback,bluetooth::BluetoothInstance * instance)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