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/common/bluetooth/binder/IBluetoothLowEnergy.h"
18
19 #include <base/logging.h>
20 #include <binder/Parcel.h>
21
22 #include "service/common/bluetooth/binder/parcel_helpers.h"
23
24 using android::IBinder;
25 using android::interface_cast;
26 using android::Parcel;
27 using android::sp;
28 using android::status_t;
29
30 using bluetooth::AdvertiseData;
31 using bluetooth::AdvertiseSettings;
32
33 namespace ipc {
34 namespace binder {
35
36 // static
37 const char IBluetoothLowEnergy::kServiceName[] =
38 "bluetooth-low-energy-service";
39
40 // BnBluetoothLowEnergy (server) implementation
41 // ========================================================
42
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)43 status_t BnBluetoothLowEnergy::onTransact(
44 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
45 VLOG(2) << "IBluetoothLowEnergy: " << code;
46 if (!data.checkInterface(this))
47 return android::PERMISSION_DENIED;
48
49 switch (code) {
50 case REGISTER_CLIENT_TRANSACTION: {
51 sp<IBinder> callback = data.readStrongBinder();
52 bool result = RegisterClient(
53 interface_cast<IBluetoothLowEnergyCallback>(callback));
54
55 reply->writeInt32(result);
56
57 return android::NO_ERROR;
58 }
59 case UNREGISTER_CLIENT_TRANSACTION: {
60 int client_id = data.readInt32();
61 UnregisterClient(client_id);
62 return android::NO_ERROR;
63 }
64 case UNREGISTER_ALL_TRANSACTION: {
65 UnregisterAll();
66 return android::NO_ERROR;
67 }
68 case CONNECT_TRANSACTION: {
69 int client_id = data.readInt32();
70 const char* address = data.readCString();
71 bool is_direct = data.readBool();
72
73 bool result = Connect(client_id, address, is_direct);
74 reply->writeInt32(result);
75
76 return android::NO_ERROR;
77 }
78 case DISCONNECT_TRANSACTION: {
79 int client_id = data.readInt32();
80 const char* address = data.readCString();
81
82 bool result = Disconnect(client_id, address);
83 reply->writeInt32(result);
84
85 return android::NO_ERROR;
86 }
87 case SET_MTU_TRANSACTION: {
88 int client_id = data.readInt32();
89 const char* address = data.readCString();
90 int mtu = data.readInt32();
91
92 bool result = SetMtu(client_id, address, mtu);
93 reply->writeInt32(result);
94
95 return android::NO_ERROR;
96 }
97 case START_SCAN_TRANSACTION: {
98 int client_id = data.readInt32();
99 auto settings = CreateScanSettingsFromParcel(data);
100 CHECK(settings);
101 std::vector<bluetooth::ScanFilter> filters;
102
103 int list_meta_data = data.readInt32();
104 CHECK(list_meta_data == kParcelValList);
105
106 int filter_count = data.readInt32();
107 if (filter_count >= 0) { // Make sure |filter_count| isn't negative.
108 for (int i = 0; i < filter_count; i++) {
109 auto filter = CreateScanFilterFromParcel(data);
110 CHECK(filter);
111 filters.push_back(*filter);
112 }
113 }
114
115 bool result = StartScan(client_id, *settings, filters);
116 reply->writeInt32(result);
117
118 return android::NO_ERROR;
119 }
120 case STOP_SCAN_TRANSACTION: {
121 int client_id = data.readInt32();
122 bool result = StopScan(client_id);
123 reply->writeInt32(result);
124 return android::NO_ERROR;
125 }
126 case START_MULTI_ADVERTISING_TRANSACTION: {
127 int client_id = data.readInt32();
128 std::unique_ptr<AdvertiseData> adv_data =
129 CreateAdvertiseDataFromParcel(data);
130 std::unique_ptr<AdvertiseData> scan_rsp =
131 CreateAdvertiseDataFromParcel(data);
132 std::unique_ptr<AdvertiseSettings> adv_settings =
133 CreateAdvertiseSettingsFromParcel(data);
134
135 bool result = StartMultiAdvertising(
136 client_id, *adv_data, *scan_rsp, *adv_settings);
137
138 reply->writeInt32(result);
139
140 return android::NO_ERROR;
141 }
142 case STOP_MULTI_ADVERTISING_TRANSACTION: {
143 int client_id = data.readInt32();
144 bool result = StopMultiAdvertising(client_id);
145
146 reply->writeInt32(result);
147
148 return android::NO_ERROR;
149 }
150 default:
151 return BBinder::onTransact(code, data, reply, flags);
152 }
153 }
154
155 // BpBluetoothLowEnergy (client) implementation
156 // ========================================================
157
BpBluetoothLowEnergy(const sp<IBinder> & impl)158 BpBluetoothLowEnergy::BpBluetoothLowEnergy(const sp<IBinder>& impl)
159 : BpInterface<IBluetoothLowEnergy>(impl) {
160 }
161
RegisterClient(const sp<IBluetoothLowEnergyCallback> & callback)162 bool BpBluetoothLowEnergy::RegisterClient(
163 const sp<IBluetoothLowEnergyCallback>& callback) {
164 Parcel data, reply;
165
166 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
167 data.writeStrongBinder(IInterface::asBinder(callback.get()));
168
169 remote()->transact(IBluetoothLowEnergy::REGISTER_CLIENT_TRANSACTION,
170 data, &reply);
171
172 return reply.readInt32();
173 }
174
UnregisterClient(int client_id)175 void BpBluetoothLowEnergy::UnregisterClient(int client_id) {
176 Parcel data, reply;
177
178 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
179 data.writeInt32(client_id);
180
181 remote()->transact(IBluetoothLowEnergy::UNREGISTER_CLIENT_TRANSACTION,
182 data, &reply);
183 }
184
UnregisterAll()185 void BpBluetoothLowEnergy::UnregisterAll() {
186 Parcel data, reply;
187
188 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
189
190 remote()->transact(IBluetoothLowEnergy::UNREGISTER_ALL_TRANSACTION,
191 data, &reply);
192 }
193
Connect(int client_id,const char * address,bool is_direct)194 bool BpBluetoothLowEnergy::Connect(int client_id, const char* address,
195 bool is_direct) {
196 Parcel data, reply;
197
198 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
199 data.writeInt32(client_id);
200 data.writeCString(address);
201 data.writeBool(is_direct);
202
203 remote()->transact(IBluetoothLowEnergy::CONNECT_TRANSACTION,
204 data, &reply);
205
206 return reply.readInt32();
207 }
208
Disconnect(int client_id,const char * address)209 bool BpBluetoothLowEnergy::Disconnect(int client_id, const char* address) {
210 Parcel data, reply;
211
212 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
213 data.writeInt32(client_id);
214 data.writeCString(address);
215
216 remote()->transact(IBluetoothLowEnergy::DISCONNECT_TRANSACTION,
217 data, &reply);
218
219 return reply.readInt32();
220 }
221
SetMtu(int client_id,const char * address,int mtu)222 bool BpBluetoothLowEnergy::SetMtu(int client_id, const char* address, int mtu) {
223 Parcel data, reply;
224
225 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
226 data.writeInt32(client_id);
227 data.writeCString(address);
228 data.writeInt32(mtu);
229
230 remote()->transact(IBluetoothLowEnergy::SET_MTU_TRANSACTION, data, &reply);
231 return reply.readInt32();
232 }
233
StartScan(int client_id,const bluetooth::ScanSettings & settings,const std::vector<bluetooth::ScanFilter> & filters)234 bool BpBluetoothLowEnergy::StartScan(
235 int client_id,
236 const bluetooth::ScanSettings& settings,
237 const std::vector<bluetooth::ScanFilter>& filters) {
238 Parcel data, reply;
239
240 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
241 data.writeInt32(client_id);
242 WriteScanSettingsToParcel(settings, &data);
243
244 // The Java equivalent of |filters| is a List<ScanFilter>. Parcel.java inserts
245 // a metadata value of VAL_LIST (11) for this so I'm doing it here for
246 // compatibility.
247 data.writeInt32(kParcelValList);
248 data.writeInt32(filters.size());
249 for (const auto& filter : filters)
250 WriteScanFilterToParcel(filter, &data);
251
252 remote()->transact(IBluetoothLowEnergy::START_SCAN_TRANSACTION,
253 data, &reply);
254
255 return reply.readInt32();
256 }
257
StopScan(int client_id)258 bool BpBluetoothLowEnergy::StopScan(int client_id) {
259 Parcel data, reply;
260
261 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
262 data.writeInt32(client_id);
263
264 remote()->transact(IBluetoothLowEnergy::STOP_SCAN_TRANSACTION,
265 data, &reply);
266
267 return reply.readInt32();
268 }
269
StartMultiAdvertising(int client_id,const AdvertiseData & advertise_data,const AdvertiseData & scan_response,const AdvertiseSettings & settings)270 bool BpBluetoothLowEnergy::StartMultiAdvertising(
271 int client_id,
272 const AdvertiseData& advertise_data,
273 const AdvertiseData& scan_response,
274 const AdvertiseSettings& settings) {
275 Parcel data, reply;
276
277 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
278 data.writeInt32(client_id);
279 WriteAdvertiseDataToParcel(advertise_data, &data);
280 WriteAdvertiseDataToParcel(scan_response, &data);
281 WriteAdvertiseSettingsToParcel(settings, &data);
282
283 remote()->transact(IBluetoothLowEnergy::START_MULTI_ADVERTISING_TRANSACTION,
284 data, &reply);
285
286 return reply.readInt32();
287 }
288
StopMultiAdvertising(int client_id)289 bool BpBluetoothLowEnergy::StopMultiAdvertising(int client_id) {
290 Parcel data, reply;
291
292 data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
293 data.writeInt32(client_id);
294
295 remote()->transact(IBluetoothLowEnergy::STOP_MULTI_ADVERTISING_TRANSACTION,
296 data, &reply);
297
298 return reply.readInt32();
299 }
300
301 IMPLEMENT_META_INTERFACE(BluetoothLowEnergy, IBluetoothLowEnergy::kServiceName);
302
303 } // namespace binder
304 } // namespace ipc
305