Loading core/java/android/bluetooth/BluetoothAdapter.java +173 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,9 @@ import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} Loading Loading @@ -1867,6 +1870,22 @@ public final class BluetoothAdapter { return false; } /** @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) public boolean isBroadcastActive() { try { mServiceLock.readLock().lock(); if (mService != null) { return mService.isBroadcastActive(); } } catch (RemoteException e) { Log.e(TAG, "", e); } finally { mServiceLock.readLock().unlock(); } return false; } /** * Connects all enabled and supported bluetooth profiles between the local and remote device. * Connection is asynchronous and you should listen to each profile's broadcast intent Loading Loading @@ -2780,6 +2799,92 @@ public final class BluetoothAdapter { return null; } private void closeBCProfile(BluetoothProfile proxy) { Class<?> bshClass = null; Method bshClose = null; try { bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BSH: exists"); bshClass = null; } if (bshClass != null) { Log.d(TAG, "Able to get BSH class handle"); try { bshClose = bshClass.getDeclaredMethod("close", null); } catch (NoSuchMethodException e) { Log.e(TAG, "no BSH:isSupported method exists"); } if (bshClose != null) { try { bshClose.invoke(proxy, null); } catch(IllegalAccessException e) { Log.e(TAG, "bshClose IllegalAccessException"); } catch (InvocationTargetException e) { Log.e(TAG, "bshClose InvocationTargetException"); } } } Log.d(TAG, "CloseBCProfile returns"); } private boolean getBCProfile(Context context, BluetoothProfile.ServiceListener sl) { boolean ret = true; boolean isProfileSupported = false; Class<?> bshClass = null; Method bshSupported = null; Constructor bshCons = null; Object bshObj = null; try { bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BSH: exists"); bshClass = null; } if (bshClass != null) { Log.d(TAG, "Able to get BSH class handle"); try { bshSupported = bshClass.getDeclaredMethod("isSupported", null); } catch (NoSuchMethodException e) { Log.e(TAG, "no BSH:isSupported method exists: gdm"); } try { bshCons = bshClass.getDeclaredConstructor( new Class[]{Context.class, BluetoothProfile.ServiceListener.class}); } catch (NoSuchMethodException ex) { Log.e(TAG, "bshCons: NoSuchMethodException: gdm" + ex); } } if (bshClass != null && bshSupported != null && bshCons != null) { try { isProfileSupported = (boolean)bshSupported.invoke(null, null); } catch(IllegalAccessException e) { Log.e(TAG, "BSH:isSupported IllegalAccessException"); } catch (InvocationTargetException e) { Log.e(TAG, "BSH:isSupported InvocationTargetException"); } if (isProfileSupported) { try { bshObj = bshCons.newInstance( context, sl); } catch (InstantiationException ex) { Log.e(TAG, "bshCons InstantiationException:" + ex); } catch (IllegalAccessException ex) { Log.e(TAG, "bshCons InstantiationException:" + ex); } catch (InvocationTargetException ex) { Log.e(TAG, "bshCons InvocationTargetException:" + ex); } } } if (bshObj == null) { ret = false; } Log.d(TAG, "getBCService returns" + ret); return ret; } /** * Get the profile proxy object associated with the profile. * Loading Loading @@ -2844,6 +2949,10 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.HID_DEVICE) { BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener); return true; } else if (profile == BluetoothProfile.BC_PROFILE) { return getBCProfile(context, listener); } else if (profile == BluetoothProfile.BROADCAST) { return getBroadcastProfile(context, listener); } else if (profile == BluetoothProfile.HEARING_AID) { if (isHearingAidProfileSupported()) { BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener); Loading Loading @@ -2931,12 +3040,76 @@ public final class BluetoothAdapter { BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy; hidDevice.close(); break; case BluetoothProfile.BC_PROFILE: closeBCProfile(proxy); break; case BluetoothProfile.BROADCAST: closeBroadcastProfile(proxy); break; case BluetoothProfile.HEARING_AID: BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; hearingAid.close(); } } private boolean getBroadcastProfile(Context context, BluetoothProfile.ServiceListener listener) { boolean ret = true; Class<?> broadcastClass = null; Constructor bcastConstructor = null; Object broadcastObj = null; try { broadcastClass = Class.forName("android.bluetooth.BluetoothBroadcast"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BluetoothBroadcast: exists"); } if (broadcastClass != null) { try { bcastConstructor = broadcastClass.getDeclaredConstructor(new Class[]{Context.class, BluetoothProfile.ServiceListener.class}); } catch (NoSuchMethodException ex) { Log.e(TAG, "bcastConstructor: NoSuchMethodException: gdm" + ex); } } if (bcastConstructor != null) { try { broadcastObj = bcastConstructor.newInstance(context, listener); } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) { ex.printStackTrace(); } } if (broadcastObj == null) { return false; } return true; } private void closeBroadcastProfile(BluetoothProfile proxy) { Class<?> broadcastClass = null; Method broadcastClose = null; try { broadcastClass = Class.forName("android.bluetooth.BluetootBroadcast"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BluetoothBroadcast: exists"); } if (broadcastClass != null) { try { broadcastClose = broadcastClass.getDeclaredMethod("close", null); } catch (NoSuchMethodException e) { Log.e(TAG, "no Broadcast:close method exists"); } if (broadcastClose != null) { try { broadcastClose.invoke(proxy, null); } catch(IllegalAccessException | InvocationTargetException ex) { ex.printStackTrace(); } } } } private final IBluetoothManagerCallback mManagerCallback = new IBluetoothManagerCallback.Stub() { public void onBluetoothServiceUp(IBluetooth bluetoothService) { Loading core/java/android/bluetooth/BluetoothDevice.java +43 −1 Original line number Diff line number Diff line Loading @@ -2355,6 +2355,48 @@ public final class BluetoothDevice implements Parcelable { public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, boolean opportunistic, int phy, Handler handler) { return connectGatt(context, autoConnect, callback, transport, opportunistic, phy, handler, false); } /** * Connect to GATT Server hosted by this device. Caller acts as GATT client. * The callback is used to deliver results to Caller, such as connection status as well * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. * * @param callback GATT callback handler that will receive asynchronous callbacks. * @param autoConnect Whether to directly connect to the remote device (false) or to * automatically connect as soon as the remote device becomes available (true). * @param transport preferred transport for GATT connections to remote dual-mode devices {@link * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link * BluetoothDevice#TRANSPORT_LE} * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client * does not hold a GATT connection. It automatically disconnects when no other GATT connections * are active for the remote device. * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} * is set to true. * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on * an un-specified background thread. * @param eattSupport specifies whether client app needs EATT channel for client operations. * If both local and remote devices support EATT and local app asks for EATT, GATT client * operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * client operations will be performed using unenhanced ATT channel. * * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client * operations. * * @throws NullPointerException if callback is null * * @hide */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, boolean opportunistic, int phy, Handler handler, boolean eattSupport) { if (callback == null) { throw new NullPointerException("callback is null"); } Loading @@ -2370,7 +2412,7 @@ public final class BluetoothDevice implements Parcelable { return null; } BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy); gatt.connect(autoConnect, callback, handler); gatt.connect(autoConnect, callback, handler, eattSupport); return gatt; } catch (RemoteException e) { Log.e(TAG, "", e); Loading core/java/android/bluetooth/BluetoothGatt.java +61 −3 Original line number Diff line number Diff line Loading @@ -799,6 +799,28 @@ public final class BluetoothGatt implements BluetoothProfile { * error */ private boolean registerApp(BluetoothGattCallback callback, Handler handler) { return registerApp(callback, handler, false); } /** * Register an application callback to start using GATT. * * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered} * is used to notify success or failure if the function returns true. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param callback GATT callback handler that will receive asynchronous callbacks. * @param eattSupport specifies whether client app needs EATT channel for client operations. * If both local and remote devices support EATT and local app asks for EATT, GATT client * operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * client operations will be performed using unenhanced ATT channel. * @return If true, the callback will be called to notify success or failure, false on immediate * error * @hide */ private boolean registerApp(BluetoothGattCallback callback, Handler handler, boolean eattSupport) { if (DBG) Log.d(TAG, "registerApp()"); if (mService == null) return false; Loading @@ -808,7 +830,7 @@ public final class BluetoothGatt implements BluetoothProfile { if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid); try { mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback); mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback, eattSupport); } catch (RemoteException e) { Log.e(TAG, "", e); return false; Loading Loading @@ -859,9 +881,45 @@ public final class BluetoothGatt implements BluetoothProfile { @UnsupportedAppUsage /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, Handler handler) { return connect(autoConnect, callback, handler, false); } /** * Initiate a connection to a Bluetooth GATT capable device. * * <p>The connection may not be established right away, but will be * completed when the remote device is available. A * {@link BluetoothGattCallback#onConnectionStateChange} callback will be * invoked when the connection state changes as a result of this function. * * <p>The autoConnect parameter determines whether to actively connect to * the remote device, or rather passively scan and finalize the connection * when the remote device is in range/available. Generally, the first ever * connection to a device should be direct (autoConnect set to false) and * subsequent connections to known devices should be invoked with the * autoConnect parameter set to true. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Remote device to connect to * @param autoConnect Whether to directly connect to the remote device (false) or to * automatically connect as soon as the remote device becomes available (true). * @param eattSupport specifies whether client app needs EATT channel for client operations. * If both local and remote devices support EATT and local app asks for EATT, GATT client * operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * client operations will be performed using unenhanced ATT channel. * @return true, if the connection attempt was initiated successfully * * @hide */ @UnsupportedAppUsage /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, Handler handler, boolean eattSupport) { if (DBG) { Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect); "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect + ", eattSupport: " + eattSupport); } synchronized (mStateLock) { if (mConnState != CONN_STATE_IDLE) { Loading @@ -872,7 +930,7 @@ public final class BluetoothGatt implements BluetoothProfile { mAutoConnect = autoConnect; if (!registerApp(callback, handler)) { if (!registerApp(callback, handler, eattSupport)) { synchronized (mStateLock) { mConnState = CONN_STATE_IDLE; } Loading core/java/android/bluetooth/BluetoothGattServer.java +19 −1 Original line number Diff line number Diff line Loading @@ -443,6 +443,24 @@ public final class BluetoothGattServer implements BluetoothProfile { * error */ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) { return registerCallback(callback, false); } /** * Register an application callback to start using GattServer. * * <p>This is an asynchronous call. The callback is used to notify * success or failure if the function returns true. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param callback GATT callback handler that will receive asynchronous callbacks. * @param eattSupport whether eattSupport is needed for Gatt server * @return true, the callback will be called to notify success or failure, false on immediate * error * @hide */ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback, boolean eattSupport) { if (DBG) Log.d(TAG, "registerCallback()"); if (mService == null) { Log.e(TAG, "GATT service not available"); Loading @@ -459,7 +477,7 @@ public final class BluetoothGattServer implements BluetoothProfile { mCallback = callback; try { mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback); mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback, eattSupport); } catch (RemoteException e) { Log.e(TAG, "", e); mCallback = null; Loading core/java/android/bluetooth/BluetoothManager.java +26 −1 Original line number Diff line number Diff line Loading @@ -233,6 +233,31 @@ public final class BluetoothManager { */ public BluetoothGattServer openGattServer(Context context, BluetoothGattServerCallback callback, int transport) { return (openGattServer(context, callback, transport, false)); } /** * Open a GATT Server * The callback is used to deliver results to Caller, such as connection status as well * as the results of any other GATT server operations. * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer * to conduct GATT server operations. * * @param context App context * @param callback GATT server callback handler that will receive asynchronous callbacks. * @param transport preferred transport for GATT connections to remote dual-mode devices {@link * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link * BluetoothDevice#TRANSPORT_LE} * @param eattSupport specifies whether server app needs EATT channel for server operations. * If both local and remote devices support EATT, local app asks for EATT using this API and * calls server connect, GATT server operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * server operations will be performed using unenhanced ATT channel. * @return BluetoothGattServer instance * @hide */ public BluetoothGattServer openGattServer(Context context, BluetoothGattServerCallback callback, int transport, boolean eattSupport) { if (context == null || callback == null) { throw new IllegalArgumentException("null parameter: " + context + " " + callback); } Loading @@ -248,7 +273,7 @@ public final class BluetoothManager { return null; } BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt, transport); Boolean regStatus = mGattServer.registerCallback(callback); Boolean regStatus = mGattServer.registerCallback(callback, eattSupport); return regStatus ? mGattServer : null; } catch (RemoteException e) { Log.e(TAG, "", e); Loading Loading
core/java/android/bluetooth/BluetoothAdapter.java +173 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,9 @@ import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} Loading Loading @@ -1867,6 +1870,22 @@ public final class BluetoothAdapter { return false; } /** @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) public boolean isBroadcastActive() { try { mServiceLock.readLock().lock(); if (mService != null) { return mService.isBroadcastActive(); } } catch (RemoteException e) { Log.e(TAG, "", e); } finally { mServiceLock.readLock().unlock(); } return false; } /** * Connects all enabled and supported bluetooth profiles between the local and remote device. * Connection is asynchronous and you should listen to each profile's broadcast intent Loading Loading @@ -2780,6 +2799,92 @@ public final class BluetoothAdapter { return null; } private void closeBCProfile(BluetoothProfile proxy) { Class<?> bshClass = null; Method bshClose = null; try { bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BSH: exists"); bshClass = null; } if (bshClass != null) { Log.d(TAG, "Able to get BSH class handle"); try { bshClose = bshClass.getDeclaredMethod("close", null); } catch (NoSuchMethodException e) { Log.e(TAG, "no BSH:isSupported method exists"); } if (bshClose != null) { try { bshClose.invoke(proxy, null); } catch(IllegalAccessException e) { Log.e(TAG, "bshClose IllegalAccessException"); } catch (InvocationTargetException e) { Log.e(TAG, "bshClose InvocationTargetException"); } } } Log.d(TAG, "CloseBCProfile returns"); } private boolean getBCProfile(Context context, BluetoothProfile.ServiceListener sl) { boolean ret = true; boolean isProfileSupported = false; Class<?> bshClass = null; Method bshSupported = null; Constructor bshCons = null; Object bshObj = null; try { bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BSH: exists"); bshClass = null; } if (bshClass != null) { Log.d(TAG, "Able to get BSH class handle"); try { bshSupported = bshClass.getDeclaredMethod("isSupported", null); } catch (NoSuchMethodException e) { Log.e(TAG, "no BSH:isSupported method exists: gdm"); } try { bshCons = bshClass.getDeclaredConstructor( new Class[]{Context.class, BluetoothProfile.ServiceListener.class}); } catch (NoSuchMethodException ex) { Log.e(TAG, "bshCons: NoSuchMethodException: gdm" + ex); } } if (bshClass != null && bshSupported != null && bshCons != null) { try { isProfileSupported = (boolean)bshSupported.invoke(null, null); } catch(IllegalAccessException e) { Log.e(TAG, "BSH:isSupported IllegalAccessException"); } catch (InvocationTargetException e) { Log.e(TAG, "BSH:isSupported InvocationTargetException"); } if (isProfileSupported) { try { bshObj = bshCons.newInstance( context, sl); } catch (InstantiationException ex) { Log.e(TAG, "bshCons InstantiationException:" + ex); } catch (IllegalAccessException ex) { Log.e(TAG, "bshCons InstantiationException:" + ex); } catch (InvocationTargetException ex) { Log.e(TAG, "bshCons InvocationTargetException:" + ex); } } } if (bshObj == null) { ret = false; } Log.d(TAG, "getBCService returns" + ret); return ret; } /** * Get the profile proxy object associated with the profile. * Loading Loading @@ -2844,6 +2949,10 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.HID_DEVICE) { BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener); return true; } else if (profile == BluetoothProfile.BC_PROFILE) { return getBCProfile(context, listener); } else if (profile == BluetoothProfile.BROADCAST) { return getBroadcastProfile(context, listener); } else if (profile == BluetoothProfile.HEARING_AID) { if (isHearingAidProfileSupported()) { BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener); Loading Loading @@ -2931,12 +3040,76 @@ public final class BluetoothAdapter { BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy; hidDevice.close(); break; case BluetoothProfile.BC_PROFILE: closeBCProfile(proxy); break; case BluetoothProfile.BROADCAST: closeBroadcastProfile(proxy); break; case BluetoothProfile.HEARING_AID: BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; hearingAid.close(); } } private boolean getBroadcastProfile(Context context, BluetoothProfile.ServiceListener listener) { boolean ret = true; Class<?> broadcastClass = null; Constructor bcastConstructor = null; Object broadcastObj = null; try { broadcastClass = Class.forName("android.bluetooth.BluetoothBroadcast"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BluetoothBroadcast: exists"); } if (broadcastClass != null) { try { bcastConstructor = broadcastClass.getDeclaredConstructor(new Class[]{Context.class, BluetoothProfile.ServiceListener.class}); } catch (NoSuchMethodException ex) { Log.e(TAG, "bcastConstructor: NoSuchMethodException: gdm" + ex); } } if (bcastConstructor != null) { try { broadcastObj = bcastConstructor.newInstance(context, listener); } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) { ex.printStackTrace(); } } if (broadcastObj == null) { return false; } return true; } private void closeBroadcastProfile(BluetoothProfile proxy) { Class<?> broadcastClass = null; Method broadcastClose = null; try { broadcastClass = Class.forName("android.bluetooth.BluetootBroadcast"); } catch (ClassNotFoundException ex) { Log.e(TAG, "no BluetoothBroadcast: exists"); } if (broadcastClass != null) { try { broadcastClose = broadcastClass.getDeclaredMethod("close", null); } catch (NoSuchMethodException e) { Log.e(TAG, "no Broadcast:close method exists"); } if (broadcastClose != null) { try { broadcastClose.invoke(proxy, null); } catch(IllegalAccessException | InvocationTargetException ex) { ex.printStackTrace(); } } } } private final IBluetoothManagerCallback mManagerCallback = new IBluetoothManagerCallback.Stub() { public void onBluetoothServiceUp(IBluetooth bluetoothService) { Loading
core/java/android/bluetooth/BluetoothDevice.java +43 −1 Original line number Diff line number Diff line Loading @@ -2355,6 +2355,48 @@ public final class BluetoothDevice implements Parcelable { public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, boolean opportunistic, int phy, Handler handler) { return connectGatt(context, autoConnect, callback, transport, opportunistic, phy, handler, false); } /** * Connect to GATT Server hosted by this device. Caller acts as GATT client. * The callback is used to deliver results to Caller, such as connection status as well * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. * * @param callback GATT callback handler that will receive asynchronous callbacks. * @param autoConnect Whether to directly connect to the remote device (false) or to * automatically connect as soon as the remote device becomes available (true). * @param transport preferred transport for GATT connections to remote dual-mode devices {@link * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link * BluetoothDevice#TRANSPORT_LE} * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client * does not hold a GATT connection. It automatically disconnects when no other GATT connections * are active for the remote device. * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} * is set to true. * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on * an un-specified background thread. * @param eattSupport specifies whether client app needs EATT channel for client operations. * If both local and remote devices support EATT and local app asks for EATT, GATT client * operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * client operations will be performed using unenhanced ATT channel. * * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client * operations. * * @throws NullPointerException if callback is null * * @hide */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, boolean opportunistic, int phy, Handler handler, boolean eattSupport) { if (callback == null) { throw new NullPointerException("callback is null"); } Loading @@ -2370,7 +2412,7 @@ public final class BluetoothDevice implements Parcelable { return null; } BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy); gatt.connect(autoConnect, callback, handler); gatt.connect(autoConnect, callback, handler, eattSupport); return gatt; } catch (RemoteException e) { Log.e(TAG, "", e); Loading
core/java/android/bluetooth/BluetoothGatt.java +61 −3 Original line number Diff line number Diff line Loading @@ -799,6 +799,28 @@ public final class BluetoothGatt implements BluetoothProfile { * error */ private boolean registerApp(BluetoothGattCallback callback, Handler handler) { return registerApp(callback, handler, false); } /** * Register an application callback to start using GATT. * * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered} * is used to notify success or failure if the function returns true. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param callback GATT callback handler that will receive asynchronous callbacks. * @param eattSupport specifies whether client app needs EATT channel for client operations. * If both local and remote devices support EATT and local app asks for EATT, GATT client * operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * client operations will be performed using unenhanced ATT channel. * @return If true, the callback will be called to notify success or failure, false on immediate * error * @hide */ private boolean registerApp(BluetoothGattCallback callback, Handler handler, boolean eattSupport) { if (DBG) Log.d(TAG, "registerApp()"); if (mService == null) return false; Loading @@ -808,7 +830,7 @@ public final class BluetoothGatt implements BluetoothProfile { if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid); try { mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback); mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback, eattSupport); } catch (RemoteException e) { Log.e(TAG, "", e); return false; Loading Loading @@ -859,9 +881,45 @@ public final class BluetoothGatt implements BluetoothProfile { @UnsupportedAppUsage /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, Handler handler) { return connect(autoConnect, callback, handler, false); } /** * Initiate a connection to a Bluetooth GATT capable device. * * <p>The connection may not be established right away, but will be * completed when the remote device is available. A * {@link BluetoothGattCallback#onConnectionStateChange} callback will be * invoked when the connection state changes as a result of this function. * * <p>The autoConnect parameter determines whether to actively connect to * the remote device, or rather passively scan and finalize the connection * when the remote device is in range/available. Generally, the first ever * connection to a device should be direct (autoConnect set to false) and * subsequent connections to known devices should be invoked with the * autoConnect parameter set to true. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Remote device to connect to * @param autoConnect Whether to directly connect to the remote device (false) or to * automatically connect as soon as the remote device becomes available (true). * @param eattSupport specifies whether client app needs EATT channel for client operations. * If both local and remote devices support EATT and local app asks for EATT, GATT client * operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * client operations will be performed using unenhanced ATT channel. * @return true, if the connection attempt was initiated successfully * * @hide */ @UnsupportedAppUsage /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, Handler handler, boolean eattSupport) { if (DBG) { Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect); "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect + ", eattSupport: " + eattSupport); } synchronized (mStateLock) { if (mConnState != CONN_STATE_IDLE) { Loading @@ -872,7 +930,7 @@ public final class BluetoothGatt implements BluetoothProfile { mAutoConnect = autoConnect; if (!registerApp(callback, handler)) { if (!registerApp(callback, handler, eattSupport)) { synchronized (mStateLock) { mConnState = CONN_STATE_IDLE; } Loading
core/java/android/bluetooth/BluetoothGattServer.java +19 −1 Original line number Diff line number Diff line Loading @@ -443,6 +443,24 @@ public final class BluetoothGattServer implements BluetoothProfile { * error */ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) { return registerCallback(callback, false); } /** * Register an application callback to start using GattServer. * * <p>This is an asynchronous call. The callback is used to notify * success or failure if the function returns true. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param callback GATT callback handler that will receive asynchronous callbacks. * @param eattSupport whether eattSupport is needed for Gatt server * @return true, the callback will be called to notify success or failure, false on immediate * error * @hide */ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback, boolean eattSupport) { if (DBG) Log.d(TAG, "registerCallback()"); if (mService == null) { Log.e(TAG, "GATT service not available"); Loading @@ -459,7 +477,7 @@ public final class BluetoothGattServer implements BluetoothProfile { mCallback = callback; try { mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback); mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback, eattSupport); } catch (RemoteException e) { Log.e(TAG, "", e); mCallback = null; Loading
core/java/android/bluetooth/BluetoothManager.java +26 −1 Original line number Diff line number Diff line Loading @@ -233,6 +233,31 @@ public final class BluetoothManager { */ public BluetoothGattServer openGattServer(Context context, BluetoothGattServerCallback callback, int transport) { return (openGattServer(context, callback, transport, false)); } /** * Open a GATT Server * The callback is used to deliver results to Caller, such as connection status as well * as the results of any other GATT server operations. * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer * to conduct GATT server operations. * * @param context App context * @param callback GATT server callback handler that will receive asynchronous callbacks. * @param transport preferred transport for GATT connections to remote dual-mode devices {@link * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link * BluetoothDevice#TRANSPORT_LE} * @param eattSupport specifies whether server app needs EATT channel for server operations. * If both local and remote devices support EATT, local app asks for EATT using this API and * calls server connect, GATT server operations will be performed using EATT channel. * If either local or remote device doesn't support EATT but local App asks for EATT, GATT * server operations will be performed using unenhanced ATT channel. * @return BluetoothGattServer instance * @hide */ public BluetoothGattServer openGattServer(Context context, BluetoothGattServerCallback callback, int transport, boolean eattSupport) { if (context == null || callback == null) { throw new IllegalArgumentException("null parameter: " + context + " " + callback); } Loading @@ -248,7 +273,7 @@ public final class BluetoothManager { return null; } BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt, transport); Boolean regStatus = mGattServer.registerCallback(callback); Boolean regStatus = mGattServer.registerCallback(callback, eattSupport); return regStatus ? mGattServer : null; } catch (RemoteException e) { Log.e(TAG, "", e); Loading