diff options
author | Josh Gao <jmgao@google.com> | 2020-03-02 20:46:15 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-03-02 20:46:15 +0000 |
commit | 9978c367548fa29473bef75dc5836000d10ad71c (patch) | |
tree | ce5381761474a3bbc1800c2abf03b665a233e65d /base/properties.cpp | |
parent | acb49fd07d328d6cb87fd8d9bdf49fbbaffe58a4 (diff) | |
parent | bbe3385097750842a8d87b9d3d0248c937dcdb97 (diff) |
Merge changes Ib97acc6d,I8f14004a,Id5bbfd6d,I4dfc3f52 into rvc-dev
* changes:
adbd: add runtime-configurable logging.
adb: don't hardcode ports in test_adb.
adbd: add usb thread spawn logging.
base: add CachedProperty.
Diffstat (limited to 'base/properties.cpp')
-rw-r--r-- | base/properties.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/base/properties.cpp b/base/properties.cpp index 4731bf2498..35e41a86e7 100644 --- a/base/properties.cpp +++ b/base/properties.cpp @@ -30,6 +30,7 @@ #include <android-base/parsebool.h> #include <android-base/parseint.h> +#include <android-base/strings.h> namespace android { namespace base { @@ -195,6 +196,62 @@ bool WaitForPropertyCreation(const std::string& key, return (WaitForPropertyCreation(key, relative_timeout, start_time) != nullptr); } +CachedProperty::CachedProperty(const char* property_name) + : property_name_(property_name), + prop_info_(nullptr), + cached_area_serial_(0), + cached_property_serial_(0), + is_read_only_(android::base::StartsWith(property_name, "ro.")), + read_only_property_(nullptr) { + static_assert(sizeof(cached_value_) == PROP_VALUE_MAX); +} + +const char* CachedProperty::Get(bool* changed) { + std::optional<uint32_t> initial_property_serial_ = cached_property_serial_; + + // Do we have a `struct prop_info` yet? + if (prop_info_ == nullptr) { + // `__system_property_find` is expensive, so only retry if a property + // has been created since last time we checked. + uint32_t property_area_serial = __system_property_area_serial(); + if (property_area_serial != cached_area_serial_) { + prop_info_ = __system_property_find(property_name_.c_str()); + cached_area_serial_ = property_area_serial; + } + } + + if (prop_info_ != nullptr) { + // Only bother re-reading the property if it's actually changed since last time. + uint32_t property_serial = __system_property_serial(prop_info_); + if (property_serial != cached_property_serial_) { + __system_property_read_callback( + prop_info_, + [](void* data, const char*, const char* value, uint32_t serial) { + CachedProperty* instance = reinterpret_cast<CachedProperty*>(data); + instance->cached_property_serial_ = serial; + // Read only properties can be larger than PROP_VALUE_MAX, but also never change value + // or location, thus we return the pointer from the shared memory directly. + if (instance->is_read_only_) { + instance->read_only_property_ = value; + } else { + strlcpy(instance->cached_value_, value, PROP_VALUE_MAX); + } + }, + this); + } + } + + if (changed) { + *changed = cached_property_serial_ != initial_property_serial_; + } + + if (is_read_only_) { + return read_only_property_; + } else { + return cached_value_; + } +} + #endif } // namespace base |