android_properties/android/
mod.rs

1use crate::AndroidProperty;
2
3use std::{
4    ffi::{CStr, CString},
5    os::raw::{c_char, c_int, c_void},
6};
7
8type Callback = unsafe fn(*mut ValuePair, *const c_char, *const c_char, u32);
9type ForEachCallback = unsafe fn(*const c_void, *mut Vec<AndroidProperty>);
10
11struct ValuePair {
12    name: String,
13    value: String,
14}
15
16unsafe fn property_callback(cookie: *mut ValuePair, name: *const c_char, value: *const c_char, _serial: u32) {
17    let cname = CStr::from_ptr(name);
18    let cvalue = CStr::from_ptr(value);
19    (*cookie).name = cname.to_str().unwrap().to_string();
20    (*cookie).value = cvalue.to_str().unwrap().to_string();
21}
22
23unsafe fn foreach_property_callback(pi: *const c_void, cookie: *mut Vec<AndroidProperty>) {
24    let mut result = Box::new(ValuePair {
25        name: String::new(),
26        value: String::new(),
27    });
28    __system_property_read_callback(pi, property_callback, &mut *result);
29    (*cookie).push(AndroidProperty {
30        name: (*result).name,
31        property_info: pi,
32    });
33}
34
35extern "C" {
36    fn __system_property_set(name: *const c_char, value: *const c_char) -> c_int;
37    fn __system_property_find(name: *const c_char) -> *const c_void;
38    fn __system_property_read_callback(pi: *const c_void, callback: Callback, cookie: *mut ValuePair);
39    fn __system_property_foreach(callback: ForEachCallback, cookie: *mut Vec<AndroidProperty>) -> c_int;
40}
41
42#[cfg(feature = "bionic-deprecated")]
43extern "C" {
44    /* Deprecated. Use __system_property_read_callback instead. */
45    fn __system_property_get(name: *const c_char, value: *mut c_char) -> c_int;
46}
47
48/// Set system property `name` to `value`, creating the system property if it doesn't already exist
49pub fn plat_setprop(name: &str, value: &str) -> Result<(), String> {
50    let cname = CString::new(name).unwrap();
51    let cvalue = CString::new(value).unwrap();
52    let ret = unsafe { __system_property_set(cname.as_ptr(), cvalue.as_ptr()) };
53    if ret >= 0 {
54        Ok(())
55    } else {
56        Err(format!("Failed to set Android property \"{}\" to \"{}\"", name, value))
57    }
58}
59
60/// Retrieve a property with name `name`. Returns None if the operation fails.
61#[cfg(not(feature = "bionic-deprecated"))]
62pub fn plat_getprop(_: &str, property_info: *const c_void) -> Option<String> {
63    let mut result = Box::new(ValuePair {
64        name: String::new(),
65        value: String::new(),
66    });
67    if !property_info.is_null() {
68        unsafe { __system_property_read_callback(property_info, property_callback, &mut *result) };
69    }
70    Some((*result).value)
71}
72
73/// Retrieve a property with name `name`. Returns None if the operation fails.
74#[cfg(feature = "bionic-deprecated")]
75pub fn plat_getprop(name: &str, _: *const c_void) -> Option<String> {
76    const PROPERTY_VALUE_MAX: usize = 92;
77    let cname = CString::new(name).unwrap();
78    let cvalue = CString::new(Vec::with_capacity(PROPERTY_VALUE_MAX)).unwrap();
79    let raw = cvalue.into_raw();
80    let ret = unsafe { __system_property_get(cname.as_ptr(), raw) };
81    match ret {
82        len if len > 0 => unsafe { Some(String::from_raw_parts(raw as *mut u8, len as usize, PROPERTY_VALUE_MAX)) },
83        _ => None,
84    }
85}
86
87/// Returns an iterator to vector, which contains all properties present in a system
88pub fn plat_prop_values() -> impl Iterator<Item = AndroidProperty> {
89    let mut properties: Box<Vec<AndroidProperty>> = Box::new(Vec::new());
90    unsafe {
91        __system_property_foreach(foreach_property_callback, &mut *properties);
92    }
93    properties.into_iter()
94}
95
96/// Find property_info pointer using bionic syscall
97///
98/// returns nullptr if not found, otherwise valid pointer
99#[cfg(not(feature = "bionic-deprecated"))]
100pub fn plat_get_property_info(name: &str) -> *const c_void {
101    let cname = CString::new(name).unwrap();
102    unsafe { __system_property_find(cname.as_ptr()) }
103}
104
105/// Deprecated version to find property_info pointer
106///
107/// Always returns nullptr
108#[cfg(feature = "bionic-deprecated")]
109pub fn plat_get_property_info(_name: &str) -> *const c_void {
110    std::ptr::null()
111}