11e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes/* 21e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * Copyright (C) 2016 The Android Open Source Project 31e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * 41e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 51e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * you may not use this file except in compliance with the License. 61e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * You may obtain a copy of the License at 71e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * 81e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 91e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * 101e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * Unless required by applicable law or agreed to in writing, software 111e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 121e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * See the License for the specific language governing permissions and 141e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes * limitations under the License. 151e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes */ 161e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 17b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 18b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes 191e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes#include "android-base/properties.h" 201e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 211e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes#include <sys/system_properties.h> 22b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes#include <sys/_system_properties.h> 231e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 2403edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes#include <algorithm> 2503edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes#include <chrono> 261e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes#include <string> 271e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 281e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes#include <android-base/parseint.h> 291e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 3003edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughesusing namespace std::chrono_literals; 3103edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes 321e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughesnamespace android { 331e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughesnamespace base { 341e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 351e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughesstd::string GetProperty(const std::string& key, const std::string& default_value) { 361e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes const prop_info* pi = __system_property_find(key.c_str()); 371e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes if (pi == nullptr) return default_value; 381e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 391e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes char buf[PROP_VALUE_MAX]; 401e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes if (__system_property_read(pi, nullptr, buf) > 0) return buf; 411e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 421e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes // If the property exists but is empty, also return the default value. 431e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes // Since we can't remove system properties, "empty" is traditionally 441e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes // the same as "missing" (this was true for cutils' property_get). 451e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes return default_value; 461e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes} 471e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 481e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughesbool GetBoolProperty(const std::string& key, bool default_value) { 491e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes std::string value = GetProperty(key, ""); 501e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes if (value == "1" || value == "y" || value == "yes" || value == "on" || value == "true") { 511e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes return true; 521e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes } else if (value == "0" || value == "n" || value == "no" || value == "off" || value == "false") { 531e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes return false; 541e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes } 551e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes return default_value; 561e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes} 571e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 581e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate <typename T> 591e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott HughesT GetIntProperty(const std::string& key, T default_value, T min, T max) { 601e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes T result; 611e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes std::string value = GetProperty(key, ""); 62da46b392f10d2809b5696632f67485f272ec5698Elliott Hughes if (!value.empty() && android::base::ParseInt(value, &result, min, max)) return result; 631e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes return default_value; 641e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes} 651e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 661e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate <typename T> 671e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott HughesT GetUintProperty(const std::string& key, T default_value, T max) { 681e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes T result; 691e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes std::string value = GetProperty(key, ""); 70da46b392f10d2809b5696632f67485f272ec5698Elliott Hughes if (!value.empty() && android::base::ParseUint(value, &result, max)) return result; 711e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes return default_value; 721e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes} 731e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 741e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate int8_t GetIntProperty(const std::string&, int8_t, int8_t, int8_t); 751e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate int16_t GetIntProperty(const std::string&, int16_t, int16_t, int16_t); 761e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate int32_t GetIntProperty(const std::string&, int32_t, int32_t, int32_t); 771e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate int64_t GetIntProperty(const std::string&, int64_t, int64_t, int64_t); 781e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 791e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate uint8_t GetUintProperty(const std::string&, uint8_t, uint8_t); 801e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate uint16_t GetUintProperty(const std::string&, uint16_t, uint16_t); 811e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate uint32_t GetUintProperty(const std::string&, uint32_t, uint32_t); 821e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughestemplate uint64_t GetUintProperty(const std::string&, uint64_t, uint64_t); 831e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 841e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughesbool SetProperty(const std::string& key, const std::string& value) { 851e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes return (__system_property_set(key.c_str(), value.c_str()) == 0); 861e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes} 871e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes 88b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughesstruct WaitForPropertyData { 89b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes bool done; 90b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes const std::string* expected_value; 91b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes unsigned last_read_serial; 92b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes}; 93b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes 94b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughesstatic void WaitForPropertyCallback(void* data_ptr, const char*, const char* value, unsigned serial) { 95b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes WaitForPropertyData* data = reinterpret_cast<WaitForPropertyData*>(data_ptr); 96b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes if (*data->expected_value == value) { 97b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes data->done = true; 98b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes } else { 99b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes data->last_read_serial = serial; 100b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes } 101b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes} 102b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes 10303edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes// TODO: chrono_utils? 10403edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughesstatic void DurationToTimeSpec(timespec& ts, std::chrono::nanoseconds d) { 10503edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes auto s = std::chrono::duration_cast<std::chrono::seconds>(d); 10603edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - s); 10703edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes ts.tv_sec = s.count(); 10803edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes ts.tv_nsec = ns.count(); 10903edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes} 11003edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes 111e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Parkusing AbsTime = std::chrono::time_point<std::chrono::steady_clock>; 112e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park 11303edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughesstatic void UpdateTimeSpec(timespec& ts, 114e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park const AbsTime& timeout) { 11503edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes auto now = std::chrono::steady_clock::now(); 11603edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes auto remaining_timeout = std::chrono::duration_cast<std::chrono::nanoseconds>(timeout - now); 11703edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes if (remaining_timeout < 0ns) { 11803edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes ts = { 0, 0 }; 11903edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes } else { 12003edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes DurationToTimeSpec(ts, remaining_timeout); 12103edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes } 12203edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes} 12303edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes 124e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park// Waits for the system property `key` to be created. 125e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park// Times out after `relative_timeout`. 126e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park// Sets absolute_timeout which represents absolute time for the timeout. 127e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park// Returns nullptr on timeout. 128e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Parkstatic const prop_info* WaitForPropertyCreation(const std::string& key, 129e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park const std::chrono::milliseconds& relative_timeout, 130e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park AbsTime& absolute_timeout) { 13103edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes // TODO: boot_clock? 13203edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes auto now = std::chrono::steady_clock::now(); 133e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park absolute_timeout = now + relative_timeout; 13403edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes 135b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes // Find the property's prop_info*. 136b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes const prop_info* pi; 137b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes unsigned global_serial = 0; 138b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes while ((pi = __system_property_find(key.c_str())) == nullptr) { 139b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes // The property doesn't even exist yet. 140b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes // Wait for a global change and then look again. 141e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park timespec ts; 14203edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes UpdateTimeSpec(ts, absolute_timeout); 143e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park if (!__system_property_wait(nullptr, global_serial, &global_serial, &ts)) return nullptr; 144b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes } 145e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park return pi; 146e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park} 147e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park 148e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Parkbool WaitForProperty(const std::string& key, 149e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park const std::string& expected_value, 150e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park std::chrono::milliseconds relative_timeout) { 151e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park AbsTime absolute_timeout; 152e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park const prop_info* pi = WaitForPropertyCreation(key, relative_timeout, absolute_timeout); 153e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park if (pi == nullptr) return false; 154b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes 155b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes WaitForPropertyData data; 156b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes data.expected_value = &expected_value; 157b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes data.done = false; 158b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes while (true) { 159e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park timespec ts; 160b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes // Check whether the property has the value we're looking for? 161b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes __system_property_read_callback(pi, WaitForPropertyCallback, &data); 16203edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes if (data.done) return true; 163b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes 16403edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes // It didn't, so wait for the property to change before checking again. 16503edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes UpdateTimeSpec(ts, absolute_timeout); 16603edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes uint32_t unused; 16703edc9f7647b3ac9db8a4743acc98b0238b846fbElliott Hughes if (!__system_property_wait(pi, data.last_read_serial, &unused, &ts)) return false; 168b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes } 169b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes} 170b30769a87acc15fc7f628d8541cdf97aba22e2e2Elliott Hughes 171e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Parkbool WaitForPropertyCreation(const std::string& key, 172e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park std::chrono::milliseconds relative_timeout) { 173e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park AbsTime absolute_timeout; 174e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park return (WaitForPropertyCreation(key, relative_timeout, absolute_timeout) != nullptr); 175e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park} 176e2d986daa644672dabe5f594701028dc04fcc5ceKeun-young Park 1771e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes} // namespace base 1781e88c8c0ac31a4b07da4228ed9ac41e50ae56886Elliott Hughes} // namespace android 179