1 /******************************************************************************
2  *
3  *  Copyright 2016 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #include "osi/include/properties.h"
20 
21 #include <string.h>
22 
23 #include <algorithm>
24 #include <optional>
25 #include <string>
26 
27 #include "os/system_properties.h"
28 
29 #ifdef __ANDROID__
30 #undef PROPERTY_VALUE_MAX
31 #include <cutils/properties.h>
32 #if BUILD_SANITY_PROPERTY_VALUE_MAX != PROPERTY_VALUE_MAX
33 #error "PROPERTY_VALUE_MAX from osi/include/properties.h != the Android value"
34 #endif  // GENERIC_PROPERTY_VALUE_MAX != PROPERTY_VALUE_MAX
35 #endif  // __ANDROID__
36 
osi_property_get(const char * key,char * value,const char * default_value)37 int osi_property_get(const char* key, char* value, const char* default_value) {
38   std::optional<std::string> result = bluetooth::os::GetSystemProperty(key);
39   if (result) {
40     memcpy(value, result->data(), result->size());
41     value[result->size()] = '\0';
42     return result->size();
43   } else if (default_value) {
44     int len = std::min(strlen(default_value), (size_t)(PROPERTY_VALUE_MAX - 1));
45     memcpy(value, default_value, len);
46     value[len] = '\0';
47     return len;
48   } else {
49     return 0;
50   }
51 }
52 
osi_property_set(const char * key,const char * value)53 int osi_property_set(const char* key, const char* value) {
54   bool success = bluetooth::os::SetSystemProperty(key, value);
55   return success ? 0 : -1;
56 }
57 
osi_property_get_int32(const char * key,int32_t default_value)58 int32_t osi_property_get_int32(const char* key, int32_t default_value) {
59   std::optional<std::string> result = bluetooth::os::GetSystemProperty(key);
60   if (result) {
61     return stoi(*result, nullptr);
62   } else {
63     return default_value;
64   }
65 }
66 
osi_property_get_bool(const char * key,bool default_value)67 bool osi_property_get_bool(const char* key, bool default_value) {
68   std::optional<std::string> result = bluetooth::os::GetSystemProperty(key);
69   if (result) {
70     return *result == std::string("true");
71   } else {
72     return default_value;
73   }
74 }
75 
osi_property_get_uintlist(const char * key,const std::vector<uint32_t> default_value)76 std::vector<uint32_t> osi_property_get_uintlist(const char* key,
77                                                 const std::vector<uint32_t> default_value) {
78   std::optional<std::string> result = bluetooth::os::GetSystemProperty(key);
79   if (!result || result->empty() || result->size() > PROPERTY_VALUE_MAX) {
80     return default_value;
81   }
82 
83   std::vector<uint32_t> list;
84   for (size_t i = 0; i < result->size(); i++) {
85     // Build a string of all the chars until the next comma or end of the
86     // string is reached. If any char is not a digit, then return the default.
87     std::string value;
88     while ((*result)[i] != ',' && i < result->size()) {
89       char c = (*result)[i];
90       if (!std::isdigit(c)) {
91         return default_value;
92       }
93       value += c;
94       i++;
95     }
96 
97     // grab value
98     list.push_back(static_cast<uint32_t>(std::stoul(value)));
99   }
100 
101   return list;
102 }
103