Cleanup resetprop code

This commit is contained in:
topjohnwu
2025-08-18 11:12:31 -07:00
committed by John Wu
parent 2e4fa6864c
commit 42d9f87bc9
7 changed files with 71 additions and 83 deletions

View File

@@ -4,6 +4,7 @@
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <linux/input.h> #include <linux/input.h>
#include <map>
#include <consts.hpp> #include <consts.hpp>
#include <base.hpp> #include <base.hpp>

View File

@@ -2,6 +2,7 @@
#include <android/log.h> #include <android/log.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <string> #include <string>
#include <map>
#include <core.hpp> #include <core.hpp>

View File

@@ -5,6 +5,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <dirent.h> #include <dirent.h>
#include <set> #include <set>
#include <map>
#include <consts.hpp> #include <consts.hpp>
#include <sqlite.hpp> #include <sqlite.hpp>

View File

@@ -1,22 +1,17 @@
#pragma once #pragma once
#include <string> #include <string>
#include <map>
#include <cxx.h> #include <cxx.h>
struct prop_cb { struct prop_info;
struct prop_callback {
virtual ~prop_callback() = default;
virtual void exec(const char *name, const char *value, uint32_t serial) = 0; virtual void exec(const char *name, const char *value, uint32_t serial) = 0;
}; void exec(Utf8CStr name, Utf8CStr value) {
exec(name.data(), value.data(), INT_MAX);
using prop_list = std::map<std::string, std::string>;
struct prop_collector : prop_cb {
explicit prop_collector(prop_list &list) : list(list) {}
void exec(const char *name, const char *value, uint32_t) override {
list.insert({name, value});
} }
private: void read(const prop_info *pi);
prop_list &list;
}; };
// System properties // System properties
@@ -32,7 +27,4 @@ static inline int set_prop_rs(Utf8CStr name, Utf8CStr value, bool skip_svc) {
} }
static inline void load_prop_file_rs(Utf8CStr filename, bool skip_svc) { static inline void load_prop_file_rs(Utf8CStr filename, bool skip_svc) {
load_prop_file(filename.data(), skip_svc); load_prop_file(filename.data(), skip_svc);
}
static inline void prop_cb_exec(prop_cb &cb, Utf8CStr name, Utf8CStr value, uint32_t serial) {
cb.exec(name.data(), value.data(), serial);
} }

View File

@@ -167,15 +167,16 @@ pub mod ffi {
include!("include/resetprop.hpp"); include!("include/resetprop.hpp");
#[cxx_name = "prop_cb"] #[cxx_name = "prop_callback"]
type PropCb; type PropCallback;
fn exec(self: Pin<&mut PropCallback>, name: Utf8CStrRef, value: Utf8CStrRef);
#[cxx_name = "get_prop_rs"] #[cxx_name = "get_prop_rs"]
fn get_prop(name: Utf8CStrRef, persist: bool) -> String; fn get_prop(name: Utf8CStrRef, persist: bool) -> String;
#[cxx_name = "set_prop_rs"] #[cxx_name = "set_prop_rs"]
fn set_prop(name: Utf8CStrRef, value: Utf8CStrRef, skip_svc: bool) -> i32; fn set_prop(name: Utf8CStrRef, value: Utf8CStrRef, skip_svc: bool) -> i32;
#[cxx_name = "load_prop_file_rs"] #[cxx_name = "load_prop_file_rs"]
fn load_prop_file(filename: Utf8CStrRef, skip_svc: bool); fn load_prop_file(filename: Utf8CStrRef, skip_svc: bool);
fn prop_cb_exec(cb: Pin<&mut PropCb>, name: Utf8CStrRef, value: Utf8CStrRef, serial: u32);
} }
extern "Rust" { extern "Rust" {
@@ -188,8 +189,8 @@ pub mod ffi {
fn revert_unmount(pid: i32); fn revert_unmount(pid: i32);
fn remove_modules(); fn remove_modules();
fn zygisk_should_load_module(flags: u32) -> bool; fn zygisk_should_load_module(flags: u32) -> bool;
unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCb>); unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCallback>);
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>); unsafe fn persist_get_props(prop_cb: Pin<&mut PropCallback>);
unsafe fn persist_delete_prop(name: Utf8CStrRef) -> bool; unsafe fn persist_delete_prop(name: Utf8CStrRef) -> bool;
unsafe fn persist_set_prop(name: Utf8CStrRef, value: Utf8CStrRef) -> bool; unsafe fn persist_set_prop(name: Utf8CStrRef, value: Utf8CStrRef) -> bool;
fn send_fd(socket: i32, fd: i32) -> bool; fn send_fd(socket: i32, fd: i32) -> bool;

