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