summaryrefslogtreecommitdiffstats
path: root/third_party/rust/ashmem
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/ashmem')
-rw-r--r--third_party/rust/ashmem/.cargo-checksum.json1
-rw-r--r--third_party/rust/ashmem/Cargo.toml24
-rw-r--r--third_party/rust/ashmem/README.md14
-rwxr-xr-xthird_party/rust/ashmem/src/lib.rs160
4 files changed, 199 insertions, 0 deletions
diff --git a/third_party/rust/ashmem/.cargo-checksum.json b/third_party/rust/ashmem/.cargo-checksum.json
new file mode 100644
index 0000000000..4fac4e23d1
--- /dev/null
+++ b/third_party/rust/ashmem/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"3b0ce20438cc2ce5485f734aaf93b50976757d39eab3d78b788932cf734d7830","README.md":"1513a18130cee5213ff581dd1703897ba9ad3f99fc601e502745833f93b78a25","src/lib.rs":"1306aacebf851c0ba32ef6c142dc35db678cf5463f267a226a4a10fd1c02041b"},"package":"b947f77692187a29daa2768b6644e589cef61e7434bb96300197acfb876105ac"} \ No newline at end of file
diff --git a/third_party/rust/ashmem/Cargo.toml b/third_party/rust/ashmem/Cargo.toml
new file mode 100644
index 0000000000..81ccdbddbf
--- /dev/null
+++ b/third_party/rust/ashmem/Cargo.toml
@@ -0,0 +1,24 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "ashmem"
+version = "0.1.2"
+authors = ["Matthew Gregan <kinetik@flim.org>"]
+description = "Rust wrapper around Android's ASharedMemory (ashmem) API"
+license = "ISC"
+repository = "https://github.com/kinetiknz/ashmem-rs"
+[dependencies.ioctl-sys]
+version = "0.7"
+
+[dependencies.libc]
+version = "0.2"
diff --git a/third_party/rust/ashmem/README.md b/third_party/rust/ashmem/README.md
new file mode 100644
index 0000000000..ce19cf4e15
--- /dev/null
+++ b/third_party/rust/ashmem/README.md
@@ -0,0 +1,14 @@
+# ashmem-rs
+
+Provides a compatibility interface for Android 8.0's public ASharedMemory API.
+
+Some variant of ashmem has existed in Android as a private API for some time. Originally available only via [direct ioctl interface](https://elixir.bootlin.com/linux/v5.11.8/source/drivers/staging/android/uapi/ashmem.h), it later became callable (still private) via ashmem_create_region (et al.) in libcutils.
+
+[ASharedMemory](https://developer.android.com/ndk/reference/group/memory) is the public API to ashmem made available in Android 8.0 (API level 26).
+Builds targeting Android 10 (API 29) are no longer permitted to access ashmem via the ioctl interface. This makes life for a portable program difficult - you can't reliably use the old or new interface during this transition period.
+
+ashmem-rs provides a simple wrapper around the ASharedMemory API, directly calling the public API implementation via dynamically loaded libandroid where available, and falling back to the direct ioctl interface elsewhere.
+
+References:
+ - [ASharedMemory documentation](https://developer.android.com/ndk/reference/group/memory)
+ - [Linux kernel ashmem.h definitions](https://elixir.bootlin.com/linux/v5.11.8/source/drivers/staging/android/uapi/ashmem.h)
diff --git a/third_party/rust/ashmem/src/lib.rs b/third_party/rust/ashmem/src/lib.rs
new file mode 100755
index 0000000000..93c91c8969
--- /dev/null
+++ b/third_party/rust/ashmem/src/lib.rs
@@ -0,0 +1,160 @@
+#![cfg(target_os = "android")]
+//! Provides a wrapper around Android's ASharedMemory API.
+//!
+//! ashmem has existed in Android as a non-public API for some time.
+//! Originally accessed via ioctl, it was later available via libcutils as ashmem_create_region etc.
+//! ASharedMemory is the new public API, but it isn't available until API 26 (Android 8).
+//! Builds targeting Android 10 (API 29) are no longer permitted to access ashmem via the ioctl interface.
+//! This makes life for a portable program difficult - you can't reliably use the old or new interface during this transition period.
+//! We try to dynamically load the new API first, then fall back to the ioctl interface.
+//!
+//! References:
+//! - [ASharedMemory documentation](https://developer.android.com/ndk/reference/group/memory)
+//! - [Linux ashmem.h definitions](https://elixir.bootlin.com/linux/v5.11.8/source/drivers/staging/android/uapi/ashmem.h)
+
+#[macro_use]
+extern crate ioctl_sys;
+
+const __ASHMEMIOC: u32 = 0x77;
+
+static mut LIBANDROID_ASHAREDMEMORY_CREATE: Option<
+ extern "C" fn(*const libc::c_char, libc::size_t) -> libc::c_int,
+> = None;
+static mut LIBANDROID_ASHAREDMEMORY_GETSIZE: Option<extern "C" fn(libc::c_int) -> libc::size_t> =
+ None;
+static mut LIBANDROID_ASHAREDMEMORY_SETPROT: Option<
+ extern "C" fn(libc::c_int, libc::c_int) -> libc::c_int,
+> = None;
+
+unsafe fn maybe_init() {
+ const LIBANDROID_NAME: *const libc::c_char = "libandroid.so\0".as_ptr() as *const libc::c_char;
+ const LIBANDROID_ASHAREDMEMORY_CREATE_NAME: *const libc::c_char =
+ "ASharedMemory_create\0".as_ptr() as _;
+ const LIBANDROID_ASHAREDMEMORY_GETSIZE_NAME: *const libc::c_char =
+ "ASharedMemory_getSize\0".as_ptr() as _;
+ const LIBANDROID_ASHAREDMEMORY_SETPROT_NAME: *const libc::c_char =
+ "ASharedMemory_setProt\0".as_ptr() as _;
+ static ONCE: std::sync::Once = std::sync::Once::new();
+ ONCE.call_once(|| {
+ // Leak the handle, there's no safe time to close it.
+ let handle = libc::dlopen(LIBANDROID_NAME, libc::RTLD_LAZY | libc::RTLD_LOCAL);
+ if handle.is_null() {
+ return;
+ }
+ // Transmute guarantee for `fn -> Option<fn>`: https://doc.rust-lang.org/std/option/#representation
+ LIBANDROID_ASHAREDMEMORY_CREATE =
+ std::mem::transmute(libc::dlsym(handle, LIBANDROID_ASHAREDMEMORY_CREATE_NAME));
+ LIBANDROID_ASHAREDMEMORY_GETSIZE =
+ std::mem::transmute(libc::dlsym(handle, LIBANDROID_ASHAREDMEMORY_GETSIZE_NAME));
+ LIBANDROID_ASHAREDMEMORY_SETPROT =
+ std::mem::transmute(libc::dlsym(handle, LIBANDROID_ASHAREDMEMORY_SETPROT_NAME));
+ });
+}
+
+/// See [ASharedMemory_create NDK documentation](https://developer.android.com/ndk/reference/group/memory#asharedmemory_create)
+///
+/// # Safety
+///
+/// Directly calls C or kernel APIs.
+#[allow(non_snake_case)]
+pub unsafe fn ASharedMemory_create(name: *const libc::c_char, size: libc::size_t) -> libc::c_int {
+ const ASHMEM_NAME_DEF: *const libc::c_char = "/dev/ashmem\0".as_ptr() as _;
+ const ASHMEM_NAME_LEN: usize = 256;
+ const ASHMEM_SET_NAME: libc::c_int = iow!(
+ __ASHMEMIOC,
+ 1,
+ std::mem::size_of::<[libc::c_char; ASHMEM_NAME_LEN]>()
+ ) as _;
+ const ASHMEM_SET_SIZE: libc::c_int =
+ iow!(__ASHMEMIOC, 3, std::mem::size_of::<libc::size_t>()) as _;
+
+ maybe_init();
+ if let Some(fun) = LIBANDROID_ASHAREDMEMORY_CREATE {
+ return fun(name, size);
+ }
+
+ let fd = libc::open(ASHMEM_NAME_DEF, libc::O_RDWR, 0o600);
+ if fd < 0 {
+ return fd;
+ }
+
+ if !name.is_null() {
+ // NOTE: libcutils uses a local stack copy of `name`.
+ let r = libc::ioctl(fd, ASHMEM_SET_NAME, name);
+ if r != 0 {
+ libc::close(fd);
+ return -1;
+ }
+ }
+
+ let r = libc::ioctl(fd, ASHMEM_SET_SIZE, size);
+ if r != 0 {
+ libc::close(fd);
+ return -1;
+ }
+
+ fd
+}
+
+/// See [ASharedMemory_getSize NDK documentation](https://developer.android.com/ndk/reference/group/memory#asharedmemory_getsize)
+///
+/// # Safety
+///
+/// Directly calls C or kernel APIs.
+#[allow(non_snake_case)]
+pub unsafe fn ASharedMemory_getSize(fd: libc::c_int) -> libc::size_t {
+ const ASHMEM_GET_SIZE: libc::c_int = io!(__ASHMEMIOC, 4) as _;
+
+ maybe_init();
+ if let Some(fun) = LIBANDROID_ASHAREDMEMORY_GETSIZE {
+ return fun(fd);
+ }
+
+ libc::ioctl(fd, ASHMEM_GET_SIZE) as libc::size_t
+}
+
+/// See [ASharedMemory_setProt NDK documentation](https://developer.android.com/ndk/reference/group/memory#asharedmemory_setprot)
+///
+/// # Safety
+///
+/// Directly calls C or kernel APIs.
+#[allow(non_snake_case)]
+pub unsafe fn ASharedMemory_setProt(fd: libc::c_int, prot: libc::c_int) -> libc::c_int {
+ const ASHMEM_SET_PROT_MASK: libc::c_int =
+ iow!(__ASHMEMIOC, 5, std::mem::size_of::<libc::c_ulong>()) as _;
+
+ maybe_init();
+ if let Some(fun) = LIBANDROID_ASHAREDMEMORY_SETPROT {
+ return fun(fd, prot);
+ }
+
+ let r = libc::ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
+ if r != 0 {
+ return -1;
+ }
+ r
+}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn basic() {
+ unsafe {
+ let name = std::ffi::CString::new("/test-ashmem").unwrap();
+ let fd = super::ASharedMemory_create(name.as_ptr(), 128);
+ assert!(fd >= 0);
+ assert_eq!(super::ASharedMemory_getSize(fd), 128);
+ assert_eq!(super::ASharedMemory_setProt(fd, 0), 0);
+ libc::close(fd);
+ }
+ }
+
+ #[test]
+ fn anonymous() {
+ unsafe {
+ let fd = super::ASharedMemory_create(std::ptr::null(), 128);
+ assert!(fd >= 0);
+ libc::close(fd);
+ }
+ }
+}