View File

@@ -2,14 +2,13 @@ use std::io::Read;
use std::{ use std::{
fs::File, fs::File,
io::{BufWriter, Write}, io::{BufWriter, Write},
ops::{Deref, DerefMut},
os::fd::FromRawFd, os::fd::FromRawFd,
pin::Pin, pin::Pin,
}; };
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer}; use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
use crate::ffi::{PropCb, prop_cb_exec}; use crate::ffi::PropCallback;
use crate::resetprop::proto::persistent_properties::{ use crate::resetprop::proto::persistent_properties::{
PersistentProperties, mod_PersistentProperties::PersistentPropertyRecord, PersistentProperties, mod_PersistentProperties::PersistentPropertyRecord,
}; };
@@ -23,30 +22,6 @@ use base::{
const PERSIST_PROP_DIR: &str = "/data/property"; const PERSIST_PROP_DIR: &str = "/data/property";
const PERSIST_PROP: &str = concatcp!(PERSIST_PROP_DIR, "/persistent_properties"); const PERSIST_PROP: &str = concatcp!(PERSIST_PROP_DIR, "/persistent_properties");
trait PropCbExec {
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr);
}
impl PropCbExec for Pin<&mut PropCb> {
fn exec(&mut self, name: &Utf8CStr, value: &Utf8CStr) {
prop_cb_exec(self.as_mut(), name, value, u32::MAX)
}
}
impl Deref for PersistentProperties {
type Target = Vec<PersistentPropertyRecord>;
fn deref(&self) -> &Self::Target {
&self.properties
}
}
impl DerefMut for PersistentProperties {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.properties
}
}
trait PropExt { trait PropExt {
fn find_index(&self, name: &Utf8CStr) -> Result<usize, usize>; fn find_index(&self, name: &Utf8CStr) -> Result<usize, usize>;
fn find(&mut self, name: &Utf8CStr) -> LoggedResult<&mut PersistentPropertyRecord>; fn find(&mut self, name: &Utf8CStr) -> LoggedResult<&mut PersistentPropertyRecord>;
@@ -54,12 +29,13 @@ trait PropExt {
impl PropExt for PersistentProperties { impl PropExt for PersistentProperties {
fn find_index(&self, name: &Utf8CStr) -> Result<usize, usize> { fn find_index(&self, name: &Utf8CStr) -> Result<usize, usize> {
self.binary_search_by(|p| p.name.as_deref().cmp(&Some(name.deref()))) self.properties
.binary_search_by(|p| p.name.as_deref().cmp(&Some(name.as_str())))
} }
fn find(&mut self, name: &Utf8CStr) -> LoggedResult<&mut PersistentPropertyRecord> { fn find(&mut self, name: &Utf8CStr) -> LoggedResult<&mut PersistentPropertyRecord> {
let idx = self.find_index(name).silent()?; let idx = self.find_index(name).silent()?;
Ok(&mut self[idx]) Ok(&mut self.properties[idx])
} }
} }
@@ -110,7 +86,9 @@ fn proto_read_props() -> LoggedResult<PersistentProperties> {
let mut r = BytesReader::from_bytes(m); let mut r = BytesReader::from_bytes(m);
let mut props = PersistentProperties::from_reader(&mut r, m)?; let mut props = PersistentProperties::from_reader(&mut r, m)?;
// Keep the list sorted for binary search // Keep the list sorted for binary search
props.sort_unstable_by(|a, b| a.name.cmp(&b.name)); props
.properties
.sort_unstable_by(|a, b| a.name.cmp(&b.name));
Ok(props) Ok(props)
} }
@@ -130,7 +108,7 @@ fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> {
Ok(()) Ok(())
} }
pub fn persist_get_prop(name: &Utf8CStr, mut prop_cb: Pin<&mut PropCb>) { pub fn persist_get_prop(name: &Utf8CStr, prop_cb: Pin<&mut PropCallback>) {
let res: LoggedResult<()> = try { let res: LoggedResult<()> = try {
if check_proto() { if check_proto() {
let mut props = proto_read_props()?; let mut props = proto_read_props()?;
@@ -151,17 +129,19 @@ pub fn persist_get_prop(name: &Utf8CStr, mut prop_cb: Pin<&mut PropCb>) {
res.ok(); res.ok();
} }
pub fn persist_get_props(mut prop_cb: Pin<&mut PropCb>) { pub fn persist_get_props(mut prop_cb: Pin<&mut PropCallback>) {
let res: LoggedResult<()> = try { let res: LoggedResult<()> = try {
if check_proto() { if check_proto() {
let mut props = proto_read_props()?; let mut props = proto_read_props()?;
props.iter_mut().for_each(|prop| { props.properties.iter_mut().for_each(|prop| {
if let PersistentPropertyRecord { if let PersistentPropertyRecord {
name: Some(n), name: Some(n),
value: Some(v), value: Some(v),
} = prop } = prop
{ {
prop_cb.exec(Utf8CStr::from_string(n), Utf8CStr::from_string(v)); prop_cb
.as_mut()
.exec(Utf8CStr::from_string(n), Utf8CStr::from_string(v));
} }
}); });
} else { } else {
@@ -170,7 +150,9 @@ pub fn persist_get_props(mut prop_cb: Pin<&mut PropCb>) {
if e.is_file() if e.is_file()
&& let Ok(mut value) = file_get_prop(e.name()) && let Ok(mut value) = file_get_prop(e.name())
{ {
prop_cb.exec(e.name(), Utf8CStr::from_string(&mut value)); prop_cb
.as_mut()
.exec(e.name(), Utf8CStr::from_string(&mut value));
} }
// Do not traverse recursively // Do not traverse recursively
Ok(WalkResult::Skip) Ok(WalkResult::Skip)
@@ -185,7 +167,7 @@ pub fn persist_delete_prop(name: &Utf8CStr) -> bool {
if check_proto() { if check_proto() {
let mut props = proto_read_props()?; let mut props = proto_read_props()?;
let idx = props.find_index(name).silent()?; let idx = props.find_index(name).silent()?;
props.remove(idx); props.properties.remove(idx);
proto_write_props(&props)?; proto_write_props(&props)?;
} else { } else {
file_set_prop(name, None)?; file_set_prop(name, None)?;
@@ -199,8 +181,8 @@ pub fn persist_set_prop(name: &Utf8CStr, value: &Utf8CStr) -> bool {
if check_proto() { if check_proto() {
let mut props = proto_read_props()?; let mut props = proto_read_props()?;
match props.find_index(name) { match props.find_index(name) {
Ok(idx) => props[idx].value = Some(value.to_string()), Ok(idx) => props.properties[idx].value = Some(value.to_string()),
Err(idx) => props.insert( Err(idx) => props.properties.insert(
idx, idx,
PersistentPropertyRecord { PersistentPropertyRecord {
name: Some(name.to_string()), name: Some(name.to_string()),

View File

@@ -14,7 +14,6 @@ using namespace std;
#ifdef APPLET_STUB_MAIN #ifdef APPLET_STUB_MAIN
#define system_property_set __system_property_set #define system_property_set __system_property_set
#define system_property_read(...)
#define system_property_find __system_property_find #define system_property_find __system_property_find
#define system_property_read_callback __system_property_read_callback #define system_property_read_callback __system_property_read_callback
#define system_property_foreach __system_property_foreach #define system_property_foreach __system_property_foreach
@@ -111,30 +110,21 @@ illegal:
return false; return false;
} }
static void read_prop_with_cb(const prop_info *pi, void *cb) { void prop_callback::read(const prop_info *pi) {
if (system_property_read_callback) { auto fn = [](void *cb, const char *name, const char *value, uint32_t serial) {
auto callback = [](void *cb, const char *name, const char *value, uint32_t serial) { static_cast<prop_callback*>(cb)->exec(name, value, serial);
static_cast<prop_cb*>(cb)->exec(name, value, serial); };
}; system_property_read_callback(pi, fn, this);
system_property_read_callback(pi, callback, cb);
} else {
char name[PROP_NAME_MAX];
char value[PROP_VALUE_MAX];
name[0] = '\0';
value[0] = '\0';
system_property_read(pi, name, value);
static_cast<prop_cb*>(cb)->exec(name, value, pi->serial);
}
} }
template<class StringType> template<class StringType>
struct prop_to_string : prop_cb { struct prop_to_string : prop_callback {
void exec(const char *, const char *value, uint32_t s) override { void exec(const char *, const char *value, uint32_t s) override {
val = value; val = value;
serial = s; serial = s;
} }
StringType val; StringType val;
uint32_t serial; uint32_t serial = 0;
}; };
template<> void prop_to_string<rust::String>::exec(const char *, const char *value, uint32_t s) { template<> void prop_to_string<rust::String>::exec(const char *, const char *value, uint32_t s) {
@@ -212,7 +202,7 @@ static StringType get_prop(const char *name, PropFlags flags) {
if (!flags.isPersistOnly()) { if (!flags.isPersistOnly()) {
if (auto pi = system_property_find(name)) { if (auto pi = system_property_find(name)) {
read_prop_with_cb(pi, &cb); cb.read(pi);
LOGD("resetprop: get prop [%s]: [%s]\n", name, cb.val.c_str()); LOGD("resetprop: get prop [%s]: [%s]\n", name, cb.val.c_str());
} }
} }
@@ -238,13 +228,13 @@ static StringType wait_prop(const char *name, const char *old_value) {
} }
prop_to_string<StringType> cb; prop_to_string<StringType> cb;
read_prop_with_cb(pi, &cb); cb.read(pi);
while (old_value == nullptr || cb.val == old_value) { while (old_value == nullptr || cb.val == old_value) {
LOGD("resetprop: waiting for prop [%s]\n", name); LOGD("resetprop: waiting for prop [%s]\n", name);
uint32_t new_serial; uint32_t new_serial;
system_property_wait(pi, cb.serial, &new_serial, nullptr); system_property_wait(pi, cb.serial, &new_serial, nullptr);
read_prop_with_cb(pi, &cb); cb.read(pi);
if (old_value == nullptr) break; if (old_value == nullptr) break;
} }
@@ -252,14 +242,23 @@ static StringType wait_prop(const char *name, const char *old_value) {
return cb.val; return cb.val;
} }
struct prop_collector : prop_callback {
void exec(const char *name, const char *value, uint32_t) override {
list.insert({name, value});
}
map<string, string> list;
};
static void print_props(PropFlags flags) { static void print_props(PropFlags flags) {
prop_list list; prop_collector collector;
prop_collector collector(list); if (!flags.isPersistOnly()) {
if (!flags.isPersistOnly()) system_property_foreach([](const prop_info *pi, void *cb) {
system_property_foreach(read_prop_with_cb, &collector); static_cast<prop_callback*>(cb)->read(pi);
}, &collector);
}
if (flags.isPersist()) if (flags.isPersist())
persist_get_props(collector); persist_get_props(collector);
for (auto &[key, val] : list) { for (auto &[key, val] : collector.list) {
const char *v = flags.isContext() ? const char *v = flags.isContext() ?
(__system_property_get_context(key.data()) ?: "") : (__system_property_get_context(key.data()) ?: "") :
val.data(); val.data();
@@ -305,6 +304,17 @@ struct Initialize {
// The platform API only exist on API 26+ // The platform API only exist on API 26+
system_property_wait = __system_property_wait; system_property_wait = __system_property_wait;
} }
if (system_property_read_callback == nullptr) {
// The platform API only exist on API 26+, create a polyfill
system_property_read_callback = [](const prop_info *pi, auto fn, void *cookie) {
char name[PROP_NAME_MAX];
char value[PROP_VALUE_MAX];
name[0] = '\0';
value[0] = '\0';
system_property_read(pi, name, value);
fn(cookie, name, value, pi->serial);
};
}
#endif #endif
if (__system_properties_init()) { if (__system_properties_init()) {
LOGE("resetprop: __system_properties_init error\n"); LOGE("resetprop: __system_properties_init error\n");
@@ -313,7 +323,7 @@ struct Initialize {
}; };
static void InitOnce() { static void InitOnce() {
static struct Initialize init; static Initialize init;
} }
#define consume_next(val) \ #define consume_next(val) \