Loading android/app/jni/com_android_bluetooth_hearing_aid.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,22 @@ static jboolean disconnectHearingAidNative(JNIEnv* env, jobject object, return JNI_TRUE; } static jboolean addToWhiteListNative(JNIEnv* env, jobject object, jbyteArray address) { std::shared_lock<std::shared_timed_mutex> lock(interface_mutex); if (!sHearingAidInterface) return JNI_FALSE; jbyte* addr = env->GetByteArrayElements(address, nullptr); if (!addr) { jniThrowIOException(env, EINVAL); return JNI_FALSE; } RawAddress* tmpraw = (RawAddress*)addr; sHearingAidInterface->AddToWhiteList(*tmpraw); env->ReleaseByteArrayElements(address, addr, 0); return JNI_TRUE; } static void setVolumeNative(JNIEnv* env, jclass clazz, jint volume) { if (!sHearingAidInterface) { LOG(ERROR) << __func__ Loading @@ -209,6 +225,7 @@ static JNINativeMethod sMethods[] = { {"cleanupNative", "()V", (void*)cleanupNative}, {"connectHearingAidNative", "([B)Z", (void*)connectHearingAidNative}, {"disconnectHearingAidNative", "([B)Z", (void*)disconnectHearingAidNative}, {"addToWhiteListNative", "([B)Z", (void*)addToWhiteListNative}, {"setVolumeNative", "(I)V", (void*)setVolumeNative}, }; Loading android/app/src/com/android/bluetooth/hearingaid/HearingAidNativeInterface.java +12 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,17 @@ public class HearingAidNativeInterface { return disconnectHearingAidNative(getByteAddress(device)); } /** * Add a hearing aid device to white list. * * @param device the remote device * @return true on success, otherwise false. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean addToWhiteList(BluetoothDevice device) { return addToWhiteListNative(getByteAddress(device)); } /** * Sets the HearingAid volume * @param volume Loading Loading @@ -168,5 +179,6 @@ public class HearingAidNativeInterface { private native void cleanupNative(); private native boolean connectHearingAidNative(byte[] address); private native boolean disconnectHearingAidNative(byte[] address); private native boolean addToWhiteListNative(byte[] address); private native void setVolumeNative(int volume); } android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +15 −0 Original line number Diff line number Diff line Loading @@ -326,6 +326,21 @@ public class HearingAidService extends ProfileService { } } /** * Check any peer device is connected. * The check considers any peer device is connected. * * @param device the peer device to connect to * @return true if there are any peer device connected. */ public boolean isConnectedPeerDevices(BluetoothDevice device) { long hiSyncId = getHiSyncId(device); if (getConnectedPeerDevices(hiSyncId).isEmpty()) { return false; } return true; } /** * Check whether can connect to a peer device. * The check considers a number of factors during the evaluation. Loading android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java +4 −0 Original line number Diff line number Diff line Loading @@ -261,6 +261,10 @@ final class HearingAidStateMachine extends StateMachine { case CONNECT_TIMEOUT: Log.w(TAG, "Connecting connection timeout: " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); if (mService.isConnectedPeerDevices(mDevice)) { Log.w(TAG, "One side connection timeout: " + mDevice + ". Try whitelist"); mNativeInterface.addToWhiteList(mDevice); } HearingAidStackEvent disconnectEvent = new HearingAidStackEvent( HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); Loading android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java +4 −0 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ public class HearingAidStateMachineTest { BluetoothDevice.class)); doReturn(true).when(mHearingAidNativeInterface).disconnectHearingAid(any( BluetoothDevice.class)); when(mHearingAidService.isConnectedPeerDevices(mTestDevice)).thenReturn(true); // Send a connect request mHearingAidStateMachine.sendMessage(HearingAidStateMachine.CONNECT, mTestDevice); Loading @@ -212,6 +213,7 @@ public class HearingAidStateMachineTest { // Check that we are in Disconnected state Assert.assertThat(mHearingAidStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HearingAidStateMachine.Disconnected.class)); verify(mHearingAidNativeInterface).addToWhiteList(eq(mTestDevice)); } /** Loading @@ -224,6 +226,7 @@ public class HearingAidStateMachineTest { BluetoothDevice.class)); doReturn(true).when(mHearingAidNativeInterface).disconnectHearingAid(any( BluetoothDevice.class)); when(mHearingAidService.isConnectedPeerDevices(mTestDevice)).thenReturn(true); // Inject an event for when incoming connection is requested HearingAidStackEvent connStCh = Loading Loading @@ -254,5 +257,6 @@ public class HearingAidStateMachineTest { // Check that we are in Disconnected state Assert.assertThat(mHearingAidStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HearingAidStateMachine.Disconnected.class)); verify(mHearingAidNativeInterface).addToWhiteList(eq(mTestDevice)); } } Loading
android/app/jni/com_android_bluetooth_hearing_aid.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,22 @@ static jboolean disconnectHearingAidNative(JNIEnv* env, jobject object, return JNI_TRUE; } static jboolean addToWhiteListNative(JNIEnv* env, jobject object, jbyteArray address) { std::shared_lock<std::shared_timed_mutex> lock(interface_mutex); if (!sHearingAidInterface) return JNI_FALSE; jbyte* addr = env->GetByteArrayElements(address, nullptr); if (!addr) { jniThrowIOException(env, EINVAL); return JNI_FALSE; } RawAddress* tmpraw = (RawAddress*)addr; sHearingAidInterface->AddToWhiteList(*tmpraw); env->ReleaseByteArrayElements(address, addr, 0); return JNI_TRUE; } static void setVolumeNative(JNIEnv* env, jclass clazz, jint volume) { if (!sHearingAidInterface) { LOG(ERROR) << __func__ Loading @@ -209,6 +225,7 @@ static JNINativeMethod sMethods[] = { {"cleanupNative", "()V", (void*)cleanupNative}, {"connectHearingAidNative", "([B)Z", (void*)connectHearingAidNative}, {"disconnectHearingAidNative", "([B)Z", (void*)disconnectHearingAidNative}, {"addToWhiteListNative", "([B)Z", (void*)addToWhiteListNative}, {"setVolumeNative", "(I)V", (void*)setVolumeNative}, }; Loading
android/app/src/com/android/bluetooth/hearingaid/HearingAidNativeInterface.java +12 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,17 @@ public class HearingAidNativeInterface { return disconnectHearingAidNative(getByteAddress(device)); } /** * Add a hearing aid device to white list. * * @param device the remote device * @return true on success, otherwise false. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean addToWhiteList(BluetoothDevice device) { return addToWhiteListNative(getByteAddress(device)); } /** * Sets the HearingAid volume * @param volume Loading Loading @@ -168,5 +179,6 @@ public class HearingAidNativeInterface { private native void cleanupNative(); private native boolean connectHearingAidNative(byte[] address); private native boolean disconnectHearingAidNative(byte[] address); private native boolean addToWhiteListNative(byte[] address); private native void setVolumeNative(int volume); }
android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +15 −0 Original line number Diff line number Diff line Loading @@ -326,6 +326,21 @@ public class HearingAidService extends ProfileService { } } /** * Check any peer device is connected. * The check considers any peer device is connected. * * @param device the peer device to connect to * @return true if there are any peer device connected. */ public boolean isConnectedPeerDevices(BluetoothDevice device) { long hiSyncId = getHiSyncId(device); if (getConnectedPeerDevices(hiSyncId).isEmpty()) { return false; } return true; } /** * Check whether can connect to a peer device. * The check considers a number of factors during the evaluation. Loading
android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java +4 −0 Original line number Diff line number Diff line Loading @@ -261,6 +261,10 @@ final class HearingAidStateMachine extends StateMachine { case CONNECT_TIMEOUT: Log.w(TAG, "Connecting connection timeout: " + mDevice); mNativeInterface.disconnectHearingAid(mDevice); if (mService.isConnectedPeerDevices(mDevice)) { Log.w(TAG, "One side connection timeout: " + mDevice + ". Try whitelist"); mNativeInterface.addToWhiteList(mDevice); } HearingAidStackEvent disconnectEvent = new HearingAidStackEvent( HearingAidStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); Loading
android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java +4 −0 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ public class HearingAidStateMachineTest { BluetoothDevice.class)); doReturn(true).when(mHearingAidNativeInterface).disconnectHearingAid(any( BluetoothDevice.class)); when(mHearingAidService.isConnectedPeerDevices(mTestDevice)).thenReturn(true); // Send a connect request mHearingAidStateMachine.sendMessage(HearingAidStateMachine.CONNECT, mTestDevice); Loading @@ -212,6 +213,7 @@ public class HearingAidStateMachineTest { // Check that we are in Disconnected state Assert.assertThat(mHearingAidStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HearingAidStateMachine.Disconnected.class)); verify(mHearingAidNativeInterface).addToWhiteList(eq(mTestDevice)); } /** Loading @@ -224,6 +226,7 @@ public class HearingAidStateMachineTest { BluetoothDevice.class)); doReturn(true).when(mHearingAidNativeInterface).disconnectHearingAid(any( BluetoothDevice.class)); when(mHearingAidService.isConnectedPeerDevices(mTestDevice)).thenReturn(true); // Inject an event for when incoming connection is requested HearingAidStackEvent connStCh = Loading Loading @@ -254,5 +257,6 @@ public class HearingAidStateMachineTest { // Check that we are in Disconnected state Assert.assertThat(mHearingAidStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HearingAidStateMachine.Disconnected.class)); verify(mHearingAidNativeInterface).addToWhiteList(eq(mTestDevice)); } }