Loading core/java/android/bluetooth/BluetoothUuid.java +19 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.os.ParcelUuid; import java.util.Arrays; import java.util.HashSet; import java.util.UUID; /** * Static helper methods and constants to decode the ParcelUuid of remote devices. Loading @@ -41,8 +42,12 @@ public final class BluetoothUuid { ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid HSP = ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid HSP_AG = ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid Handsfree = ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid Handsfree_AG = ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid AvrcpController = ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid AvrcpTarget = Loading @@ -57,6 +62,8 @@ public final class BluetoothUuid { ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid BNEP = ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid PBAP_PSE = ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, Loading Loading @@ -173,4 +180,16 @@ public final class BluetoothUuid { return true; } /** * Extract the Service Identifier or the actual uuid from the Parcel Uuid. * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid, * this function will return 110B * @param parcelUuid * @return the service identifier. */ public static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) { UUID uuid = parcelUuid.getUuid(); long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32; return (int)value; } } core/java/android/server/BluetoothEventLoop.java +1 −1 Original line number Diff line number Diff line Loading @@ -293,7 +293,7 @@ class BluetoothEventLoop { intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); } mContext.sendBroadcast(intent, BLUETOOTH_PERM); } else if (name.equals("Devices")) { } else if (name.equals("Devices") || name.equals("UUIDs")) { String value = null; int len = Integer.valueOf(propValues[1]); if (len > 0) { Loading core/java/android/server/BluetoothService.java +39 −53 Original line number Diff line number Diff line Loading @@ -97,6 +97,8 @@ public class BluetoothService extends IBluetooth.Stub { private boolean mRestart = false; // need to call enable() after disable() private boolean mIsDiscovering; private boolean mTetheringOn; private int[] mAdapterSdpUuids; private int[] mAdapterSdpHandles; private BluetoothAdapter mAdapter; // constant after init() private final BondState mBondState = new BondState(); // local cache of bondings Loading @@ -112,11 +114,10 @@ public class BluetoothService extends IBluetooth.Stub { private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; private static final int MESSAGE_FINISH_DISABLE = 2; private static final int MESSAGE_UUID_INTENT = 3; private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 5; private static final int MESSAGE_FINISH_DISABLE = 1; private static final int MESSAGE_UUID_INTENT = 2; private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 3; private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 4; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with Loading Loading @@ -378,8 +379,10 @@ public class BluetoothService extends IBluetooth.Stub { if (mEnableThread != null && mEnableThread.isAlive()) { return false; } setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF); mHandler.removeMessages(MESSAGE_REGISTER_SDP_RECORDS); if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles); setBluetoothTetheringNative(false, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); // Allow 3 seconds for profiles to gracefully disconnect Loading Loading @@ -516,43 +519,6 @@ public class BluetoothService extends IBluetooth.Stub { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_REGISTER_SDP_RECORDS: if (!isEnabledInternal()) { return; } // SystemService.start() forks sdptool to register service // records. It can fail to register some records if it is // forked multiple times in a row, probably because there is // some race in sdptool or bluez when operated in parallel. // As a workaround, delay 500ms between each fork of sdptool. // TODO: Don't fork sdptool in order to register service // records, use a DBUS call instead. switch (msg.arg1) { case 1: Log.d(TAG, "Registering hfag record"); SystemService.start("hfag"); mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 2, -1), 500); break; case 2: Log.d(TAG, "Registering hsag record"); SystemService.start("hsag"); mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 3, -1), 500); break; case 3: Log.d(TAG, "Registering pbap record"); SystemService.start("pbap"); mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 500); break; case 4: Log.d(TAG, "Registering opush record"); SystemService.start("opush"); break; } break; case MESSAGE_FINISH_DISABLE: finishDisable(msg.arg1 != 0); break; Loading Loading @@ -625,23 +591,40 @@ public class BluetoothService extends IBluetooth.Stub { if (mSaveSetting) { persistBluetoothOnSetting(true); } mIsDiscovering = false; mBondState.readAutoPairingData(); mBondState.loadBondState(); initProfileState(); //Register SDP records. if (mContext.getResources(). getBoolean(com.android.internal.R.bool.config_voice_capable)) { mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 1, -1), 3000); int[] uuids = { BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.Handsfree_AG), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.HSP_AG), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.PBAP_PSE), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.ObexObjectPush), }; mAdapterSdpUuids = uuids; } else { // Register only OPP. mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 3000); int[] uuids = { BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.HSP_AG), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.PBAP_PSE), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.ObexObjectPush), }; mAdapterSdpUuids = uuids; } mAdapterSdpHandles = addReservedServiceRecordsNative(mAdapterSdpUuids); setBluetoothTetheringNative(true, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); mIsDiscovering = false; mBondState.readAutoPairingData(); mBondState.loadBondState(); initProfileState(); // Log bluetooth on to battery stats. long ident = Binder.clearCallingIdentity(); Loading Loading @@ -2908,4 +2891,7 @@ public class BluetoothService extends IBluetooth.Stub { private native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge); private native boolean connectPanDeviceNative(String path, String srcRole, String dstRole); private native boolean disconnectPanDeviceNative(String path); private native int[] addReservedServiceRecordsNative(int[] uuuids); private native boolean removeReservedServiceRecordsNative(int[] handles); } core/jni/android_server_BluetoothService.cpp +75 −0 Original line number Diff line number Diff line Loading @@ -928,6 +928,79 @@ static jboolean discoverServicesNative(JNIEnv *env, jobject object, return JNI_FALSE; } static jintArray extract_handles(JNIEnv *env, DBusMessage *reply) { #ifdef HAVE_BLUETOOTH jint *handles; jintArray handleArray = NULL; int len; DBusError err; dbus_error_init(&err); if (dbus_message_get_args(reply, &err, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len, DBUS_TYPE_INVALID)) { handleArray = env->NewIntArray(len); if (handleArray) { env->SetIntArrayRegion(handleArray, 0, len, handles); } else { LOGE("Null array in extract_handles"); } } else { LOG_AND_FREE_DBUS_ERROR(&err); } return handleArray; #endif return NULL; } static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object, jintArray uuids) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH DBusMessage *reply = NULL; native_data_t *nat = get_native_data(env, object); jint* svc_classes = env->GetIntArrayElements(uuids, NULL); if (!svc_classes) return NULL; int len = env->GetArrayLength(uuids); reply = dbus_func_args(env, nat->conn, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "AddReservedServiceRecords", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &svc_classes, len, DBUS_TYPE_INVALID); env->ReleaseIntArrayElements(uuids, svc_classes, 0); return reply ? extract_handles(env, reply) : NULL; #endif return NULL; } static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object, jintArray handles) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jint *values = env->GetIntArrayElements(handles, NULL); DBusMessage *msg = NULL; DBusMessage *reply = NULL; if (values == NULL) return JNI_FALSE; jsize len = env->GetArrayLength(handles); reply = dbus_func_args(env, nat->conn, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "RemoveReservedServiceRecords", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &values, len, DBUS_TYPE_INVALID); env->ReleaseIntArrayElements(handles, values, NULL); return reply ? JNI_TRUE : JNI_FALSE; #endif return JNI_FALSE; } static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object, jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) { LOGV(__FUNCTION__); Loading Loading @@ -1193,6 +1266,8 @@ static JNINativeMethod sMethods[] = { {"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative}, {"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative}, {"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative}, {"addReservedServiceRecordsNative", "([I)[I", (void *) addReservedServiceRecordsNative}, {"removeReservedServiceRecordsNative", "([I)Z", (void *) removeReservedServiceRecordsNative}, {"setLinkTimeoutNative", "(Ljava/lang/String;I)Z", (void *)setLinkTimeoutNative}, // HID functions {"connectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)connectInputDeviceNative}, Loading Loading
core/java/android/bluetooth/BluetoothUuid.java +19 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.os.ParcelUuid; import java.util.Arrays; import java.util.HashSet; import java.util.UUID; /** * Static helper methods and constants to decode the ParcelUuid of remote devices. Loading @@ -41,8 +42,12 @@ public final class BluetoothUuid { ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid HSP = ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid HSP_AG = ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid Handsfree = ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid Handsfree_AG = ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid AvrcpController = ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid AvrcpTarget = Loading @@ -57,6 +62,8 @@ public final class BluetoothUuid { ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid BNEP = ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid PBAP_PSE = ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, Loading Loading @@ -173,4 +180,16 @@ public final class BluetoothUuid { return true; } /** * Extract the Service Identifier or the actual uuid from the Parcel Uuid. * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid, * this function will return 110B * @param parcelUuid * @return the service identifier. */ public static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) { UUID uuid = parcelUuid.getUuid(); long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32; return (int)value; } }
core/java/android/server/BluetoothEventLoop.java +1 −1 Original line number Diff line number Diff line Loading @@ -293,7 +293,7 @@ class BluetoothEventLoop { intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); } mContext.sendBroadcast(intent, BLUETOOTH_PERM); } else if (name.equals("Devices")) { } else if (name.equals("Devices") || name.equals("UUIDs")) { String value = null; int len = Integer.valueOf(propValues[1]); if (len > 0) { Loading
core/java/android/server/BluetoothService.java +39 −53 Original line number Diff line number Diff line Loading @@ -97,6 +97,8 @@ public class BluetoothService extends IBluetooth.Stub { private boolean mRestart = false; // need to call enable() after disable() private boolean mIsDiscovering; private boolean mTetheringOn; private int[] mAdapterSdpUuids; private int[] mAdapterSdpHandles; private BluetoothAdapter mAdapter; // constant after init() private final BondState mBondState = new BondState(); // local cache of bondings Loading @@ -112,11 +114,10 @@ public class BluetoothService extends IBluetooth.Stub { private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address"; private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings"; private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; private static final int MESSAGE_FINISH_DISABLE = 2; private static final int MESSAGE_UUID_INTENT = 3; private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 5; private static final int MESSAGE_FINISH_DISABLE = 1; private static final int MESSAGE_UUID_INTENT = 2; private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 3; private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 4; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with Loading Loading @@ -378,8 +379,10 @@ public class BluetoothService extends IBluetooth.Stub { if (mEnableThread != null && mEnableThread.isAlive()) { return false; } setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF); mHandler.removeMessages(MESSAGE_REGISTER_SDP_RECORDS); if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles); setBluetoothTetheringNative(false, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); // Allow 3 seconds for profiles to gracefully disconnect Loading Loading @@ -516,43 +519,6 @@ public class BluetoothService extends IBluetooth.Stub { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_REGISTER_SDP_RECORDS: if (!isEnabledInternal()) { return; } // SystemService.start() forks sdptool to register service // records. It can fail to register some records if it is // forked multiple times in a row, probably because there is // some race in sdptool or bluez when operated in parallel. // As a workaround, delay 500ms between each fork of sdptool. // TODO: Don't fork sdptool in order to register service // records, use a DBUS call instead. switch (msg.arg1) { case 1: Log.d(TAG, "Registering hfag record"); SystemService.start("hfag"); mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 2, -1), 500); break; case 2: Log.d(TAG, "Registering hsag record"); SystemService.start("hsag"); mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 3, -1), 500); break; case 3: Log.d(TAG, "Registering pbap record"); SystemService.start("pbap"); mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 500); break; case 4: Log.d(TAG, "Registering opush record"); SystemService.start("opush"); break; } break; case MESSAGE_FINISH_DISABLE: finishDisable(msg.arg1 != 0); break; Loading Loading @@ -625,23 +591,40 @@ public class BluetoothService extends IBluetooth.Stub { if (mSaveSetting) { persistBluetoothOnSetting(true); } mIsDiscovering = false; mBondState.readAutoPairingData(); mBondState.loadBondState(); initProfileState(); //Register SDP records. if (mContext.getResources(). getBoolean(com.android.internal.R.bool.config_voice_capable)) { mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 1, -1), 3000); int[] uuids = { BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.Handsfree_AG), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.HSP_AG), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.PBAP_PSE), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.ObexObjectPush), }; mAdapterSdpUuids = uuids; } else { // Register only OPP. mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 3000); int[] uuids = { BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.HSP_AG), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.PBAP_PSE), BluetoothUuid.getServiceIdentifierFromParcelUuid( BluetoothUuid.ObexObjectPush), }; mAdapterSdpUuids = uuids; } mAdapterSdpHandles = addReservedServiceRecordsNative(mAdapterSdpUuids); setBluetoothTetheringNative(true, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); mIsDiscovering = false; mBondState.readAutoPairingData(); mBondState.loadBondState(); initProfileState(); // Log bluetooth on to battery stats. long ident = Binder.clearCallingIdentity(); Loading Loading @@ -2908,4 +2891,7 @@ public class BluetoothService extends IBluetooth.Stub { private native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge); private native boolean connectPanDeviceNative(String path, String srcRole, String dstRole); private native boolean disconnectPanDeviceNative(String path); private native int[] addReservedServiceRecordsNative(int[] uuuids); private native boolean removeReservedServiceRecordsNative(int[] handles); }
core/jni/android_server_BluetoothService.cpp +75 −0 Original line number Diff line number Diff line Loading @@ -928,6 +928,79 @@ static jboolean discoverServicesNative(JNIEnv *env, jobject object, return JNI_FALSE; } static jintArray extract_handles(JNIEnv *env, DBusMessage *reply) { #ifdef HAVE_BLUETOOTH jint *handles; jintArray handleArray = NULL; int len; DBusError err; dbus_error_init(&err); if (dbus_message_get_args(reply, &err, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len, DBUS_TYPE_INVALID)) { handleArray = env->NewIntArray(len); if (handleArray) { env->SetIntArrayRegion(handleArray, 0, len, handles); } else { LOGE("Null array in extract_handles"); } } else { LOG_AND_FREE_DBUS_ERROR(&err); } return handleArray; #endif return NULL; } static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object, jintArray uuids) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH DBusMessage *reply = NULL; native_data_t *nat = get_native_data(env, object); jint* svc_classes = env->GetIntArrayElements(uuids, NULL); if (!svc_classes) return NULL; int len = env->GetArrayLength(uuids); reply = dbus_func_args(env, nat->conn, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "AddReservedServiceRecords", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &svc_classes, len, DBUS_TYPE_INVALID); env->ReleaseIntArrayElements(uuids, svc_classes, 0); return reply ? extract_handles(env, reply) : NULL; #endif return NULL; } static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object, jintArray handles) { LOGV(__FUNCTION__); #ifdef HAVE_BLUETOOTH native_data_t *nat = get_native_data(env, object); jint *values = env->GetIntArrayElements(handles, NULL); DBusMessage *msg = NULL; DBusMessage *reply = NULL; if (values == NULL) return JNI_FALSE; jsize len = env->GetArrayLength(handles); reply = dbus_func_args(env, nat->conn, get_adapter_path(env, object), DBUS_ADAPTER_IFACE, "RemoveReservedServiceRecords", DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &values, len, DBUS_TYPE_INVALID); env->ReleaseIntArrayElements(handles, values, NULL); return reply ? JNI_TRUE : JNI_FALSE; #endif return JNI_FALSE; } static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object, jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) { LOGV(__FUNCTION__); Loading Loading @@ -1193,6 +1266,8 @@ static JNINativeMethod sMethods[] = { {"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative}, {"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative}, {"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative}, {"addReservedServiceRecordsNative", "([I)[I", (void *) addReservedServiceRecordsNative}, {"removeReservedServiceRecordsNative", "([I)Z", (void *) removeReservedServiceRecordsNative}, {"setLinkTimeoutNative", "(Ljava/lang/String;I)Z", (void *)setLinkTimeoutNative}, // HID functions {"connectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)connectInputDeviceNative}, Loading