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/parcel_helpers.h"
18
19 #include "service/common/bluetooth/util/address_helper.h"
20
21 using android::Parcel;
22
23 using bluetooth::AdvertiseData;
24 using bluetooth::AdvertiseSettings;
25 using bluetooth::GattIdentifier;
26 using bluetooth::ScanFilter;
27 using bluetooth::ScanResult;
28 using bluetooth::ScanSettings;
29 using bluetooth::UUID;
30
31 namespace ipc {
32 namespace binder {
33
34 // TODO(armansito): The helpers below currently don't match the Java
35 // definitions. We need to change the AIDL and framework code to comply with the
36 // new definition and Parcel format provided here.
37
WriteAdvertiseDataToParcel(const AdvertiseData & data,Parcel * parcel)38 void WriteAdvertiseDataToParcel(const AdvertiseData& data, Parcel* parcel) {
39 CHECK(parcel);
40 parcel->writeByteVector(data.data());
41 parcel->writeInt32(data.include_device_name());
42 parcel->writeInt32(data.include_tx_power_level());
43 }
44
CreateAdvertiseDataFromParcel(const Parcel & parcel)45 std::unique_ptr<AdvertiseData> CreateAdvertiseDataFromParcel(
46 const Parcel& parcel) {
47 std::unique_ptr<std::vector<uint8_t>> data;
48 parcel.readByteVector(&data);
49 CHECK(data.get());
50
51 bool include_device_name = parcel.readInt32();
52 bool include_tx_power = parcel.readInt32();
53
54 std::unique_ptr<AdvertiseData> adv(new AdvertiseData(*data));
55 adv->set_include_device_name(include_device_name);
56 adv->set_include_tx_power_level(include_tx_power);
57
58 return adv;
59 }
60
WriteAdvertiseSettingsToParcel(const AdvertiseSettings & settings,Parcel * parcel)61 void WriteAdvertiseSettingsToParcel(const AdvertiseSettings& settings,
62 Parcel* parcel) {
63 CHECK(parcel);
64 parcel->writeInt32(settings.mode());
65 parcel->writeInt32(settings.tx_power_level());
66 parcel->writeInt32(settings.connectable());
67 parcel->writeInt64(settings.timeout().InMilliseconds());
68 }
69
CreateAdvertiseSettingsFromParcel(const Parcel & parcel)70 std::unique_ptr<AdvertiseSettings> CreateAdvertiseSettingsFromParcel(
71 const Parcel& parcel) {
72 AdvertiseSettings::Mode mode =
73 static_cast<AdvertiseSettings::Mode>(parcel.readInt32());
74 AdvertiseSettings::TxPowerLevel tx_power =
75 static_cast<AdvertiseSettings::TxPowerLevel>(parcel.readInt32());
76 bool connectable = parcel.readInt32();
77 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(
78 parcel.readInt64());
79
80 return std::unique_ptr<AdvertiseSettings>(
81 new AdvertiseSettings(mode, timeout, tx_power, connectable));
82 }
83
WriteUUIDToParcel(const UUID & uuid,android::Parcel * parcel)84 void WriteUUIDToParcel(const UUID& uuid, android::Parcel* parcel) {
85 // The scheme used by android.os.ParcelUuid is to wrote the most significant
86 // bits first as one 64-bit integer, followed by the least significant bits in
87 // a second 64-bit integer. This is the same as writing the raw-bytes in
88 // sequence, but we don't want to assume any host-endianness here. So follow
89 // the same scheme and use the same Parcel APIs.
90 UUID::UUID128Bit bytes = uuid.GetFullBigEndian();
91
92 uint64_t most_sig_bits =
93 ((((uint64_t) bytes[0]) << 56) |
94 (((uint64_t) bytes[1]) << 48) |
95 (((uint64_t) bytes[2]) << 40) |
96 (((uint64_t) bytes[3]) << 32) |
97 (((uint64_t) bytes[4]) << 24) |
98 (((uint64_t) bytes[5]) << 16) |
99 (((uint64_t) bytes[6]) << 8) |
100 bytes[7]);
101
102 uint64_t least_sig_bits =
103 ((((uint64_t) bytes[8]) << 56) |
104 (((uint64_t) bytes[9]) << 48) |
105 (((uint64_t) bytes[10]) << 40) |
106 (((uint64_t) bytes[11]) << 32) |
107 (((uint64_t) bytes[12]) << 24) |
108 (((uint64_t) bytes[13]) << 16) |
109 (((uint64_t) bytes[14]) << 8) |
110 bytes[15]);
111
112 parcel->writeUint64(most_sig_bits);
113 parcel->writeUint64(least_sig_bits);
114 }
115
CreateUUIDFromParcel(const android::Parcel & parcel)116 std::unique_ptr<UUID> CreateUUIDFromParcel(
117 const android::Parcel& parcel) {
118 UUID::UUID128Bit bytes;
119
120 uint64_t most_sig_bits = parcel.readUint64();
121 uint64_t least_sig_bits = parcel.readUint64();
122
123 bytes[0] = (most_sig_bits >> 56) & 0xFF;
124 bytes[1] = (most_sig_bits >> 48) & 0xFF;
125 bytes[2] = (most_sig_bits >> 40) & 0xFF;
126 bytes[3] = (most_sig_bits >> 32) & 0xFF;
127 bytes[4] = (most_sig_bits >> 24) & 0xFF;
128 bytes[5] = (most_sig_bits >> 16) & 0xFF;
129 bytes[6] = (most_sig_bits >> 8) & 0xFF;
130 bytes[7] = most_sig_bits & 0xFF;
131
132 bytes[8] = (least_sig_bits >> 56) & 0xFF;
133 bytes[9] = (least_sig_bits >> 48) & 0xFF;
134 bytes[10] = (least_sig_bits >> 40) & 0xFF;
135 bytes[11] = (least_sig_bits >> 32) & 0xFF;
136 bytes[12] = (least_sig_bits >> 24) & 0xFF;
137 bytes[13] = (least_sig_bits >> 16) & 0xFF;
138 bytes[14] = (least_sig_bits >> 8) & 0xFF;
139 bytes[15] = least_sig_bits & 0xFF;
140
141 return std::unique_ptr<UUID>(new UUID(bytes));
142 }
143
WriteGattIdentifierToParcel(const GattIdentifier & gatt_id,android::Parcel * parcel)144 void WriteGattIdentifierToParcel(
145 const GattIdentifier& gatt_id,
146 android::Parcel* parcel) {
147 parcel->writeCString(gatt_id.device_address().c_str());
148 parcel->writeInt32(gatt_id.is_primary());
149
150 WriteUUIDToParcel(gatt_id.service_uuid(), parcel);
151 WriteUUIDToParcel(gatt_id.characteristic_uuid(), parcel);
152 WriteUUIDToParcel(gatt_id.descriptor_uuid(), parcel);
153
154 parcel->writeInt32(gatt_id.service_instance_id());
155 parcel->writeInt32(gatt_id.characteristic_instance_id());
156 parcel->writeInt32(gatt_id.descriptor_instance_id());
157 }
158
CreateGattIdentifierFromParcel(const android::Parcel & parcel)159 std::unique_ptr<GattIdentifier> CreateGattIdentifierFromParcel(
160 const android::Parcel& parcel) {
161 std::string device_address = parcel.readCString();
162 bool is_primary = parcel.readInt32();
163
164 auto service_uuid = CreateUUIDFromParcel(parcel);
165 auto char_uuid = CreateUUIDFromParcel(parcel);
166 auto desc_uuid = CreateUUIDFromParcel(parcel);
167
168 int service_id = parcel.readInt32();
169 int char_id = parcel.readInt32();
170 int desc_id = parcel.readInt32();
171
172 return std::unique_ptr<GattIdentifier>(
173 new GattIdentifier(
174 device_address, is_primary,
175 *service_uuid, *char_uuid, *desc_uuid,
176 service_id, char_id, desc_id));
177 }
178
WriteScanFilterToParcel(const ScanFilter & filter,android::Parcel * parcel)179 void WriteScanFilterToParcel(
180 const ScanFilter& filter,
181 android::Parcel* parcel) {
182 bool has_name = !filter.device_name().empty();
183 parcel->writeInt32(has_name ? 1 : 0);
184 if (has_name)
185 parcel->writeCString(filter.device_name().c_str());
186
187 bool has_address = !filter.device_address().empty();
188 parcel->writeInt32(has_address ? 1 : 0);
189 if (has_address)
190 parcel->writeCString(filter.device_address().c_str());
191
192 parcel->writeInt32(filter.service_uuid() ? 1 : 0);
193 if (filter.service_uuid()) {
194 WriteUUIDToParcel(*filter.service_uuid(), parcel);
195 parcel->writeInt32(filter.service_uuid_mask() ? 1 : 0);
196 if (filter.service_uuid_mask())
197 WriteUUIDToParcel(*filter.service_uuid_mask(), parcel);
198 }
199
200 // TODO(armansito): Support service and manufacturer data.
201 }
202
CreateScanFilterFromParcel(const android::Parcel & parcel)203 std::unique_ptr<ScanFilter> CreateScanFilterFromParcel(
204 const android::Parcel& parcel) {
205 std::string device_name;
206 if (parcel.readInt32() == 1)
207 device_name = parcel.readCString();
208
209 std::string device_address;
210 if (parcel.readInt32() == 1)
211 device_address = parcel.readCString();
212
213 std::unique_ptr<UUID> service_uuid, service_uuid_mask;
214 if (parcel.readInt32() == 1) {
215 service_uuid = CreateUUIDFromParcel(parcel);
216 if (parcel.readInt32() == 1)
217 service_uuid_mask = CreateUUIDFromParcel(parcel);
218 }
219
220 // TODO(armansito): Support service and manufacturer data.
221
222 std::unique_ptr<ScanFilter> filter(new ScanFilter());
223
224 filter->set_device_name(device_name);
225
226 if (!filter->SetDeviceAddress(device_address))
227 return nullptr;
228
229 if (!service_uuid)
230 return filter;
231
232 if (service_uuid_mask)
233 filter->SetServiceUuidWithMask(*service_uuid, *service_uuid_mask);
234 else
235 filter->SetServiceUuid(*service_uuid);
236
237 return filter;
238 }
239
WriteScanSettingsToParcel(const ScanSettings & settings,android::Parcel * parcel)240 void WriteScanSettingsToParcel(
241 const ScanSettings& settings,
242 android::Parcel* parcel) {
243 parcel->writeInt32(settings.mode());
244 parcel->writeInt32(settings.callback_type());
245 parcel->writeInt32(settings.result_type());
246 parcel->writeInt64(settings.report_delay().InMilliseconds());
247 parcel->writeInt32(settings.match_mode());
248 parcel->writeInt32(settings.match_count_per_filter());
249 }
250
CreateScanSettingsFromParcel(const android::Parcel & parcel)251 std::unique_ptr<ScanSettings> CreateScanSettingsFromParcel(
252 const android::Parcel& parcel) {
253 ScanSettings::Mode mode =
254 static_cast<ScanSettings::Mode>(parcel.readInt32());
255 ScanSettings::CallbackType callback_type =
256 static_cast<ScanSettings::CallbackType>(parcel.readInt32());
257 ScanSettings::ResultType result_type =
258 static_cast<ScanSettings::ResultType>(parcel.readInt32());
259 base::TimeDelta report_delay = base::TimeDelta::FromMilliseconds(
260 parcel.readInt64());
261 ScanSettings::MatchMode match_mode =
262 static_cast<ScanSettings::MatchMode>(parcel.readInt32());
263 ScanSettings::MatchCount match_count_per_filter =
264 static_cast<ScanSettings::MatchCount>(parcel.readInt32());
265
266 return std::unique_ptr<ScanSettings>(new ScanSettings(
267 mode, callback_type, result_type, report_delay,
268 match_mode, match_count_per_filter));
269 }
270
WriteScanResultToParcel(const bluetooth::ScanResult & scan_result,android::Parcel * parcel)271 void WriteScanResultToParcel(
272 const bluetooth::ScanResult& scan_result,
273 android::Parcel* parcel) {
274 // The Java framework code conditionally inserts 1 or 0 to indicate if the
275 // device adress and the scan record fields are present, based on whether the
276 // Java object is null. We do something similar here for consistency, although
277 // the native definition of ScanResult requires a valid BD_ADDR.
278 if (util::IsAddressValid(scan_result.device_address())) {
279 parcel->writeInt32(1);
280 parcel->writeCString(scan_result.device_address().c_str());
281 } else {
282 parcel->writeInt32(0);
283 }
284
285 parcel->writeByteVector(scan_result.scan_record());
286 parcel->writeInt32(scan_result.rssi());
287 }
288
CreateScanResultFromParcel(const android::Parcel & parcel)289 std::unique_ptr<bluetooth::ScanResult> CreateScanResultFromParcel(
290 const android::Parcel& parcel) {
291 std::string device_address;
292 if (parcel.readInt32())
293 device_address = parcel.readCString();
294
295 std::unique_ptr<std::vector<uint8_t>> scan_record;
296 parcel.readByteVector(&scan_record);
297 CHECK(scan_record.get());
298
299 int rssi = parcel.readInt32();
300
301 return std::unique_ptr<ScanResult>(new ScanResult(
302 device_address, *scan_record, rssi));
303 }
304 } // namespace binder
305 } // namespace ipc
306