Loading android/app/jni/com_android_bluetooth.h +2 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,8 @@ int register_com_android_bluetooth_gatt (JNIEnv* env); int register_com_android_bluetooth_sdp (JNIEnv* env); int register_com_android_bluetooth_hearing_aid(JNIEnv* env); int register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv* env); } #endif /* COM_ANDROID_BLUETOOTH_H */ android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -1377,6 +1377,13 @@ jint JNI_OnLoad(JavaVM* jvm, void* reserved) { return JNI_ERR; } status = android::register_com_android_bluetooth_btservice_BluetoothKeystore(e); if (status < 0) { ALOGE("jni BluetoothKeyStore registration failure: %d", status); return JNI_ERR; } status = android::register_com_android_bluetooth_hfp(e); if (status < 0) { ALOGE("jni hfp registration failure, status: %d", status); Loading android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp 0 → 100644 +171 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "BluetoothKeystoreServiceJni" #include "base/logging.h" #include "com_android_bluetooth.h" #include "hardware/bt_keystore.h" #include <string.h> #include <shared_mutex> using bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks; using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface; namespace android { static jmethodID method_setEncryptKeyOrRemoveKeyCallback; static jmethodID method_getKeyCallback; static BluetoothKeystoreInterface* sBluetoothKeystoreInterface = nullptr; static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; class BluetoothKeystoreCallbacksImpl : public bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks { public: ~BluetoothKeystoreCallbacksImpl() = default; void set_encrypt_key_or_remove_key( const std::string prefixString, const std::string decryptedString) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str()); jstring j_decryptedString = sCallbackEnv->NewStringUTF(decryptedString.c_str()); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_setEncryptKeyOrRemoveKeyCallback, j_prefixString, j_decryptedString); } std::string get_key(const std::string prefixString) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return ""; jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str()); jstring j_decrypt_str = (jstring)sCallbackEnv->CallObjectMethod( mCallbacksObj, method_getKeyCallback, j_prefixString); if (j_decrypt_str == nullptr) { ALOGE("%s: Got a null decrypt_str", __func__); return ""; } const char* value = sCallbackEnv->GetStringUTFChars(j_decrypt_str, nullptr); std::string ret(value); sCallbackEnv->ReleaseStringUTFChars(j_decrypt_str, value); return ret; } }; static BluetoothKeystoreCallbacksImpl sBluetoothKeystoreCallbacks; static void classInitNative(JNIEnv* env, jclass clazz) { method_setEncryptKeyOrRemoveKeyCallback = env->GetMethodID(clazz, "setEncryptKeyOrRemoveKeyCallback", "(Ljava/lang/String;Ljava/lang/String;)V"); method_getKeyCallback = env->GetMethodID( clazz, "getKeyCallback", "(Ljava/lang/String;)Ljava/lang/String;"); LOG(INFO) << __func__ << ": succeeds"; } static void initNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sBluetoothKeystoreInterface != nullptr) { LOG(INFO) << "Cleaning up BluetoothKeystore Interface before initializing..."; sBluetoothKeystoreInterface = nullptr; } if (mCallbacksObj != nullptr) { LOG(INFO) << "Cleaning up BluetoothKeystore callback object"; env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { LOG(ERROR) << "Failed to allocate Global Ref for BluetoothKeystore Callbacks"; return; } sBluetoothKeystoreInterface = (BluetoothKeystoreInterface*)btInf->get_profile_interface(BT_KEYSTORE_ID); if (sBluetoothKeystoreInterface == nullptr) { LOG(ERROR) << "Failed to get BluetoothKeystore Interface"; return; } sBluetoothKeystoreInterface->init(&sBluetoothKeystoreCallbacks); } static void cleanupNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sBluetoothKeystoreInterface != nullptr) { sBluetoothKeystoreInterface = nullptr; } if (mCallbacksObj != nullptr) { env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } } static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, {"initNative", "()V", (void*)initNative}, {"cleanupNative", "()V", (void*)cleanupNative}, }; int register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv* env) { return jniRegisterNativeMethods( env, "com/android/bluetooth/btservice/bluetoothkeystore/" "BluetoothKeystoreNativeInterface", sMethods, NELEM(sMethods)); } } // namespace android android/app/src/com/android/bluetooth/btservice/AdapterService.java +2 −0 Original line number Diff line number Diff line Loading @@ -453,6 +453,8 @@ public class AdapterService extends Service { mBatteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); mBluetoothKeystoreService.initJni(); mSdpManager = SdpManager.init(this); registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); Loading android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreNativeInterface.java 0 → 100644 +104 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.btservice.bluetoothkeystore; import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.io.IOException; import java.security.NoSuchAlgorithmException; final class BluetoothKeystoreNativeInterface { private static final String TAG = "BluetoothKeystoreNativeInterface"; @GuardedBy("INSTANCE_LOCK") private static BluetoothKeystoreNativeInterface sInstance; private static final Object INSTANCE_LOCK = new Object(); static { classInitNative(); } private BluetoothKeystoreNativeInterface() { } /** * Get singleton instance. */ public static BluetoothKeystoreNativeInterface getInstance() { synchronized (INSTANCE_LOCK) { if (sInstance == null) { sInstance = new BluetoothKeystoreNativeInterface(); } return sInstance; } } /** * Initializes the native interface. * * priorities to configure. */ public void init() { initNative(); } /** * Cleanup the native interface. */ public void cleanup() { cleanupNative(); } // Callbacks from the native stack back into the Java framework. // All callbacks are routed via the Service which will disambiguate which // state machine the message should be routed to. private void setEncryptKeyOrRemoveKeyCallback(String prefixString, String decryptedString) { BluetoothKeystoreService service = BluetoothKeystoreService.getBluetoothKeystoreService(); if (service != null) { try { service.setEncryptKeyOrRemoveKey(prefixString, decryptedString); } catch (InterruptedException e) { Log.e(TAG, "Interrupted while operating."); } catch (IOException e) { Log.e(TAG, "IO error while file operating."); } catch (NoSuchAlgorithmException e) { Log.e(TAG, "encrypt could not find the algorithm: SHA256"); } } else { Log.e(TAG, "Event ignored, service not available: " + prefixString); } } private String getKeyCallback(String prefixString) { BluetoothKeystoreService service = BluetoothKeystoreService.getBluetoothKeystoreService(); if (service != null) { return service.getKey(prefixString); } else { Log.e(TAG, "Event ignored, service not available: " + prefixString); return null; } } // Native methods that call into the JNI interface private static native void classInitNative(); private native void initNative(); private native void cleanupNative(); } Loading
android/app/jni/com_android_bluetooth.h +2 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,8 @@ int register_com_android_bluetooth_gatt (JNIEnv* env); int register_com_android_bluetooth_sdp (JNIEnv* env); int register_com_android_bluetooth_hearing_aid(JNIEnv* env); int register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv* env); } #endif /* COM_ANDROID_BLUETOOTH_H */
android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -1377,6 +1377,13 @@ jint JNI_OnLoad(JavaVM* jvm, void* reserved) { return JNI_ERR; } status = android::register_com_android_bluetooth_btservice_BluetoothKeystore(e); if (status < 0) { ALOGE("jni BluetoothKeyStore registration failure: %d", status); return JNI_ERR; } status = android::register_com_android_bluetooth_hfp(e); if (status < 0) { ALOGE("jni hfp registration failure, status: %d", status); Loading
android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp 0 → 100644 +171 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "BluetoothKeystoreServiceJni" #include "base/logging.h" #include "com_android_bluetooth.h" #include "hardware/bt_keystore.h" #include <string.h> #include <shared_mutex> using bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks; using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface; namespace android { static jmethodID method_setEncryptKeyOrRemoveKeyCallback; static jmethodID method_getKeyCallback; static BluetoothKeystoreInterface* sBluetoothKeystoreInterface = nullptr; static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; class BluetoothKeystoreCallbacksImpl : public bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks { public: ~BluetoothKeystoreCallbacksImpl() = default; void set_encrypt_key_or_remove_key( const std::string prefixString, const std::string decryptedString) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str()); jstring j_decryptedString = sCallbackEnv->NewStringUTF(decryptedString.c_str()); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_setEncryptKeyOrRemoveKeyCallback, j_prefixString, j_decryptedString); } std::string get_key(const std::string prefixString) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return ""; jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str()); jstring j_decrypt_str = (jstring)sCallbackEnv->CallObjectMethod( mCallbacksObj, method_getKeyCallback, j_prefixString); if (j_decrypt_str == nullptr) { ALOGE("%s: Got a null decrypt_str", __func__); return ""; } const char* value = sCallbackEnv->GetStringUTFChars(j_decrypt_str, nullptr); std::string ret(value); sCallbackEnv->ReleaseStringUTFChars(j_decrypt_str, value); return ret; } }; static BluetoothKeystoreCallbacksImpl sBluetoothKeystoreCallbacks; static void classInitNative(JNIEnv* env, jclass clazz) { method_setEncryptKeyOrRemoveKeyCallback = env->GetMethodID(clazz, "setEncryptKeyOrRemoveKeyCallback", "(Ljava/lang/String;Ljava/lang/String;)V"); method_getKeyCallback = env->GetMethodID( clazz, "getKeyCallback", "(Ljava/lang/String;)Ljava/lang/String;"); LOG(INFO) << __func__ << ": succeeds"; } static void initNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sBluetoothKeystoreInterface != nullptr) { LOG(INFO) << "Cleaning up BluetoothKeystore Interface before initializing..."; sBluetoothKeystoreInterface = nullptr; } if (mCallbacksObj != nullptr) { LOG(INFO) << "Cleaning up BluetoothKeystore callback object"; env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { LOG(ERROR) << "Failed to allocate Global Ref for BluetoothKeystore Callbacks"; return; } sBluetoothKeystoreInterface = (BluetoothKeystoreInterface*)btInf->get_profile_interface(BT_KEYSTORE_ID); if (sBluetoothKeystoreInterface == nullptr) { LOG(ERROR) << "Failed to get BluetoothKeystore Interface"; return; } sBluetoothKeystoreInterface->init(&sBluetoothKeystoreCallbacks); } static void cleanupNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sBluetoothKeystoreInterface != nullptr) { sBluetoothKeystoreInterface = nullptr; } if (mCallbacksObj != nullptr) { env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } } static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, {"initNative", "()V", (void*)initNative}, {"cleanupNative", "()V", (void*)cleanupNative}, }; int register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv* env) { return jniRegisterNativeMethods( env, "com/android/bluetooth/btservice/bluetoothkeystore/" "BluetoothKeystoreNativeInterface", sMethods, NELEM(sMethods)); } } // namespace android
android/app/src/com/android/bluetooth/btservice/AdapterService.java +2 −0 Original line number Diff line number Diff line Loading @@ -453,6 +453,8 @@ public class AdapterService extends Service { mBatteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); mBluetoothKeystoreService.initJni(); mSdpManager = SdpManager.init(this); registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); Loading
android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreNativeInterface.java 0 → 100644 +104 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.btservice.bluetoothkeystore; import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.io.IOException; import java.security.NoSuchAlgorithmException; final class BluetoothKeystoreNativeInterface { private static final String TAG = "BluetoothKeystoreNativeInterface"; @GuardedBy("INSTANCE_LOCK") private static BluetoothKeystoreNativeInterface sInstance; private static final Object INSTANCE_LOCK = new Object(); static { classInitNative(); } private BluetoothKeystoreNativeInterface() { } /** * Get singleton instance. */ public static BluetoothKeystoreNativeInterface getInstance() { synchronized (INSTANCE_LOCK) { if (sInstance == null) { sInstance = new BluetoothKeystoreNativeInterface(); } return sInstance; } } /** * Initializes the native interface. * * priorities to configure. */ public void init() { initNative(); } /** * Cleanup the native interface. */ public void cleanup() { cleanupNative(); } // Callbacks from the native stack back into the Java framework. // All callbacks are routed via the Service which will disambiguate which // state machine the message should be routed to. private void setEncryptKeyOrRemoveKeyCallback(String prefixString, String decryptedString) { BluetoothKeystoreService service = BluetoothKeystoreService.getBluetoothKeystoreService(); if (service != null) { try { service.setEncryptKeyOrRemoveKey(prefixString, decryptedString); } catch (InterruptedException e) { Log.e(TAG, "Interrupted while operating."); } catch (IOException e) { Log.e(TAG, "IO error while file operating."); } catch (NoSuchAlgorithmException e) { Log.e(TAG, "encrypt could not find the algorithm: SHA256"); } } else { Log.e(TAG, "Event ignored, service not available: " + prefixString); } } private String getKeyCallback(String prefixString) { BluetoothKeystoreService service = BluetoothKeystoreService.getBluetoothKeystoreService(); if (service != null) { return service.getKey(prefixString); } else { Log.e(TAG, "Event ignored, service not available: " + prefixString); return null; } } // Native methods that call into the JNI interface private static native void classInitNative(); private native void initNative(); private native void cleanupNative(); }