1 /******************************************************************************
2 *
3 * Copyright (C) 2014 Google, Inc.
4 * Copyright (C) 2018 The Linux Foundation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19 #define LOG_TAG "device_iot_config"
20
21 #include "device/include/device_iot_config.h"
22
23 #include <bluetooth/log.h>
24 #include <com_android_bluetooth_flags.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <time.h>
28 #include <unistd.h>
29
30 #include <mutex>
31 #include <string>
32
33 #include "device_iot_config_int.h"
34 #include "internal_include/bt_target.h"
35 #include "os/log.h"
36 #include "osi/include/alarm.h"
37 #include "osi/include/allocator.h"
38 #include "osi/include/compat.h"
39 #include "osi/include/config.h"
40
41 enum ConfigSource device_iot_config_source = NOT_LOADED;
42
43 int device_iot_config_devices_loaded = -1;
44 char device_iot_config_time_created[TIME_STRING_LENGTH];
45
46 std::mutex config_lock; // protects operations on |config|.
47 std::unique_ptr<config_t> config;
48 alarm_t* config_timer;
49
50 using namespace bluetooth;
51
device_iot_config_has_section(const std::string & section)52 bool device_iot_config_has_section(const std::string& section) {
53 if (!com::android::bluetooth::flags::device_iot_config_logging())
54 return false;
55
56 log::assert_that(config != NULL, "assert failed: config != NULL");
57
58 std::unique_lock<std::mutex> lock(config_lock);
59 return config_has_section(*config, section);
60 }
61
device_iot_config_exist(const std::string & section,const std::string & key)62 bool device_iot_config_exist(const std::string& section,
63 const std::string& key) {
64 if (!com::android::bluetooth::flags::device_iot_config_logging())
65 return false;
66
67 log::assert_that(config != NULL, "assert failed: config != NULL");
68
69 std::unique_lock<std::mutex> lock(config_lock);
70 return config_has_key(*config, section, key);
71 }
72
device_iot_config_get_int(const std::string & section,const std::string & key,int & value)73 bool device_iot_config_get_int(const std::string& section,
74 const std::string& key, int& value) {
75 if (!com::android::bluetooth::flags::device_iot_config_logging())
76 return false;
77
78 log::assert_that(config != NULL, "assert failed: config != NULL");
79
80 std::unique_lock<std::mutex> lock(config_lock);
81 bool ret = config_has_key(*config, section, key);
82 if (ret) value = config_get_int(*config, section, key, value);
83
84 return ret;
85 }
86
device_iot_config_set_int(const std::string & section,const std::string & key,int value)87 bool device_iot_config_set_int(const std::string& section,
88 const std::string& key, int value) {
89 if (!com::android::bluetooth::flags::device_iot_config_logging())
90 return false;
91
92 log::assert_that(config != NULL, "assert failed: config != NULL");
93
94 std::unique_lock<std::mutex> lock(config_lock);
95 char value_str[32] = {0};
96 snprintf(value_str, sizeof(value_str), "%d", value);
97 if (device_iot_config_has_key_value(section, key, value_str)) return true;
98
99 config_set_string(config.get(), section, key, value_str);
100 device_iot_config_save_async();
101
102 return true;
103 }
104
device_iot_config_int_add_one(const std::string & section,const std::string & key)105 bool device_iot_config_int_add_one(const std::string& section,
106 const std::string& key) {
107 if (!com::android::bluetooth::flags::device_iot_config_logging())
108 return false;
109
110 log::assert_that(config != NULL, "assert failed: config != NULL");
111
112 int result = 0;
113 std::unique_lock<std::mutex> lock(config_lock);
114 result = config_get_int(*config, section, key, result);
115 if (result >= 0) {
116 result += 1;
117 } else {
118 result = 0;
119 }
120 config_set_int(config.get(), section, key, result);
121 device_iot_config_save_async();
122
123 return true;
124 }
125
device_iot_config_get_hex(const std::string & section,const std::string & key,int & value)126 bool device_iot_config_get_hex(const std::string& section,
127 const std::string& key, int& value) {
128 if (!com::android::bluetooth::flags::device_iot_config_logging())
129 return false;
130
131 log::assert_that(config != NULL, "assert failed: config != NULL");
132
133 std::unique_lock<std::mutex> lock(config_lock);
134 const std::string* stored_value =
135 config_get_string(*config, section, key, NULL);
136 if (!stored_value) return false;
137
138 errno = 0;
139 char* endptr = nullptr;
140 int result = strtoul(stored_value->c_str(), &endptr, 16);
141 if (stored_value->c_str() == endptr) return false;
142 if (endptr == nullptr || endptr[0] != '\0') return false;
143 if (errno) return false;
144
145 value = result;
146 return true;
147 }
148
device_iot_config_set_hex(const std::string & section,const std::string & key,int value,int byte_num)149 bool device_iot_config_set_hex(const std::string& section,
150 const std::string& key, int value,
151 int byte_num) {
152 if (!com::android::bluetooth::flags::device_iot_config_logging())
153 return false;
154
155 log::assert_that(config != NULL, "assert failed: config != NULL");
156
157 char value_str[32] = {0};
158 if (byte_num == 1)
159 snprintf(value_str, sizeof(value_str), "%02x", value);
160 else if (byte_num == 2)
161 snprintf(value_str, sizeof(value_str), "%04x", value);
162 else if (byte_num == 3)
163 snprintf(value_str, sizeof(value_str), "%06x", value);
164 else if (byte_num == 4)
165 snprintf(value_str, sizeof(value_str), "%08x", value);
166
167 std::unique_lock<std::mutex> lock(config_lock);
168 if (device_iot_config_has_key_value(section, key, value_str)) return true;
169
170 config_set_string(config.get(), section, key, value_str);
171 device_iot_config_save_async();
172
173 return true;
174 }
175
device_iot_config_set_hex_if_greater(const std::string & section,const std::string & key,int value,int byte_num)176 bool device_iot_config_set_hex_if_greater(const std::string& section,
177 const std::string& key, int value,
178 int byte_num) {
179 if (!com::android::bluetooth::flags::device_iot_config_logging())
180 return false;
181
182 int stored_value = 0;
183 bool ret = device_iot_config_get_hex(section, key, stored_value);
184 if (ret && stored_value >= value) return true;
185
186 return device_iot_config_set_hex(section, key, value, byte_num);
187 }
188
device_iot_config_get_str(const std::string & section,const std::string & key,char * value,int * size_bytes)189 bool device_iot_config_get_str(const std::string& section,
190 const std::string& key, char* value,
191 int* size_bytes) {
192 if (!com::android::bluetooth::flags::device_iot_config_logging())
193 return false;
194
195 log::assert_that(config != NULL, "assert failed: config != NULL");
196 log::assert_that(value != NULL, "assert failed: value != NULL");
197 log::assert_that(size_bytes != NULL, "assert failed: size_bytes != NULL");
198
199 std::unique_lock<std::mutex> lock(config_lock);
200 const std::string* stored_value =
201 config_get_string(*config, section, key, NULL);
202
203 if (!stored_value) return false;
204
205 strlcpy(value, stored_value->c_str(), *size_bytes);
206 *size_bytes = strlen(value) + 1;
207
208 return true;
209 }
210
device_iot_config_set_str(const std::string & section,const std::string & key,const std::string & value)211 bool device_iot_config_set_str(const std::string& section,
212 const std::string& key,
213 const std::string& value) {
214 if (!com::android::bluetooth::flags::device_iot_config_logging())
215 return false;
216
217 log::assert_that(config != NULL, "assert failed: config != NULL");
218
219 std::unique_lock<std::mutex> lock(config_lock);
220 if (device_iot_config_has_key_value(section, key, value)) return true;
221
222 config_set_string(config.get(), section, key, value);
223 device_iot_config_save_async();
224
225 return true;
226 }
227
device_iot_config_get_bin(const std::string & section,const std::string & key,uint8_t * value,size_t * length)228 bool device_iot_config_get_bin(const std::string& section,
229 const std::string& key, uint8_t* value,
230 size_t* length) {
231 if (!com::android::bluetooth::flags::device_iot_config_logging())
232 return false;
233
234 log::assert_that(config != NULL, "assert failed: config != NULL");
235 log::assert_that(value != NULL, "assert failed: value != NULL");
236 log::assert_that(length != NULL, "assert failed: length != NULL");
237
238 std::unique_lock<std::mutex> lock(config_lock);
239 const std::string* value_string =
240 config_get_string(*config, section, key, NULL);
241
242 if (!value_string) return false;
243
244 const char* value_str = value_string->c_str();
245
246 size_t value_len = strlen(value_str);
247 if ((value_len % 2) != 0 || *length < (value_len / 2)) return false;
248
249 for (size_t i = 0; i < value_len; ++i)
250 if (!isxdigit(value_str[i])) return false;
251
252 for (*length = 0; *value_str; value_str += 2, *length += 1) {
253 errno = 0;
254 char* endptr = nullptr;
255 value[*length] = strtoul(value_str, &endptr, 16);
256 if (value_str == endptr) return false;
257 if (*endptr) return false;
258 if (errno) return false;
259 }
260
261 return true;
262 }
263
device_iot_config_get_bin_length(const std::string & section,const std::string & key)264 size_t device_iot_config_get_bin_length(const std::string& section,
265 const std::string& key) {
266 if (!com::android::bluetooth::flags::device_iot_config_logging()) return 0;
267
268 log::assert_that(config != NULL, "assert failed: config != NULL");
269
270 std::unique_lock<std::mutex> lock(config_lock);
271 const std::string* value_str = config_get_string(*config, section, key, NULL);
272
273 if (!value_str) return 0;
274
275 size_t value_len = strlen(value_str->c_str());
276 return ((value_len % 2) != 0) ? 0 : (value_len / 2);
277 }
278
device_iot_config_set_bin(const std::string & section,const std::string & key,const uint8_t * value,size_t length)279 bool device_iot_config_set_bin(const std::string& section,
280 const std::string& key, const uint8_t* value,
281 size_t length) {
282 if (!com::android::bluetooth::flags::device_iot_config_logging())
283 return false;
284
285 const char* lookup = "0123456789abcdef";
286
287 log::assert_that(config != NULL, "assert failed: config != NULL");
288
289 log::verbose("Key = {}", key);
290 if (length > 0)
291 log::assert_that(value != NULL, "assert failed: value != NULL");
292
293 char* str = (char*)osi_calloc(length * 2 + 1);
294 if (str == NULL) {
295 log::error("Unable to allocate a str.");
296 return false;
297 }
298
299 for (size_t i = 0; i < length; ++i) {
300 str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F];
301 str[(i * 2) + 1] = lookup[value[i] & 0x0F];
302 }
303
304 std::unique_lock<std::mutex> lock(config_lock);
305 if (device_iot_config_has_key_value(section, key, str)) {
306 osi_free(str);
307 return true;
308 }
309
310 config_set_string(config.get(), section, key, str);
311 device_iot_config_save_async();
312
313 osi_free(str);
314 return true;
315 }
316
device_iot_config_remove(const std::string & section,const std::string & key)317 bool device_iot_config_remove(const std::string& section,
318 const std::string& key) {
319 if (!com::android::bluetooth::flags::device_iot_config_logging())
320 return false;
321
322 log::assert_that(config != NULL, "assert failed: config != NULL");
323
324 std::unique_lock<std::mutex> lock(config_lock);
325 return config_remove_key(config.get(), section, key);
326 }
327
device_iot_config_flush(void)328 void device_iot_config_flush(void) {
329 if (!com::android::bluetooth::flags::device_iot_config_logging()) return;
330
331 log::assert_that(config != NULL, "assert failed: config != NULL");
332 log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL");
333
334 int event = alarm_is_scheduled(config_timer) ? IOT_CONFIG_SAVE_TIMER_FIRED_EVT
335 : IOT_CONFIG_FLUSH_EVT;
336 log::verbose("evt={}", event);
337 alarm_cancel(config_timer);
338 device_iot_config_write(event, NULL);
339 }
340
device_iot_config_clear(void)341 bool device_iot_config_clear(void) {
342 if (!com::android::bluetooth::flags::device_iot_config_logging()) return true;
343
344 log::assert_that(config != NULL, "assert failed: config != NULL");
345 log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL");
346
347 log::info("");
348 alarm_cancel(config_timer);
349
350 std::unique_lock<std::mutex> lock(config_lock);
351 config.reset();
352
353 config = config_new_empty();
354 if (config == NULL) {
355 return false;
356 }
357
358 bool ret = config_save(*config, IOT_CONFIG_FILE_PATH);
359 device_iot_config_source = RESET;
360 return ret;
361 }
362
device_debug_iot_config_dump(int fd)363 void device_debug_iot_config_dump(int fd) {
364 if (!com::android::bluetooth::flags::device_iot_config_logging()) return;
365
366 dprintf(fd, "\nBluetooth Iot Config:\n");
367
368 dprintf(fd, " Config Source: ");
369 switch (device_iot_config_source) {
370 case NOT_LOADED:
371 dprintf(fd, "Not loaded\n");
372 break;
373 case ORIGINAL:
374 dprintf(fd, "Original file\n");
375 break;
376 case BACKUP:
377 dprintf(fd, "Backup file\n");
378 break;
379 case NEW_FILE:
380 dprintf(fd, "New file\n");
381 break;
382 case RESET:
383 dprintf(fd, "Reset file\n");
384 break;
385 }
386
387 dprintf(fd, " Devices loaded: %d\n", device_iot_config_devices_loaded);
388 dprintf(fd, " File created/tagged: %s\n", device_iot_config_time_created);
389 }
390