android_properties/android/
mod.rs1use 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 fn __system_property_get(name: *const c_char, value: *mut c_char) -> c_int;
46}
47
48pub 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#[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#[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
87pub 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#[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#[cfg(feature = "bionic-deprecated")]
109pub fn plat_get_property_info(_name: &str) -> *const c_void {
110 std::ptr::null()
111}