Skip to content

Commit

Permalink
WIP: api-level bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
MarijnS95 committed Jul 25, 2024
1 parent e4a0b94 commit d9dd843
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 0 deletions.
1 change: 1 addition & 0 deletions ndk-sys/generate_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ while read ARCH && read TARGET ; do
--blocklist-item 'C?_?JNIEnv' \
--blocklist-item '_?JavaVM' \
--blocklist-item '_?j\w+' \
--blocklist-item '__ANDROID_API__' \
--newtype-enum '\w+_(result|status)_t' \
--newtype-enum 'ACameraDevice_request_template' \
--newtype-enum 'ADataSpace' \
Expand Down
154 changes: 154 additions & 0 deletions ndk/src/api_level.rs
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() }
}
1 change: 1 addition & 0 deletions ndk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

pub mod api_level;
pub mod asset;
pub mod audio;
pub mod bitmap;
Expand Down

0 comments on commit d9dd843

Please sign in to comment.