1 // Generated by the sysprop generator. DO NOT EDIT!
2 
3 #include <ApexProperties.sysprop.h>
4 
5 #include <cctype>
6 #include <cerrno>
7 #include <cstdio>
8 #include <cstring>
9 #include <limits>
10 #include <utility>
11 
12 #include <strings.h>
13 #ifdef __BIONIC__
14 #include <sys/system_properties.h>
SetProp(const char * key,const char * value)15 [[maybe_unused]] static bool SetProp(const char* key, const char* value) {
16     return __system_property_set(key, value) == 0;
17 }
18 #else
19 #include <android-base/properties.h>
SetProp(const char * key,const char * value)20 [[maybe_unused]] static bool SetProp(const char* key, const char* value) {
21     android::base::SetProperty(key, value);
22     return true;
23 }
24 #endif
25 
26 #include <android-base/parseint.h>
27 #include <log/log.h>
28 
29 namespace {
30 
31 using namespace android::sysprop::ApexProperties;
32 
33 template <typename T> T DoParse(const char* str);
34 
35 template <typename T> constexpr bool is_vector = false;
36 
37 template <typename T> constexpr bool is_vector<std::vector<T>> = true;
38 
DoParse(const char * str)39 template <> [[maybe_unused]] std::optional<bool> DoParse(const char* str) {
40     static constexpr const char* kYes[] = {"1", "true"};
41     static constexpr const char* kNo[] = {"0", "false"};
42 
43     for (const char* yes : kYes) {
44         if (strcasecmp(yes, str) == 0) return std::make_optional(true);
45     }
46 
47     for (const char* no : kNo) {
48         if (strcasecmp(no, str) == 0) return std::make_optional(false);
49     }
50 
51     return std::nullopt;
52 }
53 
DoParse(const char * str)54 template <> [[maybe_unused]] std::optional<std::int32_t> DoParse(const char* str) {
55     std::int32_t ret;
56     return android::base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt;
57 }
58 
DoParse(const char * str)59 template <> [[maybe_unused]] std::optional<std::uint32_t> DoParse(const char* str) {
60     std::uint32_t ret;
61     return android::base::ParseUint(str, &ret) ? std::make_optional(ret) : std::nullopt;
62 }
63 
DoParse(const char * str)64 template <> [[maybe_unused]] std::optional<std::int64_t> DoParse(const char* str) {
65     std::int64_t ret;
66     return android::base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt;
67 }
68 
DoParse(const char * str)69 template <> [[maybe_unused]] std::optional<std::uint64_t> DoParse(const char* str) {
70     std::uint64_t ret;
71     return android::base::ParseUint(str, &ret) ? std::make_optional(ret) : std::nullopt;
72 }
73 
DoParse(const char * str)74 template <> [[maybe_unused]] std::optional<double> DoParse(const char* str) {
75     int old_errno = errno;
76     errno = 0;
77     char* end;
78     double ret = std::strtod(str, &end);
79     if (errno != 0) {
80         return std::nullopt;
81     }
82     if (str == end || *end != '\0') {
83         errno = EINVAL;
84         return std::nullopt;
85     }
86     errno = old_errno;
87     return std::make_optional(ret);
88 }
89 
DoParse(const char * str)90 template <> [[maybe_unused]] std::optional<std::string> DoParse(const char* str) {
91     return *str == '\0' ? std::nullopt : std::make_optional(str);
92 }
93 
DoParseList(const char * str)94 template <typename Vec> [[maybe_unused]] Vec DoParseList(const char* str) {
95     Vec ret;
96     if (*str == '\0') return ret;
97     const char* p = str;
98     for (;;) {
99         const char* r = p;
100         std::string value;
101         while (*r != ',') {
102             if (*r == '\\') ++r;
103             if (*r == '\0') break;
104             value += *r++;
105         }
106         ret.emplace_back(DoParse<typename Vec::value_type>(value.c_str()));
107         if (*r == '\0') break;
108         p = r + 1;
109     }
110     return ret;
111 }
112 
TryParse(const char * str)113 template <typename T> inline T TryParse(const char* str) {
114     if constexpr(is_vector<T>) {
115         return DoParseList<T>(str);
116     } else {
117         return DoParse<T>(str);
118     }
119 }
120 
FormatValue(const std::optional<std::int32_t> & value)121 [[maybe_unused]] std::string FormatValue(const std::optional<std::int32_t>& value) {
122     return value ? std::to_string(*value) : "";
123 }
124 
FormatValue(const std::optional<std::uint32_t> & value)125 [[maybe_unused]] std::string FormatValue(const std::optional<std::uint32_t>& value) {
126     return value ? std::to_string(*value) : "";
127 }
128 
FormatValue(const std::optional<std::int64_t> & value)129 [[maybe_unused]] std::string FormatValue(const std::optional<std::int64_t>& value) {
130     return value ? std::to_string(*value) : "";
131 }
132 
FormatValue(const std::optional<std::uint64_t> & value)133 [[maybe_unused]] std::string FormatValue(const std::optional<std::uint64_t>& value) {
134     return value ? std::to_string(*value) : "";
135 }
136 
FormatValue(const std::optional<double> & value)137 [[maybe_unused]] std::string FormatValue(const std::optional<double>& value) {
138     if (!value) return "";
139     char buf[1024];
140     std::sprintf(buf, "%.*g", std::numeric_limits<double>::max_digits10, *value);
141     return buf;
142 }
143 
FormatValue(const std::optional<bool> & value)144 [[maybe_unused]] std::string FormatValue(const std::optional<bool>& value) {
145     return value ? (*value ? "true" : "false") : "";
146 }
147 
148 template <typename T>
FormatValue(const std::vector<T> & value)149 [[maybe_unused]] std::string FormatValue(const std::vector<T>& value) {
150     if (value.empty()) return "";
151 
152     std::string ret;
153     bool first = true;
154 
155     for (auto&& element : value) {
156         if (!first) ret += ',';
157         else first = false;
158         if constexpr(std::is_same_v<T, std::optional<std::string>>) {
159             if (element) {
160                 for (char c : *element) {
161                     if (c == '\\' || c == ',') ret += '\\';
162                     ret += c;
163                 }
164             }
165         } else {
166             ret += FormatValue(element);
167         }
168     }
169 
170     return ret;
171 }
172 
173 template <typename T>
GetProp(const char * key,const char * legacy=nullptr)174 T GetProp(const char* key, const char* legacy = nullptr) {
175     std::string value;
176 #ifdef __BIONIC__
177     auto pi = __system_property_find(key);
178     if (pi != nullptr) {
179         __system_property_read_callback(pi, [](void* cookie, const char*, const char* value, std::uint32_t) {
180             *static_cast<std::string*>(cookie) = value;
181         }, &value);
182     }
183 #else
184     value = android::base::GetProperty(key, "");
185 #endif
186     if (value.empty() && legacy) {
187         ALOGV("prop %s doesn't exist; fallback to legacy prop %s", key, legacy);
188         return GetProp<T>(legacy);
189     }
190     return TryParse<T>(value.c_str());
191 }
192 
193 }  // namespace
194 
195 namespace android::sysprop::ApexProperties {
196 
updatable()197 std::optional<bool> updatable() {
198     return GetProp<std::optional<bool>>("ro.apex.updatable");
199 }
200 
dm_delete_timeout()201 std::optional<std::uint32_t> dm_delete_timeout() {
202     return GetProp<std::optional<std::uint32_t>>("apexd.config.dm_delete.timeout");
203 }
204 
dm_create_timeout()205 std::optional<std::uint32_t> dm_create_timeout() {
206     return GetProp<std::optional<std::uint32_t>>("apexd.config.dm_create.timeout");
207 }
208 
loop_wait_attempts()209 std::optional<std::uint32_t> loop_wait_attempts() {
210     return GetProp<std::optional<std::uint32_t>>("apexd.config.loop_wait.attempts");
211 }
212 
boot_activation_threads()213 std::optional<std::uint32_t> boot_activation_threads() {
214     return GetProp<std::optional<std::uint32_t>>("apexd.config.boot_activation.threads");
215 }
216 
loopback_readahead()217 std::optional<std::uint32_t> loopback_readahead() {
218     return GetProp<std::optional<std::uint32_t>>("apexd.config.loopback.readahead");
219 }
220 
221 }  // namespace android::sysprop::ApexProperties
222