diff --git a/native/jni/external/nanopb b/native/jni/external/nanopb index 3c69a905b..1466e6f95 160000 --- a/native/jni/external/nanopb +++ b/native/jni/external/nanopb @@ -1 +1 @@ -Subproject commit 3c69a905b16df149e1bda12f25e0522073a24678 +Subproject commit 1466e6f953835b191a7f5acf0c06c941d4cd33d9 diff --git a/native/jni/include/resetprop.hpp b/native/jni/include/resetprop.hpp index 558ba4735..55e2cf89a 100644 --- a/native/jni/include/resetprop.hpp +++ b/native/jni/include/resetprop.hpp @@ -8,4 +8,4 @@ std::string getprop(const char *name, bool persist = false); void getprops(void (*callback)(const char *, const char *, void *), void *cookie = nullptr, bool persist = false); int delprop(const char *name, bool persist = false); -void load_prop_file(const char *filename, bool trigger = true); +void load_prop_file(const char *filename, bool prop_svc = true); diff --git a/native/jni/resetprop/_resetprop.hpp b/native/jni/resetprop/_resetprop.hpp index 03a9eb428..e400ba96d 100644 --- a/native/jni/resetprop/_resetprop.hpp +++ b/native/jni/resetprop/_resetprop.hpp @@ -8,41 +8,30 @@ #define PERSISTENT_PROPERTY_DIR "/data/property" struct prop_cb { - virtual void exec(const char *name, const char *value) = 0; -}; - -template -struct prop_cb_impl : public prop_cb { - typedef void (*callback_type)(const char *, const char *, T&); - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdangling-field" // Dangling field is expected - prop_cb_impl(T &arg, callback_type fn) : arg(arg), fn(fn) {} -#pragma GCC diagnostic pop - - void exec(const char *name, const char *value) override { - fn(name, value, arg); + virtual void exec(const char *name, const char *value) { + exec(std::string(name), value); + } + virtual void exec(std::string &&name, const char *value) { + exec(name.data(), value); } -private: - T &arg; - callback_type fn; }; extern bool use_pb; -using prop_list = std::map; +using prop_list = std::map; -struct prop_collector : prop_cb_impl { - prop_collector(prop_list &list) : - prop_cb_impl(list, [](auto name, auto val, auto list){ list.emplace(name, val); }) {} +struct prop_collector : prop_cb { + explicit prop_collector(prop_list &list) : list(list) {} + void exec(const char *name, const char *value) override { + list.insert_or_assign(name, value); + } + void exec(std::string &&name, const char *value) override { + list.insert_or_assign(std::move(name), value); + } +private: + prop_list &list; }; -template -prop_cb_impl make_prop_cb(T &arg, Func f) { - return prop_cb_impl(arg, f); -} - std::string persist_getprop(const char *name); void persist_getprops(prop_cb *prop_cb); bool persist_deleteprop(const char *name); -void persist_cleanup(); diff --git a/native/jni/resetprop/persist_properties.cpp b/native/jni/resetprop/persist_properties.cpp index f31657fa4..b9aa9ef9a 100644 --- a/native/jni/resetprop/persist_properties.cpp +++ b/native/jni/resetprop/persist_properties.cpp @@ -1,14 +1,7 @@ -#include -#include -#include -#include -#include -#include -#include - #include #include #include + #include #include "_resetprop.hpp" @@ -16,34 +9,28 @@ using namespace std; /* *********************************************************************** - * Auto generated header and constant definitions compiled from - * android/platform/system/core/master/init/persistent_properties.proto - * using Nanopb's protoc - * Nanopb: https://github.com/nanopb/nanopb + * Auto generated header and field definitions compiled from + * https://android.googlesource.com/platform/system/core/+/master/init/persistent_properties.proto + * Generated with Nanopb: https://github.com/nanopb/nanopb * ***********************************************************************/ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.9.1 at Sun Apr 22 14:36:22 2018. */ +/* Generated by nanopb-0.4.3 */ -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif /* Struct definitions */ -typedef struct _PersistentProperties { - pb_callback_t properties; -/* @@protoc_insertion_point(struct:PersistentProperties) */ -} PersistentProperties; +struct PersistentProperties { + pb_callback_t properties; +}; -typedef struct _PersistentProperties_PersistentPropertyRecord { - pb_callback_t name; - bool has_value; - char value[92]; -/* @@protoc_insertion_point(struct:PersistentProperties_PersistentPropertyRecord) */ -} PersistentProperties_PersistentPropertyRecord; - -/* Default values for struct fields */ +struct PersistentProperties_PersistentPropertyRecord { + pb_callback_t name; + bool has_value; + char value[92]; +}; /* Initializer values for message structs */ #define PersistentProperties_init_default {{{NULL}, NULL}} @@ -56,33 +43,33 @@ typedef struct _PersistentProperties_PersistentPropertyRecord { #define PersistentProperties_PersistentPropertyRecord_name_tag 1 #define PersistentProperties_PersistentPropertyRecord_value_tag 2 -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.3.9.1 at Sun Apr 22 14:36:22 2018. */ - /* Struct field encoding specification for nanopb */ -const pb_field_t PersistentProperties_PersistentPropertyRecord_fields[3] = { - PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, PersistentProperties_PersistentPropertyRecord, name, name, 0), - PB_FIELD( 2, STRING , OPTIONAL, STATIC , OTHER, PersistentProperties_PersistentPropertyRecord, value, name, 0), - PB_LAST_FIELD -}; +#define PersistentProperties_FIELDLIST(X, a) \ +X(a, CALLBACK, REPEATED, MESSAGE, properties, 1) +#define PersistentProperties_CALLBACK pb_default_field_callback +#define PersistentProperties_DEFAULT NULL +#define PersistentProperties_properties_MSGTYPE PersistentProperties_PersistentPropertyRecord -const pb_field_t PersistentProperties_fields[2] = { - PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, PersistentProperties, properties, properties, &PersistentProperties_PersistentPropertyRecord_fields), - PB_LAST_FIELD -}; +#define PersistentProperties_PersistentPropertyRecord_FIELDLIST(X, a) \ +X(a, CALLBACK, OPTIONAL, STRING, name, 1) \ +X(a, STATIC, OPTIONAL, STRING, value, 2) +#define PersistentProperties_PersistentPropertyRecord_CALLBACK pb_default_field_callback +#define PersistentProperties_PersistentPropertyRecord_DEFAULT NULL + +extern const pb_msgdesc_t PersistentProperties_msg; +extern const pb_msgdesc_t PersistentProperties_PersistentPropertyRecord_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define PersistentProperties_fields &PersistentProperties_msg +#define PersistentProperties_PersistentPropertyRecord_fields &PersistentProperties_PersistentPropertyRecord_msg /* Maximum encoded size of messages (where known) */ /* PersistentProperties_size depends on runtime parameters */ /* PersistentProperties_PersistentPropertyRecord_size depends on runtime parameters */ -/* Message IDs (where set with "msgid" option) */ -#ifdef PB_MSGID - -#define PROPS_MESSAGES \ - -#endif -/* @@protoc_insertion_point(eof) */ +PB_BIND(PersistentProperties, PersistentProperties, AUTO) +PB_BIND(PersistentProperties_PersistentPropertyRecord, PersistentProperties_PersistentPropertyRecord, AUTO) /* *************************** * End of auto generated code @@ -90,27 +77,10 @@ const pb_field_t PersistentProperties_fields[2] = { bool use_pb = false; -#ifdef APPLET_STUB_MAIN -struct { - void push_back(...){}; -} allocs; -void persist_cleanup(){} -#else -static thread_local vector allocs; -void persist_cleanup() { - std::for_each(allocs.begin(), allocs.end(), [](auto p){ free(p); }); - allocs.clear(); -} -#endif - static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { - auto name = (pb_byte_t *) malloc(stream->bytes_left + 1); - allocs.push_back(name); /* Record all mallocs to cleanup */ - name[stream->bytes_left] = '\0'; - if (!pb_read(stream, name, stream->bytes_left)) - return false; - *arg = name; - return true; + string &name = *static_cast(*arg); + name.resize(stream->bytes_left); + return pb_read(stream, (pb_byte_t *)(name.data()), stream->bytes_left); } static bool name_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { @@ -119,25 +89,28 @@ static bool name_encode(pb_ostream_t *stream, const pb_field_t *field, void * co } static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { - PersistentProperties_PersistentPropertyRecord prop = {}; + PersistentProperties_PersistentPropertyRecord prop{}; + string name; prop.name.funcs.decode = name_decode; - if (!pb_decode(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop)) + prop.name.arg = &name; + if (!pb_decode(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop)) return false; - reinterpret_cast(*arg)->exec((const char *) prop.name.arg, prop.value); + auto cb = reinterpret_cast(*arg); + cb->exec(std::move(name), prop.value); return true; } static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { - PersistentProperties_PersistentPropertyRecord prop = {}; + PersistentProperties_PersistentPropertyRecord prop{}; prop.name.funcs.encode = name_encode; prop.has_value = true; - auto &list = *(prop_list *) *arg; + auto &list = *static_cast(*arg); for (auto &p : list) { if (!pb_encode_tag_for_field(stream, field)) return false; prop.name.arg = (void *) p.first.data(); strcpy(prop.value, p.second.data()); - if (!pb_encode_submessage(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop)) + if (!pb_encode_submessage(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop)) return false; } return true; @@ -168,18 +141,18 @@ static void pb_getprop(prop_cb *prop_cb) { size_t size; mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", buf, size); pb_istream_t stream = pb_istream_from_buffer(buf, size); - pb_decode(&stream, PersistentProperties_fields, &props); + pb_decode(&stream, &PersistentProperties_msg, &props); munmap(buf, size); } static bool file_getprop(const char *name, char *value) { - char path[PATH_MAX]; + char path[4096]; snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); int fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return false; LOGD("resetprop: read prop from [%s]\n", path); - value[read(fd, value, PROP_VALUE_MAX)] = '\0'; // Null terminate the read value + value[read(fd, value, PROP_VALUE_MAX - 1)] = '\0'; // Null terminate the read value close(fd); return value[0] != '\0'; } @@ -188,11 +161,9 @@ void persist_getprops(prop_cb *prop_cb) { if (use_pb) { pb_getprop(prop_cb); } else { - DIR *dir = opendir(PERSISTENT_PROPERTY_DIR); - struct dirent *entry; - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 ) - continue; + auto dir = open_dir(PERSISTENT_PROPERTY_DIR); + if (!dir) return; + for (dirent *entry; (entry = xreaddir(dir.get()));) { char value[PROP_VALUE_MAX]; if (file_getprop(entry->d_name, value)) prop_cb->exec(entry->d_name, value); @@ -200,20 +171,21 @@ void persist_getprops(prop_cb *prop_cb) { } } +struct match_prop_name : prop_cb { + explicit match_prop_name(const char *name) : _name(name) { value[0] = '\0'; } + void exec(string &&name, const char *val) override { + if (name == _name) + strcpy(value, val); + } + char value[PROP_VALUE_MAX]; +private: + const char *_name; +}; + string persist_getprop(const char *name) { if (use_pb) { - run_finally f([]{ persist_cleanup(); }); - struct { - const char *name; - char value[PROP_VALUE_MAX]; - } prop; - prop.name = name; - prop.value[0] = '\0'; - auto reader = make_prop_cb(prop, [](auto name, auto value, auto prop) { - if (strcmp(name, prop.name) == 0) - strcpy(prop.value, value); - }); - pb_getprop(&reader); + auto prop = match_prop_name(name); + pb_getprop(&prop); if (prop.value[0]) return prop.value; } else { @@ -227,7 +199,6 @@ string persist_getprop(const char *name) { bool persist_deleteprop(const char *name) { if (use_pb) { - run_finally f([]{ persist_cleanup(); }); prop_list list; prop_collector collector(list); persist_getprops(&collector); @@ -236,14 +207,14 @@ bool persist_deleteprop(const char *name) { if (it->first == name) { list.erase(it); // Dump the props back - PersistentProperties props = PersistentProperties_init_zero; + PersistentProperties props{}; pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); props.properties.funcs.encode = prop_encode; props.properties.arg = &list; LOGD("resetprop: encode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp]\n"); - if (!pb_encode(&ostream, PersistentProperties_fields, &props)) + if (!pb_encode(&ostream, &PersistentProperties_msg, &props)) return false; clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties", PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); @@ -254,7 +225,7 @@ bool persist_deleteprop(const char *name) { } return false; } else { - char path[PATH_MAX]; + char path[4096]; snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); if (unlink(path) == 0) { LOGD("resetprop: unlink [%s]\n", path); diff --git a/native/jni/resetprop/resetprop.cpp b/native/jni/resetprop/resetprop.cpp index 66575ad4b..65018a26d 100644 --- a/native/jni/resetprop/resetprop.cpp +++ b/native/jni/resetprop/resetprop.cpp @@ -67,25 +67,25 @@ static bool check_legal_property_name(const char *name) { return true; - illegal: +illegal: LOGE("Illegal property name: [%s]\n", name); return false; } static void read_prop(const prop_info *pi, void *cb) { - __system_property_read_callback( - pi, [](auto cb, auto name, auto value, auto) { - reinterpret_cast(cb)->exec(name, value); - }, cb); + auto callback = [](void *cb, const char *name, const char *value, uint32_t) { + static_cast(cb)->exec(name, value); + }; + __system_property_read_callback(pi, callback, cb); } static void print_props(bool persist) { - getprops([](auto name, auto value, auto) { + getprops([](const char *name, const char *value, auto) { printf("[%s]: [%s]\n", name, value); }, nullptr, persist); } -struct sysprop { +struct sysprop_stub { virtual int setprop(const char *name, const char *value, bool trigger) { return 1; } virtual string getprop(const char *name, bool persist) { return ""; } virtual void getprops(void (*callback)(const char *, const char *, void *), @@ -93,7 +93,7 @@ struct sysprop { virtual int delprop(const char *name, bool persist) { return 1; } }; -struct stock_sysprop : public sysprop { +struct sysprop : public sysprop_stub { int setprop(const char *name, const char *value, bool) override { return system_property_set(name, value); } @@ -105,31 +105,30 @@ struct stock_sysprop : public sysprop { } }; -struct resetprop : public sysprop { - int setprop(const char *name, const char *value, bool trigger) override { +struct resetprop : public sysprop_stub { + int setprop(const char *name, const char *value, bool prop_svc) override { if (!check_legal_property_name(name)) return 1; + const char *msg = prop_svc ? "property_service" : "modifying prop data structure"; int ret; auto pi = const_cast(__system_property_find(name)); if (pi != nullptr) { - if (trigger) { + if (prop_svc) { if (strncmp(name, "ro.", 3) == 0) delprop(name, false); ret = system_property_set(name, value); } else { ret = __system_property_update(pi, value, strlen(value)); } - LOGD("resetprop: update prop [%s]: [%s] by %s\n", name, value, - trigger ? "property_service" : "modifying prop data structure"); + LOGD("resetprop: update prop [%s]: [%s] by %s\n", name, value, msg); } else { - if (trigger) { + if (prop_svc) { ret = system_property_set(name, value); } else { ret = __system_property_add(name, strlen(name), value, strlen(value)); } - LOGD("resetprop: create prop [%s]: [%s] by %s\n", name, value, - trigger ? "property_service" : "modifying prop data structure"); + LOGD("resetprop: create prop [%s]: [%s] by %s\n", name, value, msg); } if (ret) @@ -138,24 +137,30 @@ struct resetprop : public sysprop { return ret; } + struct prop_to_string : prop_cb { + explicit prop_to_string(string &s) : val(s) {} + void exec(const char *name, const char *value) override { + val = value; + } + private: + string &val; + }; + string getprop(const char *name, bool persist) override { if (!check_legal_property_name(name)) return string(); auto pi = __system_property_find(name); if (pi == nullptr) { if (persist && strncmp(name, "persist.", 8) == 0) { - auto value = persist_getprop(name); - if (value.empty()) - goto not_found; - return value; + if (auto value = persist_getprop(name); !value.empty()) + return value; } - not_found: LOGD("resetprop: prop [%s] does not exist\n", name); return string(); } else { string val; - auto reader = make_prop_cb(val, [](auto, auto value, auto str){ str = value; }); - read_prop(pi, &reader); + auto prop = prop_to_string(val); + read_prop(pi, &prop); LOGD("resetprop: getprop [%s]: [%s]\n", name, val.data()); return val; } @@ -170,8 +175,6 @@ struct resetprop : public sysprop { persist_getprops(&collector); for (auto &[key, val] : list) callback(key.data(), val.data(), cookie); - if (persist) - persist_cleanup(); } int delprop(const char *name, bool persist) override { @@ -187,8 +190,8 @@ struct resetprop : public sysprop { #define DLOAD(name) \ *(void **) &name = dlsym(RTLD_DEFAULT, "__" #name) -static sysprop *get_impl() { - static sysprop *impl = nullptr; +static sysprop_stub *get_impl() { + static sysprop_stub *impl = nullptr; if (impl == nullptr) { use_pb = access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0; #ifdef APPLET_STUB_MAIN @@ -203,7 +206,7 @@ static sysprop *get_impl() { if (__system_properties_init()) { LOGW("resetprop: __system_properties_init error\n"); DLOAD(system_property_get); - impl = system_property_get ? new stock_sysprop() : new sysprop(); + impl = system_property_get ? new sysprop() : new sysprop_stub(); } else { impl = new resetprop(); } @@ -232,11 +235,11 @@ int delprop(const char *name, bool persist) { return get_impl()->delprop(name, persist); } -void load_prop_file(const char *filename, bool trigger) { +void load_prop_file(const char *filename, bool prop_svc) { auto impl = get_impl(); LOGD("resetprop: Parse prop file [%s]\n", filename); parse_prop_file(filename, [=](auto key, auto val) -> bool { - impl->setprop(key.data(), val.data(), trigger); + impl->setprop(key.data(), val.data(), prop_svc); return true; }); } @@ -244,9 +247,9 @@ void load_prop_file(const char *filename, bool trigger) { int resetprop_main(int argc, char *argv[]) { log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; }; - bool trigger = true, persist = false; + bool prop_svc = true; + bool persist = false; char *argv0 = argv[0]; - string prop; --argc; ++argv; @@ -257,7 +260,7 @@ int resetprop_main(int argc, char *argv[]) { switch (argv[0][idx]) { case '-': if (strcmp(argv[0], "--file") == 0 && argc == 2) { - load_prop_file(argv[1], trigger); + load_prop_file(argv[1], prop_svc); return 0; } else if (strcmp(argv[0], "--delete") == 0 && argc == 2) { return delprop(argv[1], persist); @@ -271,7 +274,7 @@ int resetprop_main(int argc, char *argv[]) { persist = true; continue; case 'n': - trigger = false; + prop_svc = false; continue; case '\0': break; @@ -289,13 +292,15 @@ int resetprop_main(int argc, char *argv[]) { case 0: print_props(persist); return 0; - case 1: - prop = getprop(argv[0], persist); - if (prop.empty()) return 1; + case 1: { + string prop = getprop(argv[0], persist); + if (prop.empty()) + return 1; printf("%s\n", prop.data()); return 0; + } case 2: - return setprop(argv[0], argv[1], trigger); + return setprop(argv[0], argv[1], prop_svc); default: usage(argv0); }