Merge "libbase: add host properties support."

This commit is contained in:
Elliott Hughes 2018-05-29 23:59:50 +00:00 committed by Gerrit Code Review
commit d580c441ab
11 changed files with 77 additions and 75 deletions

View file

@ -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"],
},
@ -130,6 +128,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",
@ -139,7 +138,6 @@ cc_test {
],
target: {
android: {
srcs: ["properties_test.cpp"],
sanitize: {
misc_undefined: ["integer"],
},

View file

@ -19,10 +19,6 @@
#include <sys/cdefs.h>
#if !defined(__BIONIC__)
#error Only bionic supports system properties.
#endif
#include <chrono>
#include <limits>
#include <string>
@ -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

View file

@ -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 <sys/system_properties.h>
#include <sys/_system_properties.h>
#endif
#include <algorithm>
#include <chrono>
#include <limits>
#include <map>
#include <string>
#include <android-base/parseint.h>
@ -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<std::string*>(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<std::string, std::string>& g_properties = *new std::map<std::string, std::string>;
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<std::string*>(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

View file

@ -23,7 +23,9 @@
#include <string>
#include <thread>
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<uint32_t>(); }
TEST(properties, GetUintProperty_uint64_t) { CheckGetUintProperty<uint64_t>(); }
TEST(properties, WaitForProperty) {
#if defined(__BIONIC__)
std::atomic<bool> 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<std::chrono::milliseconds>(t1 - t0), 200ms);
// Upper bounds on timing are inherently flaky, but let's try...
ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(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<bool> 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<bool> 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<std::chrono::milliseconds>(t1 - t0), 200ms);
// Upper bounds on timing are inherently flaky, but let's try...
ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms);
#else
GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
#endif
}

View file

@ -18,16 +18,11 @@
#include <android-base/chrono_utils.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include "util.h"
#if defined(__ANDROID__)
#include <android-base/properties.h>
#else
#include "host_init_stubs.h"
#endif
using android::base::Join;
namespace android {

View file

@ -16,13 +16,12 @@
#include "action_parser.h"
#include <android-base/properties.h>
#include <android-base/strings.h>
#include "stable_properties.h"
#if defined(__ANDROID__)
#include <android-base/properties.h>
#else
#if !defined(__ANDROID__)
#include "host_init_stubs.h"
#endif

View file

@ -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 {

View file

@ -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 {

View file

@ -33,6 +33,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
@ -47,8 +48,6 @@
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#include <android-base/properties.h>
#include "init.h"
#include "property_service.h"
#else

View file

@ -33,6 +33,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
@ -43,8 +44,6 @@
#include "reboot.h"
#if defined(__ANDROID__)
#include <android-base/properties.h>
#include "selinux.h"
#else
#include "host_init_stubs.h"

View file

@ -39,18 +39,14 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#ifdef __ANDROID__
#include <android-base/properties.h>
#endif
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <private/android_filesystem_config.h>
#include <processgroup/processgroup.h>
#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