-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
//! `__ANDROID_API__` is the [API | ||
//! level](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels) | ||
//! this code is being built for. The resulting binaries are only guaranteed to | ||
//! be compatible with devices which have an API level greater than or equal to | ||
//! `__ANDROID_API__`. | ||
//! | ||
//! For NDK and APEX builds, this macro will always be defined. It is set | ||
//! automatically by Clang using the version suffix that is a part of the target | ||
//! name. For example, `__ANDROID_API__` will be 24 when Clang is given the | ||
//! argument `-target aarch64-linux-android24`. | ||
//! | ||
//! For non-APEX OS code, this defaults to __ANDROID_API_FUTURE__. | ||
//! | ||
//! The value of `__ANDROID_API__` can be compared to the named constants in | ||
//! `<android/api-level.h>`. | ||
//! | ||
//! The interpretation of `__ANDROID_API__` is similar to the AndroidManifest.xml | ||
//! `minSdkVersion`. In most cases `__ANDROID_API__` will be identical to | ||
//! `minSdkVersion`, but as it is a build time constant it is possible for | ||
//! library code to use a different value than the app it will be included in. | ||
//! When libraries and applications build for different API levels, the | ||
//! `minSdkVersion` of the application must be at least as high as the highest | ||
//! API level used by any of its libraries which are loaded unconditionally. | ||
//! | ||
//! Note that in some cases the resulting binaries may load successfully on | ||
//! devices with an older API level. That behavior should not be relied upon, | ||
//! even if you are careful to avoid using new APIs, as the toolchain may make | ||
//! use of new features by default. For example, additional FORTIFY features may | ||
//! implicitly make use of new APIs, SysV hashes may be omitted in favor of GNU | ||
//! hashes to improve library load times, or relocation packing may be enabled to | ||
//! reduce binary size. | ||
//! | ||
//! See android_get_device_api_level(), | ||
//! android_get_application_target_sdk_version() and | ||
//! https://android.googlesource.com/platform/bionic/+/master/docs/defines.md. | ||
|
||
use num_enum::{FromPrimitive, IntoPrimitive}; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, IntoPrimitive)] | ||
#[repr(u32)] | ||
#[non_exhaustive] | ||
pub enum ApiLevel { | ||
/** Names the Gingerbread API level (9) */ | ||
G = ffi::__ANDROID_API_G__, | ||
|
||
/** Names the Ice-Cream Sandwich API level (14) */ | ||
I = ffi::__ANDROID_API_I__, | ||
|
||
/** Names the Jellybean API level (16) */ | ||
J = ffi::__ANDROID_API_J__, | ||
|
||
/** Names the Jellybean MR1 API level (17) */ | ||
J_MR1 = ffi::__ANDROID_API_J_MR1__, | ||
|
||
/** Names the Jellybean MR2 API level (18) */ | ||
J_MR2 = ffi::__ANDROID_API_J_MR2__, | ||
|
||
/** Names the KitKat API level (19) */ | ||
K = ffi::__ANDROID_API_K__, | ||
|
||
/** Names the Lollipop API level (21) */ | ||
L = ffi::__ANDROID_API_L__, | ||
|
||
/** Names the Lollipop MR1 API level (22) */ | ||
L_MR1 = ffi::__ANDROID_API_L_MR1__, | ||
|
||
/** Names the Marshmallow API level (23) */ | ||
M = ffi::__ANDROID_API_M__, | ||
|
||
/** Names the Nougat API level (24) */ | ||
N = ffi::__ANDROID_API_N__, | ||
|
||
/** Names the Nougat MR1 API level (25) */ | ||
N_MR1 = ffi::__ANDROID_API_N_MR1__, | ||
|
||
/** Names the Oreo API level (26) */ | ||
O = ffi::__ANDROID_API_O__, | ||
|
||
/** Names the Oreo MR1 API level (27) */ | ||
O_MR1 = ffi::__ANDROID_API_O_MR1__, | ||
|
||
/** Names the Pie API level (28) */ | ||
P = ffi::__ANDROID_API_P__, | ||
|
||
/** Names the Android 10 (aka "Q" or "Quince Tart") API level (29) */ | ||
Q = ffi::__ANDROID_API_Q__, | ||
|
||
/** Names the Android 11 (aka "R" or "Red Velvet Cake") API level (30) */ | ||
R = ffi::__ANDROID_API_R__, | ||
|
||
/** Names the Android 12 (aka "S" or "Snowcone") API level (31) */ | ||
S = ffi::__ANDROID_API_S__, | ||
|
||
/** Names the Android 13 (aka "T" or "Tiramisu") API level (33) */ | ||
T = ffi::__ANDROID_API_T__, | ||
|
||
/** Names the Android 14 (aka "U" or "UpsideDownCake") API level (34) */ | ||
U = ffi::__ANDROID_API_U__, | ||
|
||
/** Names the "V" API level (35) */ | ||
V = ffi::__ANDROID_API_V__, | ||
|
||
#[doc(hidden)] | ||
#[num_enum(catch_all)] | ||
__Unknown(u32), | ||
} | ||
|
||
/// Returns the `targetSdkVersion` of the caller, or [`ffi::__ANDROID_API_FUTURE__`] if there is no | ||
/// known target SDK version (for code not running in the context of an app). | ||
/// | ||
/// The returned values correspond to the named constants in `<android/api-level.h>`, and is | ||
/// equivalent to the `AndroidManifest.xml` `targetSdkVersion`. | ||
/// | ||
/// See also [`device_api_level()`]. | ||
#[cfg(feature = "api-level-24")] | ||
pub fn application_target_sdk_version() -> i32 { | ||
#[cfg(feature = "api-level-29")] | ||
unsafe { | ||
ffi::android_get_application_target_sdk_version() | ||
} | ||
|
||
#[cfg(not(feature = "api-level-29"))] | ||
{ | ||
use std::ffi::{c_char, c_int}; | ||
let mut value = [0; 92]; | ||
if unsafe { | ||
// TODO: from sys/cdefs.h, available in libc | ||
extern "C" { | ||
fn __system_property_get(__name: *const c_char, __value: *mut c_char) -> c_int; | ||
} | ||
// libc:: | ||
__system_property_get(c"ro.build.version.sdk".as_ptr(), value.as_mut_ptr()) | ||
} < 1 | ||
{ | ||
-1 | ||
} else { | ||
std::str::from_utf8(&value) | ||
.unwrap_or("") | ||
.parse() | ||
.unwrap_or(-1) | ||
// TODO: Return -1 if this is 0? | ||
} | ||
} | ||
} | ||
|
||
/// Returns the API level of the device we're actually running on, or `-1` on failure. The returned | ||
/// values correspond to the named constants in `<android/api-level.h>`, and is equivalent to the | ||
/// Java `Build.VERSION.SDK_INT` API. | ||
/// | ||
/// See also [`application_target_sdk_version()`]. | ||
#[cfg(feature = "api-level-29")] | ||
pub fn device_api_level() -> i32 { | ||
unsafe { ffi::android_get_device_api_level() } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters