From dc803126283444431c0d06f0386eddada0fe6b77 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 24 May 2018 18:00:39 -0700 Subject: [PATCH] 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 +++++++++++- init/action.cpp | 7 +-- init/action_parser.cpp | 5 +-- init/host_init_stubs.cpp | 14 ------ init/host_init_stubs.h | 10 ----- init/service.cpp | 3 +- init/util.cpp | 3 +- libprocessgroup/processgroup.cpp | 9 ---- 11 files changed, 77 insertions(+), 75 deletions(-) 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 } diff --git a/init/action.cpp b/init/action.cpp index f782b51c1..11335ca14 100644 --- a/init/action.cpp +++ b/init/action.cpp @@ -18,16 +18,11 @@ #include #include +#include #include #include "util.h" -#if defined(__ANDROID__) -#include -#else -#include "host_init_stubs.h" -#endif - using android::base::Join; namespace android { diff --git a/init/action_parser.cpp b/init/action_parser.cpp index a2c96718b..f9b96eb5e 100644 --- a/init/action_parser.cpp +++ b/init/action_parser.cpp @@ -16,13 +16,12 @@ #include "action_parser.h" +#include #include #include "stable_properties.h" -#if defined(__ANDROID__) -#include -#else +#if !defined(__ANDROID__) #include "host_init_stubs.h" #endif diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp index 4451ac8b9..c40a25435 100644 --- a/init/host_init_stubs.cpp +++ b/init/host_init_stubs.cpp @@ -21,20 +21,6 @@ int setgroups(size_t __size, const gid_t* __list) { return 0; } -namespace android { -namespace base { - -std::string GetProperty(const std::string&, const std::string& default_value) { - return default_value; -} - -bool GetBoolProperty(const std::string&, bool default_value) { - return default_value; -} - -} // namespace base -} // namespace android - namespace android { namespace init { diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h index bb241af9b..f0e1f0729 100644 --- a/init/host_init_stubs.h +++ b/init/host_init_stubs.h @@ -29,16 +29,6 @@ // unistd.h int setgroups(size_t __size, const gid_t* __list); -// android-base/properties.h -namespace android { -namespace base { - -std::string GetProperty(const std::string& key, const std::string& default_value); -bool GetBoolProperty(const std::string& key, bool default_value); - -} // namespace base -} // namespace android - namespace android { namespace init { diff --git a/init/service.cpp b/init/service.cpp index 0e08d9bba..c9ed87f90 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -46,8 +47,6 @@ #if defined(__ANDROID__) #include -#include - #include "init.h" #include "property_service.h" #else diff --git a/init/util.cpp b/init/util.cpp index 4455b2eb1..5f2b87d71 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -43,8 +44,6 @@ #include "reboot.h" #if defined(__ANDROID__) -#include - #include "selinux.h" #else #include "host_init_stubs.h" diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp index 58295fadb..1cebb5daa 100644 --- a/libprocessgroup/processgroup.cpp +++ b/libprocessgroup/processgroup.cpp @@ -39,18 +39,14 @@ #include #include -#ifdef __ANDROID__ #include -#endif #include #include #include #include -#ifdef __ANDROID__ using android::base::GetBoolProperty; -#endif using android::base::StartsWith; using android::base::StringPrintf; using android::base::WriteStringToFile; @@ -68,15 +64,10 @@ std::once_flag init_path_flag; static const std::string& GetCgroupRootPath() { static std::string cgroup_root_path; std::call_once(init_path_flag, [&]() { -#ifdef __ANDROID__ // low-ram devices use per-app memcg by default, unlike high-end ones bool low_ram_device = GetBoolProperty("ro.config.low_ram", false); bool per_app_memcg = GetBoolProperty("ro.config.per_app_memcg", low_ram_device); -#else - // host does not support Android properties - bool per_app_memcg = false; -#endif if (per_app_memcg) { // Check if mem cgroup is mounted, only then check for // write-access to avoid SELinux denials