android_native_keyring_store/
lib.rs

1use std::collections::HashMap;
2use std::ffi::c_void;
3use std::sync::{Arc, OnceLock};
4
5use jni::{
6    JNIEnv,
7    objects::{GlobalRef, JObject},
8};
9use keyring_core::{Error, Result};
10
11#[cfg(feature = "android-log")]
12pub mod android_log;
13pub mod cipher;
14pub mod credential;
15pub mod keystore;
16pub mod methods;
17pub mod shared_preferences;
18#[cfg(feature = "compile_tests")]
19pub mod tests;
20
21pub type Store = credential::AndroidStore;
22pub type Cred = credential::AndroidCredential;
23
24// package io.crates.keyring
25// import android.content.Context
26// class Keyring {
27//     companion object {
28//         init {
29//             System.loadLibrary("android_native_keyring_store")
30//         }
31//         external fun initializeNdkContext(context: Context);
32//     }
33// }
34#[allow(non_snake_case)]
35#[unsafe(no_mangle)]
36pub extern "system" fn Java_io_crates_keyring_Keyring_00024Companion_initializeNdkContext(
37    env: JNIEnv,
38    _class: JObject,
39    context: JObject,
40) {
41    static REF: OnceLock<Option<GlobalRef>> = OnceLock::new();
42    REF.get_or_init(|| match env.new_global_ref(&context) {
43        Ok(ref_) => {
44            let vm = env.get_java_vm().unwrap();
45            let vm = vm.get_java_vm_pointer() as *mut c_void;
46            unsafe {
47                ndk_context::initialize_android_context(vm, ref_.as_obj().as_raw() as _);
48            }
49            Some(ref_)
50        }
51        Err(e) => {
52            tracing::error!(%e, "error creating global reference for context");
53            tracing::debug!(?e);
54            None
55        }
56    });
57}
58
59/// Standard Store creation signature.
60impl Store {
61    pub fn new() -> Result<Arc<Self>> {
62        match credential::AndroidStore::from_ndk_context() {
63            Ok(store) => Ok(store),
64            Err(e) => Err(e.into()),
65        }
66    }
67
68    pub fn new_with_configuration(configuration: &HashMap<&str, &str>) -> Result<Arc<Self>> {
69        if !configuration.is_empty() {
70            return Err(Error::NotSupportedByStore(
71                "The Android Keyring Store does not support configuration options".to_string(),
72            ));
73        }
74        Self::new()
75    }
76}