From dc803126283444431c0d06f0386eddada0fe6b77 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 24 May 2018 18:00:39 -0700 Subject: libbase: add host properties support. Move init and libprocessgroup away from their existing hacks. Bug: N/A Test: ran tests Change-Id: Ifabdd38e0cc4ab2582f1ea59d32159d386f48eb6 --- base/Android.bp | 6 ++-- base/include/android-base/properties.h | 8 ++--- base/properties.cpp | 59 ++++++++++++++++++++++------------ base/properties_test.cpp | 28 +++++++++++++++- 4 files changed, 72 insertions(+), 29 deletions(-) (limited to 'base') diff --git a/base/Android.bp b/base/Android.bp index 47b29c6a6..3e51af35f 100644 --- a/base/Android.bp +++ b/base/Android.bp @@ -48,6 +48,7 @@ cc_defaults { "file.cpp", "logging.cpp", "parsenetaddress.cpp", + "properties.cpp", "quick_exit.cpp", "stringprintf.cpp", "strings.cpp", @@ -58,9 +59,6 @@ cc_defaults { shared_libs: ["liblog"], target: { android: { - srcs: [ - "properties.cpp", - ], sanitize: { misc_undefined: ["integer"], }, @@ -129,6 +127,7 @@ cc_test { "parsedouble_test.cpp", "parseint_test.cpp", "parsenetaddress_test.cpp", + "properties_test.cpp", "quick_exit_test.cpp", "scopeguard_test.cpp", "stringprintf_test.cpp", @@ -138,7 +137,6 @@ cc_test { ], target: { android: { - srcs: ["properties_test.cpp"], sanitize: { misc_undefined: ["integer"], }, diff --git a/base/include/android-base/properties.h b/base/include/android-base/properties.h index 041586c2c..3a051435c 100644 --- a/base/include/android-base/properties.h +++ b/base/include/android-base/properties.h @@ -19,10 +19,6 @@ #include -#if !defined(__BIONIC__) -#error Only bionic supports system properties. -#endif - #include #include #include @@ -62,14 +58,18 @@ bool SetProperty(const std::string& key, const std::string& value); // Waits for the system property `key` to have the value `expected_value`. // Times out after `relative_timeout`. // Returns true on success, false on timeout. +#if defined(__BIONIC__) bool WaitForProperty(const std::string& key, const std::string& expected_value, std::chrono::milliseconds relative_timeout = std::chrono::milliseconds::max()); +#endif // Waits for the system property `key` to be created. // Times out after `relative_timeout`. // Returns true on success, false on timeout. +#if defined(__BIONIC__) bool WaitForPropertyCreation(const std::string& key, std::chrono::milliseconds relative_timeout = std::chrono::milliseconds::max()); +#endif } // namespace base } // namespace android diff --git a/base/properties.cpp b/base/properties.cpp index 6cf43f9e2..d5a5918ce 100644 --- a/base/properties.cpp +++ b/base/properties.cpp @@ -14,16 +14,18 @@ * limitations under the License. */ -#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ - #include "android-base/properties.h" +#if defined(__BIONIC__) +#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include #include +#endif #include #include #include +#include #include #include @@ -31,24 +33,6 @@ namespace android { namespace base { -std::string GetProperty(const std::string& key, const std::string& default_value) { - const prop_info* pi = __system_property_find(key.c_str()); - if (pi == nullptr) return default_value; - - std::string property_value; - __system_property_read_callback(pi, - [](void* cookie, const char*, const char* value, unsigned) { - auto property_value = reinterpret_cast(cookie); - *property_value = value; - }, - &property_value); - - // If the property exists but is empty, also return the default value. - // Since we can't remove system properties, "empty" is traditionally - // the same as "missing" (this was true for cutils' property_get). - return property_value.empty() ? default_value : property_value; -} - bool GetBoolProperty(const std::string& key, bool default_value) { std::string value = GetProperty(key, ""); if (value == "1" || value == "y" || value == "yes" || value == "on" || value == "true") { @@ -85,10 +69,43 @@ template uint16_t GetUintProperty(const std::string&, uint16_t, uint16_t); template uint32_t GetUintProperty(const std::string&, uint32_t, uint32_t); template uint64_t GetUintProperty(const std::string&, uint64_t, uint64_t); +#if !defined(__BIONIC__) +static std::map& g_properties = *new std::map; +static int __system_property_set(const char* key, const char* value) { + g_properties[key] = value; + return 0; +} +#endif + +std::string GetProperty(const std::string& key, const std::string& default_value) { + std::string property_value; +#if defined(__BIONIC__) + const prop_info* pi = __system_property_find(key.c_str()); + if (pi == nullptr) return default_value; + + __system_property_read_callback(pi, + [](void* cookie, const char*, const char* value, unsigned) { + auto property_value = reinterpret_cast(cookie); + *property_value = value; + }, + &property_value); +#else + auto it = g_properties.find(key); + if (it == g_properties.end()) return default_value; + property_value = it->second; +#endif + // If the property exists but is empty, also return the default value. + // Since we can't remove system properties, "empty" is traditionally + // the same as "missing" (this was true for cutils' property_get). + return property_value.empty() ? default_value : property_value; +} + bool SetProperty(const std::string& key, const std::string& value) { return (__system_property_set(key.c_str(), value.c_str()) == 0); } +#if defined(__BIONIC__) + struct WaitForPropertyData { bool done; const std::string* expected_value; @@ -175,5 +192,7 @@ bool WaitForPropertyCreation(const std::string& key, return (WaitForPropertyCreation(key, relative_timeout, start_time) != nullptr); } +#endif + } // namespace base } // namespace android diff --git a/base/properties_test.cpp b/base/properties_test.cpp index de5f3dcfa..e7d4880c2 100644 --- a/base/properties_test.cpp +++ b/base/properties_test.cpp @@ -23,7 +23,9 @@ #include #include -using namespace std::chrono_literals; +#if !defined(_WIN32) +using namespace std::literals; +#endif TEST(properties, smoke) { android::base::SetProperty("debug.libbase.property_test", "hello"); @@ -126,6 +128,7 @@ TEST(properties, GetUintProperty_uint32_t) { CheckGetUintProperty(); } TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty(); } TEST(properties, WaitForProperty) { +#if defined(__BIONIC__) std::atomic flag{false}; std::thread thread([&]() { std::this_thread::sleep_for(100ms); @@ -138,9 +141,13 @@ TEST(properties, WaitForProperty) { flag = true; ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", 1s)); thread.join(); +#else + GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; +#endif } TEST(properties, WaitForProperty_timeout) { +#if defined(__BIONIC__) auto t0 = std::chrono::steady_clock::now(); ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_timeout_test", "a", 200ms)); @@ -149,9 +156,13 @@ TEST(properties, WaitForProperty_timeout) { ASSERT_GE(std::chrono::duration_cast(t1 - t0), 200ms); // Upper bounds on timing are inherently flaky, but let's try... ASSERT_LT(std::chrono::duration_cast(t1 - t0), 600ms); +#else + GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; +#endif } TEST(properties, WaitForProperty_MaxTimeout) { +#if defined(__BIONIC__) std::atomic flag{false}; std::thread thread([&]() { android::base::SetProperty("debug.libbase.WaitForProperty_test", "a"); @@ -165,9 +176,13 @@ TEST(properties, WaitForProperty_MaxTimeout) { // Test that this does not immediately return false due to overflow issues with the timeout. ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b")); thread.join(); +#else + GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; +#endif } TEST(properties, WaitForProperty_NegativeTimeout) { +#if defined(__BIONIC__) std::atomic flag{false}; std::thread thread([&]() { android::base::SetProperty("debug.libbase.WaitForProperty_test", "a"); @@ -181,9 +196,13 @@ TEST(properties, WaitForProperty_NegativeTimeout) { // Assert that this immediately returns with a negative timeout ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", -100ms)); thread.join(); +#else + GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; +#endif } TEST(properties, WaitForPropertyCreation) { +#if defined(__BIONIC__) std::thread thread([&]() { std::this_thread::sleep_for(100ms); android::base::SetProperty("debug.libbase.WaitForPropertyCreation_test", "a"); @@ -192,9 +211,13 @@ TEST(properties, WaitForPropertyCreation) { ASSERT_TRUE(android::base::WaitForPropertyCreation( "debug.libbase.WaitForPropertyCreation_test", 1s)); thread.join(); +#else + GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; +#endif } TEST(properties, WaitForPropertyCreation_timeout) { +#if defined(__BIONIC__) auto t0 = std::chrono::steady_clock::now(); ASSERT_FALSE(android::base::WaitForPropertyCreation( "debug.libbase.WaitForPropertyCreation_timeout_test", 200ms)); @@ -203,4 +226,7 @@ TEST(properties, WaitForPropertyCreation_timeout) { ASSERT_GE(std::chrono::duration_cast(t1 - t0), 200ms); // Upper bounds on timing are inherently flaky, but let's try... ASSERT_LT(std::chrono::duration_cast(t1 - t0), 600ms); +#else + GTEST_LOG_(INFO) << "This test does nothing on the host.\n"; +#endif } -- cgit v1.2.3