Loading core/java/android/bluetooth/BluetoothDevice.java +45 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.util.Log; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.UUID; /** * Represents a remote Bluetooth device. Loading Loading @@ -225,6 +226,20 @@ public final class BluetoothDevice implements Parcelable { /** @hide */ public static final String EXTRA_PASSKEY = "android.bluetooth.device.extra.PASSKEY"; /** * Broadcast Action: This intent is used to broadcast the {@link UUID} * wrapped as a {@link ParcelUuid} of the remote device after it has been * fetched. This intent is sent only when the UUIDs of the remote device * are requested to be fetched using Service Discovery Protocol * <p> Always contains the extra field {@link #EXTRA_DEVICE} * <p> Always contains the extra filed {@link #EXTRA_UUID} * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_UUID = "android.bleutooth.device.action.UUID"; /** * Broadcast Action: Indicates a failure to retrieve the name of a remote * device. Loading Loading @@ -292,6 +307,15 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4; /** * Used as an extra field in {@link #ACTION_UUID} intents, * Contains the {@link ParcelUuid}s of the remote device which is a parcelable * version of {@link UUID}. * @hide */ public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; private static IBluetooth sService; /* Guarenteed constant after first object constructed */ private final String mAddress; Loading Loading @@ -507,6 +531,27 @@ public final class BluetoothDevice implements Parcelable { return null; } /** * Perform a SDP query on the remote device to get the UUIDs * supported. This API is asynchronous and an Intent is sent, * with the UUIDs supported by the remote end. If there is an error * in getting the SDP records or if the process takes a long time, * an Intent is sent with the UUIDs that is currently present in the * cache. Clients should use the {@link getUuids} to get UUIDs * is SDP is not to be performed. * * @return False if the sanity check fails, True if the process * of initiating an ACL connection to the remote device * was started. * @hide */ public boolean fetchUuidsWithSdp() { try { return sService.fetchRemoteUuidsWithSdp(mAddress); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } /** @hide */ public int getServiceChannel(ParcelUuid uuid) { try { Loading core/java/android/bluetooth/IBluetooth.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ interface IBluetooth String getRemoteName(in String address); int getRemoteClass(in String address); ParcelUuid[] getRemoteUuids(in String address); boolean fetchRemoteUuidsWithSdp(in String address); int getRemoteServiceChannel(in String address,in ParcelUuid uuid); boolean setPin(in String address, in byte[] pin); Loading core/java/android/server/BluetoothEventLoop.java +23 −0 Original line number Diff line number Diff line Loading @@ -330,6 +330,9 @@ class BluetoothEventLoop { Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null"); return; } if (DBG) { log("Device property changed:" + address + "property:" + name); } BluetoothDevice device = mAdapter.getRemoteDevice(address); if (name.equals("Name")) { Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED); Loading Loading @@ -366,6 +369,7 @@ class BluetoothEventLoop { uuid = str.toString(); } mBluetoothService.setRemoteDeviceProperty(address, name, uuid); mBluetoothService.sendUuidIntent(address); } else if (name.equals("Paired")) { if (propValues[1].equals("true")) { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED); Loading Loading @@ -528,6 +532,25 @@ class BluetoothEventLoop { return; } private void onDiscoverServicesResult(String deviceObjectPath, boolean result) { String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); // We don't parse the xml here, instead just query Bluez for the properties. if (result) { String[] properties = mBluetoothService.getRemoteDeviceProperties(address); mBluetoothService.addRemoteDeviceProperties(address, properties); } mBluetoothService.sendUuidIntent(address); } private void onCreateDeviceResult(String address, boolean result) { if (DBG) { log("Result of onCreateDeviceResult:" + result); } if (!result) { mBluetoothService.sendUuidIntent(address); } } private void onRestartRequired() { if (mBluetoothService.isEnabled()) { Log.e(TAG, "*** A serious error occured (did bluetoothd crash?) - " + Loading core/java/android/server/BluetoothService.java +61 −0 Original line number Diff line number Diff line Loading @@ -76,10 +76,17 @@ public class BluetoothService extends IBluetooth.Stub { 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; // The timeout used to sent the UUIDs Intent // This timeout should be greater than the page timeout private static final int UUID_INTENT_DELAY = 6000; private final Map<String, String> mAdapterProperties; private final HashMap <String, Map<String, String>> mDeviceProperties; private final ArrayList <String> mUuidIntentTracker; static { classInitNative(); } Loading @@ -104,6 +111,7 @@ public class BluetoothService extends IBluetooth.Stub { mIsDiscovering = false; mAdapterProperties = new HashMap<String, String>(); mDeviceProperties = new HashMap<String, Map<String,String>>(); mUuidIntentTracker = new ArrayList<String>(); registerForAirplaneMode(); } Loading Loading @@ -291,6 +299,11 @@ public class BluetoothService extends IBluetooth.Stub { case MESSAGE_FINISH_DISABLE: finishDisable(msg.arg1 != 0); break; case MESSAGE_UUID_INTENT: String address = (String)msg.obj; if (address != null) sendUuidIntent(address); break; } } }; Loading Loading @@ -976,6 +989,10 @@ public class BluetoothService extends IBluetooth.Stub { if (!BluetoothAdapter.checkBluetoothAddress(address)) { return null; } return getUuidFromCache(address); } private ParcelUuid[] getUuidFromCache(String address) { String value = getRemoteDeviceProperty(address, "UUIDs"); if (value == null) return null; Loading @@ -990,6 +1007,36 @@ public class BluetoothService extends IBluetooth.Stub { return uuids; } public synchronized boolean fetchRemoteUuidsWithSdp(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (!BluetoothAdapter.checkBluetoothAddress(address)) { return false; } if (mUuidIntentTracker.contains(address)) { // An SDP query for this address is already in progress return true; } boolean ret; if (getBondState(address) == BluetoothDevice.BOND_BONDED) { String path = getObjectPathFromAddress(address); if (path == null) return false; // Use an empty string for the UUID pattern ret = discoverServicesNative(path, ""); } else { ret = createDeviceNative(address); } mUuidIntentTracker.add(address); Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); message.obj = address; mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); return ret; } /** * Gets the rfcomm channel associated with the UUID. * Loading Loading @@ -1121,6 +1168,18 @@ public class BluetoothService extends IBluetooth.Stub { Settings.System.AIRPLANE_MODE_ON, 0) == 1; } /* Broadcast the Uuid intent */ /*package*/ synchronized void sendUuidIntent(String address) { if (mUuidIntentTracker.contains(address)) { ParcelUuid[] uuid = getUuidFromCache(address); Intent intent = new Intent(BluetoothDevice.ACTION_UUID); intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); mUuidIntentTracker.remove(address); } } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n"); Loading Loading @@ -1284,4 +1343,6 @@ public class BluetoothService extends IBluetooth.Stub { private native boolean setPairingConfirmationNative(String address, boolean confirm, int nativeData); private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value); private native boolean createDeviceNative(String address); private native boolean discoverServicesNative(String objectPath, String pattern); } core/jni/android_server_BluetoothEventLoop.cpp +54 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ static jmethodID method_onDeviceRemoved; static jmethodID method_onDeviceDisconnectRequested; static jmethodID method_onCreatePairedDeviceResult; static jmethodID method_onCreateDeviceResult; static jmethodID method_onDiscoverServicesResult; static jmethodID method_onGetDeviceServiceChannelResult; static jmethodID method_onRequestPinCode; Loading Loading @@ -92,6 +94,10 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult", "(Ljava/lang/String;I)V"); method_onCreateDeviceResult = env->GetMethodID(clazz, "onCreateDeviceResult", "(Ljava/lang/String;Z)V"); method_onDiscoverServicesResult = env->GetMethodID(clazz, "onDiscoverServicesResult", "(Ljava/lang/String;Z)V"); method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize", "(Ljava/lang/String;Ljava/lang/String;)Z"); Loading Loading @@ -1097,6 +1103,54 @@ done: free(user); } void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) { LOGV(__FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *address= (const char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env; nat->vm->GetEnv((void**)&env, nat->envVer); LOGV("... Address = %s", address); bool result = JNI_TRUE; if (dbus_set_error_from_message(&err, msg)) { LOG_AND_FREE_DBUS_ERROR(&err); result = JNI_FALSE; } env->CallVoidMethod(nat->me, method_onCreateDeviceResult, env->NewStringUTF(address), result); free(user); } void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) { LOGV(__FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *path = (const char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env; nat->vm->GetEnv((void**)&env, nat->envVer); LOGV("... Device Path = %s", path); bool result = JNI_TRUE; if (dbus_set_error_from_message(&err, msg)) { LOG_AND_FREE_DBUS_ERROR(&err); result = JNI_FALSE; } env->CallVoidMethod(nat->me, method_onDiscoverServicesResult, env->NewStringUTF(path), result); free(user); } void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) { LOGV(__FUNCTION__); Loading Loading
core/java/android/bluetooth/BluetoothDevice.java +45 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.util.Log; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.UUID; /** * Represents a remote Bluetooth device. Loading Loading @@ -225,6 +226,20 @@ public final class BluetoothDevice implements Parcelable { /** @hide */ public static final String EXTRA_PASSKEY = "android.bluetooth.device.extra.PASSKEY"; /** * Broadcast Action: This intent is used to broadcast the {@link UUID} * wrapped as a {@link ParcelUuid} of the remote device after it has been * fetched. This intent is sent only when the UUIDs of the remote device * are requested to be fetched using Service Discovery Protocol * <p> Always contains the extra field {@link #EXTRA_DEVICE} * <p> Always contains the extra filed {@link #EXTRA_UUID} * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_UUID = "android.bleutooth.device.action.UUID"; /** * Broadcast Action: Indicates a failure to retrieve the name of a remote * device. Loading Loading @@ -292,6 +307,15 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4; /** * Used as an extra field in {@link #ACTION_UUID} intents, * Contains the {@link ParcelUuid}s of the remote device which is a parcelable * version of {@link UUID}. * @hide */ public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; private static IBluetooth sService; /* Guarenteed constant after first object constructed */ private final String mAddress; Loading Loading @@ -507,6 +531,27 @@ public final class BluetoothDevice implements Parcelable { return null; } /** * Perform a SDP query on the remote device to get the UUIDs * supported. This API is asynchronous and an Intent is sent, * with the UUIDs supported by the remote end. If there is an error * in getting the SDP records or if the process takes a long time, * an Intent is sent with the UUIDs that is currently present in the * cache. Clients should use the {@link getUuids} to get UUIDs * is SDP is not to be performed. * * @return False if the sanity check fails, True if the process * of initiating an ACL connection to the remote device * was started. * @hide */ public boolean fetchUuidsWithSdp() { try { return sService.fetchRemoteUuidsWithSdp(mAddress); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } /** @hide */ public int getServiceChannel(ParcelUuid uuid) { try { Loading
core/java/android/bluetooth/IBluetooth.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ interface IBluetooth String getRemoteName(in String address); int getRemoteClass(in String address); ParcelUuid[] getRemoteUuids(in String address); boolean fetchRemoteUuidsWithSdp(in String address); int getRemoteServiceChannel(in String address,in ParcelUuid uuid); boolean setPin(in String address, in byte[] pin); Loading
core/java/android/server/BluetoothEventLoop.java +23 −0 Original line number Diff line number Diff line Loading @@ -330,6 +330,9 @@ class BluetoothEventLoop { Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null"); return; } if (DBG) { log("Device property changed:" + address + "property:" + name); } BluetoothDevice device = mAdapter.getRemoteDevice(address); if (name.equals("Name")) { Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED); Loading Loading @@ -366,6 +369,7 @@ class BluetoothEventLoop { uuid = str.toString(); } mBluetoothService.setRemoteDeviceProperty(address, name, uuid); mBluetoothService.sendUuidIntent(address); } else if (name.equals("Paired")) { if (propValues[1].equals("true")) { mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED); Loading Loading @@ -528,6 +532,25 @@ class BluetoothEventLoop { return; } private void onDiscoverServicesResult(String deviceObjectPath, boolean result) { String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); // We don't parse the xml here, instead just query Bluez for the properties. if (result) { String[] properties = mBluetoothService.getRemoteDeviceProperties(address); mBluetoothService.addRemoteDeviceProperties(address, properties); } mBluetoothService.sendUuidIntent(address); } private void onCreateDeviceResult(String address, boolean result) { if (DBG) { log("Result of onCreateDeviceResult:" + result); } if (!result) { mBluetoothService.sendUuidIntent(address); } } private void onRestartRequired() { if (mBluetoothService.isEnabled()) { Log.e(TAG, "*** A serious error occured (did bluetoothd crash?) - " + Loading
core/java/android/server/BluetoothService.java +61 −0 Original line number Diff line number Diff line Loading @@ -76,10 +76,17 @@ public class BluetoothService extends IBluetooth.Stub { 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; // The timeout used to sent the UUIDs Intent // This timeout should be greater than the page timeout private static final int UUID_INTENT_DELAY = 6000; private final Map<String, String> mAdapterProperties; private final HashMap <String, Map<String, String>> mDeviceProperties; private final ArrayList <String> mUuidIntentTracker; static { classInitNative(); } Loading @@ -104,6 +111,7 @@ public class BluetoothService extends IBluetooth.Stub { mIsDiscovering = false; mAdapterProperties = new HashMap<String, String>(); mDeviceProperties = new HashMap<String, Map<String,String>>(); mUuidIntentTracker = new ArrayList<String>(); registerForAirplaneMode(); } Loading Loading @@ -291,6 +299,11 @@ public class BluetoothService extends IBluetooth.Stub { case MESSAGE_FINISH_DISABLE: finishDisable(msg.arg1 != 0); break; case MESSAGE_UUID_INTENT: String address = (String)msg.obj; if (address != null) sendUuidIntent(address); break; } } }; Loading Loading @@ -976,6 +989,10 @@ public class BluetoothService extends IBluetooth.Stub { if (!BluetoothAdapter.checkBluetoothAddress(address)) { return null; } return getUuidFromCache(address); } private ParcelUuid[] getUuidFromCache(String address) { String value = getRemoteDeviceProperty(address, "UUIDs"); if (value == null) return null; Loading @@ -990,6 +1007,36 @@ public class BluetoothService extends IBluetooth.Stub { return uuids; } public synchronized boolean fetchRemoteUuidsWithSdp(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (!BluetoothAdapter.checkBluetoothAddress(address)) { return false; } if (mUuidIntentTracker.contains(address)) { // An SDP query for this address is already in progress return true; } boolean ret; if (getBondState(address) == BluetoothDevice.BOND_BONDED) { String path = getObjectPathFromAddress(address); if (path == null) return false; // Use an empty string for the UUID pattern ret = discoverServicesNative(path, ""); } else { ret = createDeviceNative(address); } mUuidIntentTracker.add(address); Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); message.obj = address; mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); return ret; } /** * Gets the rfcomm channel associated with the UUID. * Loading Loading @@ -1121,6 +1168,18 @@ public class BluetoothService extends IBluetooth.Stub { Settings.System.AIRPLANE_MODE_ON, 0) == 1; } /* Broadcast the Uuid intent */ /*package*/ synchronized void sendUuidIntent(String address) { if (mUuidIntentTracker.contains(address)) { ParcelUuid[] uuid = getUuidFromCache(address); Intent intent = new Intent(BluetoothDevice.ACTION_UUID); intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); mUuidIntentTracker.remove(address); } } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n"); Loading Loading @@ -1284,4 +1343,6 @@ public class BluetoothService extends IBluetooth.Stub { private native boolean setPairingConfirmationNative(String address, boolean confirm, int nativeData); private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value); private native boolean createDeviceNative(String address); private native boolean discoverServicesNative(String objectPath, String pattern); }
core/jni/android_server_BluetoothEventLoop.cpp +54 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ static jmethodID method_onDeviceRemoved; static jmethodID method_onDeviceDisconnectRequested; static jmethodID method_onCreatePairedDeviceResult; static jmethodID method_onCreateDeviceResult; static jmethodID method_onDiscoverServicesResult; static jmethodID method_onGetDeviceServiceChannelResult; static jmethodID method_onRequestPinCode; Loading Loading @@ -92,6 +94,10 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult", "(Ljava/lang/String;I)V"); method_onCreateDeviceResult = env->GetMethodID(clazz, "onCreateDeviceResult", "(Ljava/lang/String;Z)V"); method_onDiscoverServicesResult = env->GetMethodID(clazz, "onDiscoverServicesResult", "(Ljava/lang/String;Z)V"); method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize", "(Ljava/lang/String;Ljava/lang/String;)Z"); Loading Loading @@ -1097,6 +1103,54 @@ done: free(user); } void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) { LOGV(__FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *address= (const char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env; nat->vm->GetEnv((void**)&env, nat->envVer); LOGV("... Address = %s", address); bool result = JNI_TRUE; if (dbus_set_error_from_message(&err, msg)) { LOG_AND_FREE_DBUS_ERROR(&err); result = JNI_FALSE; } env->CallVoidMethod(nat->me, method_onCreateDeviceResult, env->NewStringUTF(address), result); free(user); } void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) { LOGV(__FUNCTION__); native_data_t *nat = (native_data_t *)n; const char *path = (const char *)user; DBusError err; dbus_error_init(&err); JNIEnv *env; nat->vm->GetEnv((void**)&env, nat->envVer); LOGV("... Device Path = %s", path); bool result = JNI_TRUE; if (dbus_set_error_from_message(&err, msg)) { LOG_AND_FREE_DBUS_ERROR(&err); result = JNI_FALSE; } env->CallVoidMethod(nat->me, method_onDiscoverServicesResult, env->NewStringUTF(path), result); free(user); } void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) { LOGV(__FUNCTION__); Loading