Merge "libbase: add host properties support."
This commit is contained in:
commit
d580c441ab
|
@ -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"],
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue