@@ -37,6 +37,14 @@ include!("common.rs");
37
37
// core::ffi::c_* (except c_void) requires Rust 1.64
38
38
#[ allow( non_camel_case_types) ]
39
39
mod ffi {
40
+ // c_char is u8 on aarch64 Linux/Android
41
+ // https://github.com/rust-lang/rust/blob/1.67.0/library/core/src/ffi/mod.rs#L104-L157
42
+ #[ cfg( target_os = "android" ) ]
43
+ pub ( crate ) type c_char = u8 ;
44
+ // c_{,u}int is {i,u}32 on non-16-bit architectures
45
+ // https://github.com/rust-lang/rust/blob/1.67.0/library/core/src/ffi/mod.rs#L159-L173
46
+ #[ cfg( target_os = "android" ) ]
47
+ pub ( crate ) type c_int = i32 ;
40
48
// https://github.com/rust-lang/rust/blob/1.67.0/library/core/src/ffi/mod.rs#L175-L190
41
49
#[ cfg( target_pointer_width = "64" ) ]
42
50
pub ( crate ) type c_ulong = u64 ;
@@ -49,6 +57,11 @@ mod ffi {
49
57
// https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/linux/musl/mod.rs#L744
50
58
// https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/android/b64/mod.rs#L333
51
59
pub ( crate ) fn getauxval ( type_ : c_ulong ) -> c_ulong ;
60
+
61
+ // Defined in sys/system_properties.h.
62
+ // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/android/mod.rs#L3471
63
+ #[ cfg( target_os = "android" ) ]
64
+ pub ( crate ) fn __system_property_get ( __name : * const c_char , __value : * mut c_char ) -> c_int ;
52
65
}
53
66
54
67
// https://github.com/torvalds/linux/blob/HEAD/include/uapi/linux/auxvec.h
@@ -57,10 +70,34 @@ mod ffi {
57
70
pub ( crate ) const HWCAP_ATOMICS : c_ulong = 1 << 8 ;
58
71
#[ cfg( test) ]
59
72
pub ( crate ) const HWCAP_USCAT : c_ulong = 1 << 25 ;
73
+
74
+ // Defined in sys/system_properties.h.
75
+ // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/android/mod.rs#L2760
76
+ #[ cfg( target_os = "android" ) ]
77
+ pub ( crate ) const PROP_VALUE_MAX : c_int = 92 ;
60
78
}
61
79
62
80
#[ inline]
63
81
fn _detect ( info : & mut CpuInfo ) {
82
+ #[ cfg( target_os = "android" ) ]
83
+ {
84
+ // Samsung Exynos 9810 has a bug that big and little cores have different
85
+ // ISAs. And on older Android (pre-9), the kernel incorrectly reports
86
+ // that features available only on some cores are available on all cores.
87
+ // https://reviews.llvm.org/D114523
88
+ let mut arch = [ 0_u8 ; ffi:: PROP_VALUE_MAX as usize ] ;
89
+ // SAFETY: we've passed a valid C string and a buffer with max length.
90
+ let len = unsafe {
91
+ ffi:: __system_property_get (
92
+ b"ro.arch\0 " . as_ptr ( ) as * const ffi:: c_char ,
93
+ arch. as_mut_ptr ( ) as * mut ffi:: c_char ,
94
+ )
95
+ } ;
96
+ if len > 0 && arch. starts_with ( b"exynos9810\0 " ) {
97
+ return ;
98
+ }
99
+ }
100
+
64
101
// SAFETY: getauxval is available in all versions on aarch64 linux-gnu/android.
65
102
// See also the module level docs.
66
103
let hwcap = unsafe { ffi:: getauxval ( ffi:: AT_HWCAP ) } ;
@@ -88,6 +125,29 @@ fn _detect(info: &mut CpuInfo) {
88
125
mod tests {
89
126
use super :: * ;
90
127
128
+ #[ allow( clippy:: cast_sign_loss) ]
129
+ #[ cfg( target_os = "android" ) ]
130
+ #[ test]
131
+ fn test_android ( ) {
132
+ unsafe {
133
+ let mut arch = [ 1 ; ffi:: PROP_VALUE_MAX as usize ] ;
134
+ let len = ffi:: __system_property_get (
135
+ b"ro.arch\0 " . as_ptr ( ) as * const ffi:: c_char ,
136
+ arch. as_mut_ptr ( ) ,
137
+ ) ;
138
+ if len < 1 {
139
+ std:: println!( "len={}" , len) ;
140
+ }
141
+ std:: println!( "len={}" , len) ;
142
+ std:: println!( "arch={:?}" , arch) ;
143
+ std:: println!(
144
+ "arch={:?}" ,
145
+ core:: str :: from_utf8( core:: slice:: from_raw_parts( arch. as_ptr( ) , len as usize ) )
146
+ . unwrap( )
147
+ ) ;
148
+ }
149
+ }
150
+
91
151
// Static assertions for FFI bindings.
92
152
// This checks that FFI bindings defined in this crate, FFI bindings defined
93
153
// in libc, and FFI bindings generated for the platform's latest header file
@@ -105,10 +165,27 @@ mod tests {
105
165
) ]
106
166
const _: fn ( ) = || {
107
167
use crate :: tests:: sys:: * ;
168
+ #[ cfg( target_os = "android" ) ]
169
+ let _: ffi:: c_char = 0 as std:: os:: raw:: c_char ;
170
+ #[ cfg( target_os = "android" ) ]
171
+ let _: ffi:: c_char = 0 as libc:: c_char ;
172
+ #[ cfg( target_os = "android" ) ]
173
+ let _: ffi:: c_int = 0 as std:: os:: raw:: c_int ;
174
+ #[ cfg( target_os = "android" ) ]
175
+ let _: ffi:: c_int = 0 as libc:: c_int ;
108
176
let _: ffi:: c_ulong = 0 as std:: os:: raw:: c_ulong ;
109
177
let _: ffi:: c_ulong = 0 as libc:: c_ulong ;
110
178
let mut _getauxval: unsafe extern "C" fn ( ffi:: c_ulong ) -> ffi:: c_ulong = ffi:: getauxval;
111
179
_getauxval = libc:: getauxval;
180
+ #[ cfg( target_os = "android" ) ]
181
+ let mut ___system_property_get: unsafe extern "C" fn (
182
+ * const ffi:: c_char ,
183
+ * mut ffi:: c_char ,
184
+ ) -> ffi:: c_int = ffi:: __system_property_get;
185
+ #[ cfg( target_os = "android" ) ]
186
+ {
187
+ ___system_property_get = libc:: __system_property_get;
188
+ }
112
189
let [ ] = [ ( ) ; ( ffi:: AT_HWCAP - libc:: AT_HWCAP ) as usize ] ;
113
190
let [ ] =
114
191
[ ( ) ; ( ffi:: AT_HWCAP - include_uapi_linux_auxvec:: AT_HWCAP as ffi:: c_ulong ) as usize ] ;
@@ -120,5 +197,7 @@ mod tests {
120
197
let [ ] = [ ( ) ; ( ffi:: HWCAP_USCAT
121
198
- arch_arm64_include_uapi_asm_hwcap:: HWCAP_USCAT as ffi:: c_ulong )
122
199
as usize ] ;
200
+ #[ cfg( target_os = "android" ) ]
201
+ let [ ] = [ ( ) ; ( ffi:: PROP_VALUE_MAX - libc:: PROP_VALUE_MAX ) as usize ] ;
123
202
} ;
124
203
}
0 commit comments