Loading libcutils/Android.bp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -152,6 +152,7 @@ cc_library { "iosched_policy.cpp", "iosched_policy.cpp", "load_file.cpp", "load_file.cpp", "native_handle.cpp", "native_handle.cpp", "properties.cpp", "record_stream.cpp", "record_stream.cpp", "strlcpy.c", "strlcpy.c", "threads.cpp", "threads.cpp", Loading Loading @@ -187,7 +188,6 @@ cc_library { "fs_config.cpp", "fs_config.cpp", "klog.cpp", "klog.cpp", "partition_utils.cpp", "partition_utils.cpp", "properties.cpp", "qtaguid.cpp", "qtaguid.cpp", "trace-dev.cpp", "trace-dev.cpp", "uevent.cpp", "uevent.cpp", Loading Loading @@ -268,6 +268,7 @@ cc_defaults { name: "libcutils_test_default", name: "libcutils_test_default", srcs: [ srcs: [ "native_handle_test.cpp", "native_handle_test.cpp", "properties_test.cpp", "sockets_test.cpp", "sockets_test.cpp", ], ], Loading @@ -280,7 +281,6 @@ cc_defaults { "fs_config_test.cpp", "fs_config_test.cpp", "memset_test.cpp", "memset_test.cpp", "multiuser_test.cpp", "multiuser_test.cpp", "properties_test.cpp", "sched_policy_test.cpp", "sched_policy_test.cpp", "str_parms_test.cpp", "str_parms_test.cpp", "trace-dev_test.cpp", "trace-dev_test.cpp", Loading libcutils/include/cutils/properties.h +15 −14 Original line number Original line Diff line number Diff line Loading @@ -14,25 +14,28 @@ * limitations under the License. * limitations under the License. */ */ #ifndef __CUTILS_PROPERTIES_H #pragma once #define __CUTILS_PROPERTIES_H #include <sys/cdefs.h> #include <sys/cdefs.h> #include <stddef.h> #include <stddef.h> #include <sys/system_properties.h> #include <stdint.h> #include <stdint.h> #if __has_include(<sys/system_properties.h>) #include <sys/system_properties.h> #else #define PROP_VALUE_MAX 92 #endif #ifdef __cplusplus #ifdef __cplusplus extern "C" { extern "C" { #endif #endif /* System properties are *small* name value pairs managed by the // ** property service. If your data doesn't fit in the provided // Deprecated. ** space it is not appropriate for a system property. // ** // See <android-base/properties.h> for better API. ** WARNING: system/bionic/include/sys/system_properties.h also defines // ** these, but with different names. (TODO: fix that) */ #define PROPERTY_KEY_MAX PROP_NAME_MAX #define PROPERTY_KEY_MAX PROP_NAME_MAX #define PROPERTY_VALUE_MAX PROP_VALUE_MAX #define PROPERTY_VALUE_MAX PROP_VALUE_MAX Loading Loading @@ -146,5 +149,3 @@ int property_get(const char *key, char *value, const char *default_value) { #ifdef __cplusplus #ifdef __cplusplus } } #endif #endif #endif libcutils/properties.cpp +38 −64 Original line number Original line Diff line number Diff line Loading @@ -16,27 +16,19 @@ #include <cutils/properties.h> #include <cutils/properties.h> #define LOG_TAG "properties" // #define LOG_NDEBUG 0 #include <assert.h> #include <ctype.h> #include <errno.h> #include <errno.h> #include <inttypes.h> #include <inttypes.h> #include <stdlib.h> #include <stdlib.h> #include <string.h> #include <string.h> #include <unistd.h> #include <unistd.h> #include <cutils/sockets.h> #include <android-base/properties.h> #include <log/log.h> int8_t property_get_bool(const char* key, int8_t default_value) { int8_t property_get_bool(const char* key, int8_t default_value) { if (!key) { if (!key) return default_value; return default_value; } int8_t result = default_value; int8_t result = default_value; char buf[PROPERTY_VALUE_MAX] = {'\0'}; char buf[PROPERTY_VALUE_MAX] = {}; int len = property_get(key, buf, ""); int len = property_get(key, buf, ""); if (len == 1) { if (len == 1) { Loading @@ -57,73 +49,53 @@ int8_t property_get_bool(const char *key, int8_t default_value) { return result; return result; } } // Convert string property to int (default if fails); return default value if out of bounds template <typename T> static intmax_t property_get_imax(const char *key, intmax_t lower_bound, intmax_t upper_bound, static T property_get_int(const char* key, T default_value) { intmax_t default_value) { if (!key) return default_value; if (!key) { return default_value; } intmax_t result = default_value; char value[PROPERTY_VALUE_MAX] = {}; char buf[PROPERTY_VALUE_MAX] = {'\0'}; if (property_get(key, value, "") < 1) return default_value; char *end = NULL; int len = property_get(key, buf, ""); // libcutils unwisely allows octal, which libbase doesn't. if (len > 0) { T result = default_value; int tmp = errno; int saved_errno = errno; errno = 0; errno = 0; char* end = nullptr; // Infer base automatically intmax_t v = strtoimax(value, &end, 0); result = strtoimax(buf, &end, /*base*/ 0); if (errno != ERANGE && end != value && v >= std::numeric_limits<T>::min() && if ((result == INTMAX_MIN || result == INTMAX_MAX) && errno == ERANGE) { v <= std::numeric_limits<T>::max()) { // Over or underflow result = v; result = default_value; ALOGV("%s(%s,%" PRIdMAX ") - overflow", __FUNCTION__, key, default_value); } else if (result < lower_bound || result > upper_bound) { // Out of range of requested bounds result = default_value; ALOGV("%s(%s,%" PRIdMAX ") - out of range", __FUNCTION__, key, default_value); } else if (end == buf) { // Numeric conversion failed result = default_value; ALOGV("%s(%s,%" PRIdMAX ") - numeric conversion failed", __FUNCTION__, key, default_value); } } errno = saved_errno; errno = tmp; } return result; return result; } } int64_t property_get_int64(const char* key, int64_t default_value) { int64_t property_get_int64(const char* key, int64_t default_value) { return (int64_t)property_get_imax(key, INT64_MIN, INT64_MAX, default_value); return property_get_int<int64_t>(key, default_value); } } int32_t property_get_int32(const char* key, int32_t default_value) { int32_t property_get_int32(const char* key, int32_t default_value) { return (int32_t)property_get_imax(key, INT32_MIN, INT32_MAX, default_value); return property_get_int<int32_t>(key, default_value); } } #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> int property_set(const char* key, const char* value) { int property_set(const char* key, const char* value) { return __system_property_set(key, value); return __system_property_set(key, value); } } int property_get(const char* key, char* value, const char* default_value) { int property_get(const char* key, char* value, const char* default_value) { int len = __system_property_get(key, value); int len = __system_property_get(key, value); if (len > 0) { if (len < 1 && default_value) { return len; snprintf(value, PROPERTY_VALUE_MAX, "%s", default_value); } return strlen(value); if (default_value) { len = strnlen(default_value, PROPERTY_VALUE_MAX - 1); memcpy(value, default_value, len); value[len] = '\0'; } } return len; return len; } } #if __has_include(<sys/system_properties.h>) #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> struct callback_data { struct callback_data { void (*callback)(const char* name, const char* value, void* cookie); void (*callback)(const char* name, const char* value, void* cookie); void* cookie; void* cookie; Loading @@ -142,3 +114,5 @@ int property_list(void (*fn)(const char* name, const char* value, void* cookie), callback_data data = {fn, cookie}; callback_data data = {fn, cookie}; return __system_property_foreach(property_list_callback, &data); return __system_property_foreach(property_list_callback, &data); } } #endif libcutils/properties_test.cpp +136 −117 Original line number Original line Diff line number Diff line Loading @@ -93,16 +93,12 @@ protected: } } }; }; TEST_F(PropertiesTest, SetString) { TEST_F(PropertiesTest, property_set_null_key) { // Null key -> unsuccessful set // Null key -> unsuccessful set { // Null key -> fails EXPECT_GT(0, property_set(/*key*/ NULL, PROPERTY_TEST_VALUE_DEFAULT)); EXPECT_GT(0, property_set(/*key*/ NULL, PROPERTY_TEST_VALUE_DEFAULT)); } } // Null value -> returns default value TEST_F(PropertiesTest, property_set_null_value) { { // Null value -> OK, and it clears the value // Null value -> OK, and it clears the value EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/ NULL)); EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/ NULL)); ResetValue(); ResetValue(); Loading @@ -113,16 +109,16 @@ TEST_F(PropertiesTest, SetString) { EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue); EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue); } } TEST_F(PropertiesTest, property_set) { // Trivial case => get returns what was set // Trivial case => get returns what was set { size_t len = SetAndGetProperty("hello_world"); size_t len = SetAndGetProperty("hello_world"); EXPECT_EQ(strlen("hello_world"), len) << "hello_world key"; EXPECT_EQ(strlen("hello_world"), len) << "hello_world key"; EXPECT_STREQ("hello_world", mValue); EXPECT_STREQ("hello_world", mValue); ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_set_empty) { // Set to empty string => get returns default always // Set to empty string => get returns default always { const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING"; const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING"; size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT); size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT); EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key"; EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key"; Loading @@ -130,8 +126,8 @@ TEST_F(PropertiesTest, SetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_set_max_length) { // Set to max length => get returns what was set // Set to max length => get returns what was set { std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); int len = SetAndGetProperty(maxLengthString.c_str()); int len = SetAndGetProperty(maxLengthString.c_str()); Loading @@ -140,8 +136,8 @@ TEST_F(PropertiesTest, SetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_set_too_long) { // Set to max length + 1 => set fails // Set to max length + 1 => set fails { const char* VALID_TEST_VALUE = "VALID_VALUE"; const char* VALID_TEST_VALUE = "VALID_VALUE"; ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE)); ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE)); Loading @@ -155,12 +151,9 @@ TEST_F(PropertiesTest, SetString) { EXPECT_STREQ(VALID_TEST_VALUE, mValue); EXPECT_STREQ(VALID_TEST_VALUE, mValue); ResetValue(); ResetValue(); } } } TEST_F(PropertiesTest, GetString) { TEST_F(PropertiesTest, property_get_too_long) { // Try to use a default value that's too long => get truncates the value // Try to use a default value that's too long => get truncates the value { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); Loading @@ -173,8 +166,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_too_long) { // Try to use a default value that's the max length => get succeeds // Try to use a default value that's the max length => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b'); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b'); Loading @@ -186,8 +179,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_okay) { // Try to use a default value of length one => get succeeds // Try to use a default value of length one => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string oneCharString = std::string(1, 'c'); std::string oneCharString = std::string(1, 'c'); Loading @@ -199,8 +192,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_empty) { // Try to use a default value of length zero => get succeeds // Try to use a default value of length zero => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string zeroCharString = std::string(0, 'd'); std::string zeroCharString = std::string(0, 'd'); Loading @@ -212,8 +205,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_NULL) { // Try to use a NULL default value => get returns 0 // Try to use a NULL default value => get returns 0 { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); // Expect a return value of 0 // Expect a return value of 0 Loading @@ -221,32 +214,58 @@ TEST_F(PropertiesTest, GetString) { EXPECT_EQ(0, len); EXPECT_EQ(0, len); ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_bool_0) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "0")); ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } } TEST_F(PropertiesTest, GetBool) { TEST_F(PropertiesTest, property_get_bool_1) { /** ASSERT_OK(property_set(PROPERTY_TEST_KEY, "1")); * TRUE ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); */ const char *valuesTrue[] = { "1", "true", "y", "yes", "on", }; for (size_t i = 0; i < arraysize(valuesTrue); ++i) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesTrue[i])); bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false); EXPECT_TRUE(val) << "Property should've been TRUE for value: '" << valuesTrue[i] << "'"; } } /** TEST_F(PropertiesTest, property_get_bool_false) { * FALSE ASSERT_OK(property_set(PROPERTY_TEST_KEY, "false")); */ ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); const char *valuesFalse[] = { "0", "false", "n", "no", "off", }; for (size_t i = 0; i < arraysize(valuesFalse); ++i) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesFalse[i])); bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true); EXPECT_FALSE(val) << "Property shoud've been FALSE For string value: '" << valuesFalse[i] << "'"; } } /** TEST_F(PropertiesTest, property_get_bool_n) { * NEITHER ASSERT_OK(property_set(PROPERTY_TEST_KEY, "n")); */ ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } TEST_F(PropertiesTest, property_get_bool_no) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "no")); ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } TEST_F(PropertiesTest, property_get_bool_off) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "off")); ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } TEST_F(PropertiesTest, property_get_bool_on) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "on")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_true) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "true")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_y) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "y")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_yes) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "yes")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_neither) { const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ", const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ", "+1", " 1 ", " true", " true ", " y ", " yes", "yes ", "+1", " 1 ", " true", " true ", " y ", " yes", "yes ", "+0", "-0", "00", " 00 ", " false", "false ", "+0", "-0", "00", " 00 ", " false", "false ", Loading @@ -263,7 +282,7 @@ TEST_F(PropertiesTest, GetBool) { } } } } TEST_F(PropertiesTest, GetInt64) { TEST_F(PropertiesTest, property_get_int64) { const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD); const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD); const std::string longMaxString = ToString(INT64_MAX); const std::string longMaxString = ToString(INT64_MAX); Loading Loading @@ -310,7 +329,7 @@ TEST_F(PropertiesTest, GetInt64) { } } } } TEST_F(PropertiesTest, GetInt32) { TEST_F(PropertiesTest, property_get_int32) { const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF); const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF); const std::string intMaxString = ToString(INT32_MAX); const std::string intMaxString = ToString(INT32_MAX); Loading Loading
libcutils/Android.bp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -152,6 +152,7 @@ cc_library { "iosched_policy.cpp", "iosched_policy.cpp", "load_file.cpp", "load_file.cpp", "native_handle.cpp", "native_handle.cpp", "properties.cpp", "record_stream.cpp", "record_stream.cpp", "strlcpy.c", "strlcpy.c", "threads.cpp", "threads.cpp", Loading Loading @@ -187,7 +188,6 @@ cc_library { "fs_config.cpp", "fs_config.cpp", "klog.cpp", "klog.cpp", "partition_utils.cpp", "partition_utils.cpp", "properties.cpp", "qtaguid.cpp", "qtaguid.cpp", "trace-dev.cpp", "trace-dev.cpp", "uevent.cpp", "uevent.cpp", Loading Loading @@ -268,6 +268,7 @@ cc_defaults { name: "libcutils_test_default", name: "libcutils_test_default", srcs: [ srcs: [ "native_handle_test.cpp", "native_handle_test.cpp", "properties_test.cpp", "sockets_test.cpp", "sockets_test.cpp", ], ], Loading @@ -280,7 +281,6 @@ cc_defaults { "fs_config_test.cpp", "fs_config_test.cpp", "memset_test.cpp", "memset_test.cpp", "multiuser_test.cpp", "multiuser_test.cpp", "properties_test.cpp", "sched_policy_test.cpp", "sched_policy_test.cpp", "str_parms_test.cpp", "str_parms_test.cpp", "trace-dev_test.cpp", "trace-dev_test.cpp", Loading
libcutils/include/cutils/properties.h +15 −14 Original line number Original line Diff line number Diff line Loading @@ -14,25 +14,28 @@ * limitations under the License. * limitations under the License. */ */ #ifndef __CUTILS_PROPERTIES_H #pragma once #define __CUTILS_PROPERTIES_H #include <sys/cdefs.h> #include <sys/cdefs.h> #include <stddef.h> #include <stddef.h> #include <sys/system_properties.h> #include <stdint.h> #include <stdint.h> #if __has_include(<sys/system_properties.h>) #include <sys/system_properties.h> #else #define PROP_VALUE_MAX 92 #endif #ifdef __cplusplus #ifdef __cplusplus extern "C" { extern "C" { #endif #endif /* System properties are *small* name value pairs managed by the // ** property service. If your data doesn't fit in the provided // Deprecated. ** space it is not appropriate for a system property. // ** // See <android-base/properties.h> for better API. ** WARNING: system/bionic/include/sys/system_properties.h also defines // ** these, but with different names. (TODO: fix that) */ #define PROPERTY_KEY_MAX PROP_NAME_MAX #define PROPERTY_KEY_MAX PROP_NAME_MAX #define PROPERTY_VALUE_MAX PROP_VALUE_MAX #define PROPERTY_VALUE_MAX PROP_VALUE_MAX Loading Loading @@ -146,5 +149,3 @@ int property_get(const char *key, char *value, const char *default_value) { #ifdef __cplusplus #ifdef __cplusplus } } #endif #endif #endif
libcutils/properties.cpp +38 −64 Original line number Original line Diff line number Diff line Loading @@ -16,27 +16,19 @@ #include <cutils/properties.h> #include <cutils/properties.h> #define LOG_TAG "properties" // #define LOG_NDEBUG 0 #include <assert.h> #include <ctype.h> #include <errno.h> #include <errno.h> #include <inttypes.h> #include <inttypes.h> #include <stdlib.h> #include <stdlib.h> #include <string.h> #include <string.h> #include <unistd.h> #include <unistd.h> #include <cutils/sockets.h> #include <android-base/properties.h> #include <log/log.h> int8_t property_get_bool(const char* key, int8_t default_value) { int8_t property_get_bool(const char* key, int8_t default_value) { if (!key) { if (!key) return default_value; return default_value; } int8_t result = default_value; int8_t result = default_value; char buf[PROPERTY_VALUE_MAX] = {'\0'}; char buf[PROPERTY_VALUE_MAX] = {}; int len = property_get(key, buf, ""); int len = property_get(key, buf, ""); if (len == 1) { if (len == 1) { Loading @@ -57,73 +49,53 @@ int8_t property_get_bool(const char *key, int8_t default_value) { return result; return result; } } // Convert string property to int (default if fails); return default value if out of bounds template <typename T> static intmax_t property_get_imax(const char *key, intmax_t lower_bound, intmax_t upper_bound, static T property_get_int(const char* key, T default_value) { intmax_t default_value) { if (!key) return default_value; if (!key) { return default_value; } intmax_t result = default_value; char value[PROPERTY_VALUE_MAX] = {}; char buf[PROPERTY_VALUE_MAX] = {'\0'}; if (property_get(key, value, "") < 1) return default_value; char *end = NULL; int len = property_get(key, buf, ""); // libcutils unwisely allows octal, which libbase doesn't. if (len > 0) { T result = default_value; int tmp = errno; int saved_errno = errno; errno = 0; errno = 0; char* end = nullptr; // Infer base automatically intmax_t v = strtoimax(value, &end, 0); result = strtoimax(buf, &end, /*base*/ 0); if (errno != ERANGE && end != value && v >= std::numeric_limits<T>::min() && if ((result == INTMAX_MIN || result == INTMAX_MAX) && errno == ERANGE) { v <= std::numeric_limits<T>::max()) { // Over or underflow result = v; result = default_value; ALOGV("%s(%s,%" PRIdMAX ") - overflow", __FUNCTION__, key, default_value); } else if (result < lower_bound || result > upper_bound) { // Out of range of requested bounds result = default_value; ALOGV("%s(%s,%" PRIdMAX ") - out of range", __FUNCTION__, key, default_value); } else if (end == buf) { // Numeric conversion failed result = default_value; ALOGV("%s(%s,%" PRIdMAX ") - numeric conversion failed", __FUNCTION__, key, default_value); } } errno = saved_errno; errno = tmp; } return result; return result; } } int64_t property_get_int64(const char* key, int64_t default_value) { int64_t property_get_int64(const char* key, int64_t default_value) { return (int64_t)property_get_imax(key, INT64_MIN, INT64_MAX, default_value); return property_get_int<int64_t>(key, default_value); } } int32_t property_get_int32(const char* key, int32_t default_value) { int32_t property_get_int32(const char* key, int32_t default_value) { return (int32_t)property_get_imax(key, INT32_MIN, INT32_MAX, default_value); return property_get_int<int32_t>(key, default_value); } } #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> int property_set(const char* key, const char* value) { int property_set(const char* key, const char* value) { return __system_property_set(key, value); return __system_property_set(key, value); } } int property_get(const char* key, char* value, const char* default_value) { int property_get(const char* key, char* value, const char* default_value) { int len = __system_property_get(key, value); int len = __system_property_get(key, value); if (len > 0) { if (len < 1 && default_value) { return len; snprintf(value, PROPERTY_VALUE_MAX, "%s", default_value); } return strlen(value); if (default_value) { len = strnlen(default_value, PROPERTY_VALUE_MAX - 1); memcpy(value, default_value, len); value[len] = '\0'; } } return len; return len; } } #if __has_include(<sys/system_properties.h>) #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> struct callback_data { struct callback_data { void (*callback)(const char* name, const char* value, void* cookie); void (*callback)(const char* name, const char* value, void* cookie); void* cookie; void* cookie; Loading @@ -142,3 +114,5 @@ int property_list(void (*fn)(const char* name, const char* value, void* cookie), callback_data data = {fn, cookie}; callback_data data = {fn, cookie}; return __system_property_foreach(property_list_callback, &data); return __system_property_foreach(property_list_callback, &data); } } #endif
libcutils/properties_test.cpp +136 −117 Original line number Original line Diff line number Diff line Loading @@ -93,16 +93,12 @@ protected: } } }; }; TEST_F(PropertiesTest, SetString) { TEST_F(PropertiesTest, property_set_null_key) { // Null key -> unsuccessful set // Null key -> unsuccessful set { // Null key -> fails EXPECT_GT(0, property_set(/*key*/ NULL, PROPERTY_TEST_VALUE_DEFAULT)); EXPECT_GT(0, property_set(/*key*/ NULL, PROPERTY_TEST_VALUE_DEFAULT)); } } // Null value -> returns default value TEST_F(PropertiesTest, property_set_null_value) { { // Null value -> OK, and it clears the value // Null value -> OK, and it clears the value EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/ NULL)); EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/ NULL)); ResetValue(); ResetValue(); Loading @@ -113,16 +109,16 @@ TEST_F(PropertiesTest, SetString) { EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue); EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue); } } TEST_F(PropertiesTest, property_set) { // Trivial case => get returns what was set // Trivial case => get returns what was set { size_t len = SetAndGetProperty("hello_world"); size_t len = SetAndGetProperty("hello_world"); EXPECT_EQ(strlen("hello_world"), len) << "hello_world key"; EXPECT_EQ(strlen("hello_world"), len) << "hello_world key"; EXPECT_STREQ("hello_world", mValue); EXPECT_STREQ("hello_world", mValue); ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_set_empty) { // Set to empty string => get returns default always // Set to empty string => get returns default always { const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING"; const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING"; size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT); size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT); EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key"; EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key"; Loading @@ -130,8 +126,8 @@ TEST_F(PropertiesTest, SetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_set_max_length) { // Set to max length => get returns what was set // Set to max length => get returns what was set { std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); int len = SetAndGetProperty(maxLengthString.c_str()); int len = SetAndGetProperty(maxLengthString.c_str()); Loading @@ -140,8 +136,8 @@ TEST_F(PropertiesTest, SetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_set_too_long) { // Set to max length + 1 => set fails // Set to max length + 1 => set fails { const char* VALID_TEST_VALUE = "VALID_VALUE"; const char* VALID_TEST_VALUE = "VALID_VALUE"; ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE)); ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE)); Loading @@ -155,12 +151,9 @@ TEST_F(PropertiesTest, SetString) { EXPECT_STREQ(VALID_TEST_VALUE, mValue); EXPECT_STREQ(VALID_TEST_VALUE, mValue); ResetValue(); ResetValue(); } } } TEST_F(PropertiesTest, GetString) { TEST_F(PropertiesTest, property_get_too_long) { // Try to use a default value that's too long => get truncates the value // Try to use a default value that's too long => get truncates the value { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); Loading @@ -173,8 +166,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_too_long) { // Try to use a default value that's the max length => get succeeds // Try to use a default value that's the max length => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b'); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b'); Loading @@ -186,8 +179,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_okay) { // Try to use a default value of length one => get succeeds // Try to use a default value of length one => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string oneCharString = std::string(1, 'c'); std::string oneCharString = std::string(1, 'c'); Loading @@ -199,8 +192,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_empty) { // Try to use a default value of length zero => get succeeds // Try to use a default value of length zero => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string zeroCharString = std::string(0, 'd'); std::string zeroCharString = std::string(0, 'd'); Loading @@ -212,8 +205,8 @@ TEST_F(PropertiesTest, GetString) { ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_default_NULL) { // Try to use a NULL default value => get returns 0 // Try to use a NULL default value => get returns 0 { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); // Expect a return value of 0 // Expect a return value of 0 Loading @@ -221,32 +214,58 @@ TEST_F(PropertiesTest, GetString) { EXPECT_EQ(0, len); EXPECT_EQ(0, len); ResetValue(); ResetValue(); } } TEST_F(PropertiesTest, property_get_bool_0) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "0")); ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } } TEST_F(PropertiesTest, GetBool) { TEST_F(PropertiesTest, property_get_bool_1) { /** ASSERT_OK(property_set(PROPERTY_TEST_KEY, "1")); * TRUE ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); */ const char *valuesTrue[] = { "1", "true", "y", "yes", "on", }; for (size_t i = 0; i < arraysize(valuesTrue); ++i) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesTrue[i])); bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false); EXPECT_TRUE(val) << "Property should've been TRUE for value: '" << valuesTrue[i] << "'"; } } /** TEST_F(PropertiesTest, property_get_bool_false) { * FALSE ASSERT_OK(property_set(PROPERTY_TEST_KEY, "false")); */ ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); const char *valuesFalse[] = { "0", "false", "n", "no", "off", }; for (size_t i = 0; i < arraysize(valuesFalse); ++i) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesFalse[i])); bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true); EXPECT_FALSE(val) << "Property shoud've been FALSE For string value: '" << valuesFalse[i] << "'"; } } /** TEST_F(PropertiesTest, property_get_bool_n) { * NEITHER ASSERT_OK(property_set(PROPERTY_TEST_KEY, "n")); */ ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } TEST_F(PropertiesTest, property_get_bool_no) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "no")); ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } TEST_F(PropertiesTest, property_get_bool_off) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "off")); ASSERT_FALSE(property_get_bool(PROPERTY_TEST_KEY, true)); } TEST_F(PropertiesTest, property_get_bool_on) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "on")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_true) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "true")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_y) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "y")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_yes) { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "yes")); ASSERT_TRUE(property_get_bool(PROPERTY_TEST_KEY, false)); } TEST_F(PropertiesTest, property_get_bool_neither) { const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ", const char *valuesNeither[] = { "x0", "x1", "2", "-2", "True", "False", "garbage", "", " ", "+1", " 1 ", " true", " true ", " y ", " yes", "yes ", "+1", " 1 ", " true", " true ", " y ", " yes", "yes ", "+0", "-0", "00", " 00 ", " false", "false ", "+0", "-0", "00", " 00 ", " false", "false ", Loading @@ -263,7 +282,7 @@ TEST_F(PropertiesTest, GetBool) { } } } } TEST_F(PropertiesTest, GetInt64) { TEST_F(PropertiesTest, property_get_int64) { const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD); const int64_t DEFAULT_VALUE = INT64_C(0xDEADBEEFBEEFDEAD); const std::string longMaxString = ToString(INT64_MAX); const std::string longMaxString = ToString(INT64_MAX); Loading Loading @@ -310,7 +329,7 @@ TEST_F(PropertiesTest, GetInt64) { } } } } TEST_F(PropertiesTest, GetInt32) { TEST_F(PropertiesTest, property_get_int32) { const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF); const int32_t DEFAULT_VALUE = INT32_C(0xDEADBEEF); const std::string intMaxString = ToString(INT32_MAX); const std::string intMaxString = ToString(INT32_MAX); Loading