From 4adcffe2cec22fda1d753d5fb3b95cb6eb511eb2 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sat, 10 Aug 2024 15:25:09 +0200 Subject: [PATCH] Add bindings for Permission Manager (`checkPermission()`) --- ndk/CHANGELOG.md | 1 + ndk/src/lib.rs | 1 + ndk/src/permission_manager.rs | 53 +++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 ndk/src/permission_manager.rs diff --git a/ndk/CHANGELOG.md b/ndk/CHANGELOG.md index 4bc9a7e2..ec7c4e61 100644 --- a/ndk/CHANGELOG.md +++ b/ndk/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased - image_reader: Add `ImageReader::new_with_data_space()` constructor and `ImageReader::data_space()` getter from API level 34. (#474) +- Add bindings for Permission Manager (`checkPermission()`). (#484) # 0.9.0 (2024-04-26) diff --git a/ndk/src/lib.rs b/ndk/src/lib.rs index 81e2ef61..a628e0a3 100644 --- a/ndk/src/lib.rs +++ b/ndk/src/lib.rs @@ -26,6 +26,7 @@ pub mod media; pub mod media_error; pub mod native_activity; pub mod native_window; +pub mod permission_manager; pub mod shared_memory; pub mod surface_texture; pub mod sync; diff --git a/ndk/src/permission_manager.rs b/ndk/src/permission_manager.rs new file mode 100644 index 00000000..53378e51 --- /dev/null +++ b/ndk/src/permission_manager.rs @@ -0,0 +1,53 @@ +//! Bindings for permission checks +//! +//! +#![cfg(feature = "api-level-31")] + +use std::{ffi::CStr, mem::MaybeUninit}; + +use num_enum::{FromPrimitive, IntoPrimitive}; + +/// Permission check return status values. +#[repr(i32)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)] +#[non_exhaustive] +pub enum PermissionManagerStatus { + /// This is returned if the permission check encountered an unspecified error. + ErrorUnknown = ffi::PERMISSION_MANAGER_STATUS_ERROR_UNKNOWN, + /// This is returned if the permission check failed because the service is unavailable. + ServiceUnavailable = ffi::PERMISSION_MANAGER_STATUS_SERVICE_UNAVAILABLE, + + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(i32) = 0, +} + +/// Checks whether the package with the given pid/uid has been granted a permission. +/// +/// Note that the Java API of [`Context#checkPermission()`] is usually faster due to caching, +/// thus is preferred over this API wherever possible. +/// +/// [`Context#checkPermission()`]: https://developer.android.com/reference/android/content/Context#checkPermission(java.lang.String,%20int,%20int) +/// +/// # Parameters +/// - `permission`: the permission to be checked. +/// - `pid`: the process id of the package to be checked. +/// - `uid`: the uid of the package to be checked. +#[doc(alias = "APermissionManager_checkPermission")] +pub fn check_permission( + permission: &CStr, + pid: i32, + uid: u32, +) -> Result { + let mut result = MaybeUninit::uninit(); + match unsafe { + ffi::APermissionManager_checkPermission(permission.as_ptr(), pid, uid, result.as_mut_ptr()) + } { + ffi::PERMISSION_MANAGER_STATUS_OK => Ok(match unsafe { result.assume_init() } { + ffi::PERMISSION_MANAGER_PERMISSION_GRANTED => true, + ffi::PERMISSION_MANAGER_PERMISSION_DENIED => false, + x => unreachable!("Unexpected `PERMISSION` result output {x}"), + }), + x => Err(x.into()), + } +}