diff options
Diffstat (limited to 'framework/java/android')
27 files changed, 670 insertions, 57 deletions
diff --git a/framework/java/android/bluetooth/BluetoothA2dp.java b/framework/java/android/bluetooth/BluetoothA2dp.java index 94fd138ca6..d21f76d435 100644 --- a/framework/java/android/bluetooth/BluetoothA2dp.java +++ b/framework/java/android/bluetooth/BluetoothA2dp.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -29,6 +30,7 @@ import android.os.Binder; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import com.android.internal.annotations.GuardedBy; @@ -117,6 +119,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_ACTIVE_DEVICE_CHANGED = "android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED"; @@ -137,6 +140,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_CODEC_CONFIG_CHANGED = "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED"; @@ -160,6 +164,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; /** @@ -167,6 +172,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; /** @@ -174,6 +180,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public static final int OPTIONAL_CODECS_SUPPORTED = 1; /** @@ -182,6 +189,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; /** @@ -189,6 +197,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; /** @@ -196,6 +205,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; private Context mContext; @@ -261,13 +271,14 @@ public final class BluetoothA2dp implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - mContext.getUser())) { + UserHandle.CURRENT_OR_SELF)) { Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent); return false; } return true; } + @UnsupportedAppUsage /*package*/ void close() { mServiceListener = null; IBluetoothManager mgr = mAdapter.getBluetoothManager(); @@ -315,6 +326,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @return false on immediate error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); try { @@ -357,6 +369,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @return false on immediate error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); try { @@ -460,6 +473,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @return false on immediate error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean setActiveDevice(@Nullable BluetoothDevice device) { if (DBG) log("setActiveDevice(" + device + ")"); try { @@ -490,6 +504,7 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @RequiresPermission(Manifest.permission.BLUETOOTH) @Nullable + @UnsupportedAppUsage public BluetoothDevice getActiveDevice() { if (VDBG) log("getActiveDevice()"); try { @@ -556,6 +571,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) + @UnsupportedAppUsage public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); try { @@ -671,6 +687,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @return the current codec status * @hide */ + @UnsupportedAppUsage public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) { if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")"); try { @@ -698,6 +715,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * @param codecConfig the codec configuration preference * @hide */ + @UnsupportedAppUsage public void setCodecConfigPreference(BluetoothDevice device, BluetoothCodecConfig codecConfig) { if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")"); @@ -723,6 +741,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * active A2DP Bluetooth device. * @hide */ + @UnsupportedAppUsage public void enableOptionalCodecs(BluetoothDevice device) { if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")"); enableDisableOptionalCodecs(device, true); @@ -735,6 +754,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * active A2DP Bluetooth device. * @hide */ + @UnsupportedAppUsage public void disableOptionalCodecs(BluetoothDevice device) { if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")"); enableDisableOptionalCodecs(device, false); @@ -775,6 +795,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * OPTIONAL_CODECS_SUPPORTED. * @hide */ + @UnsupportedAppUsage public int supportsOptionalCodecs(BluetoothDevice device) { try { mServiceLock.readLock().lock(); @@ -799,6 +820,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * OPTIONAL_CODECS_PREF_DISABLED. * @hide */ + @UnsupportedAppUsage public int getOptionalCodecsEnabled(BluetoothDevice device) { try { mServiceLock.readLock().lock(); @@ -824,6 +846,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * OPTIONAL_CODECS_PREF_DISABLED. * @hide */ + @UnsupportedAppUsage public void setOptionalCodecsEnabled(BluetoothDevice device, int value) { try { if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN @@ -854,6 +877,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public static String stateToString(int state) { switch (state) { case STATE_DISCONNECTED: diff --git a/framework/java/android/bluetooth/BluetoothA2dpSink.java b/framework/java/android/bluetooth/BluetoothA2dpSink.java index 13f0aaf47f..fda2f89275 100755 --- a/framework/java/android/bluetooth/BluetoothA2dpSink.java +++ b/framework/java/android/bluetooth/BluetoothA2dpSink.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -278,6 +279,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * @return false on immediate error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothA2dpSink service = mService; diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 44051081b5..8e6a3856d5 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -23,6 +23,7 @@ import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; +import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; import android.bluetooth.le.BluetoothLeAdvertiser; import android.bluetooth.le.BluetoothLeScanner; @@ -80,7 +81,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * {@link #getBondedDevices()}; start device discovery with * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to * listen for incoming RFComm connection requests with {@link - * #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for + * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented + * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}. * </p> * <p>This class is thread safe.</p> @@ -394,6 +396,64 @@ public final class BluetoothAdapter { public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; /** + * Device only has a display. + * + * @hide + */ + public static final int IO_CAPABILITY_OUT = 0; + + /** + * Device has a display and the ability to input Yes/No. + * + * @hide + */ + public static final int IO_CAPABILITY_IO = 1; + + /** + * Device only has a keyboard for entry but no display. + * + * @hide + */ + public static final int IO_CAPABILITY_IN = 2; + + /** + * Device has no Input or Output capability. + * + * @hide + */ + public static final int IO_CAPABILITY_NONE = 3; + + /** + * Device has a display and a full keyboard. + * + * @hide + */ + public static final int IO_CAPABILITY_KBDISP = 4; + + /** + * Maximum range value for Input/Output capabilities. + * + * <p>This should be updated when adding a new Input/Output capability. Other code + * like validation depends on this being accurate. + * + * @hide + */ + public static final int IO_CAPABILITY_MAX = 5; + + /** + * The Input/Output capability of the device is unknown. + * + * @hide + */ + public static final int IO_CAPABILITY_UNKNOWN = 255; + + /** @hide */ + @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE, + IO_CAPABILITY_KBDISP}) + @Retention(RetentionPolicy.SOURCE) + public @interface IoCapability {} + + /** * Broadcast Action: The local Bluetooth adapter has started the remote * device discovery process. * <p>This usually involves an inquiry scan of about 12 seconds, followed @@ -581,6 +641,7 @@ public final class BluetoothAdapter { private static PeriodicAdvertisingManager sPeriodicAdvertisingManager; private final IBluetoothManager mManagerService; + @UnsupportedAppUsage private IBluetooth mService; private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); @@ -936,6 +997,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH) @AdapterState + @UnsupportedAppUsage public int getLeState() { int state = BluetoothAdapter.STATE_OFF; @@ -1046,6 +1108,7 @@ public final class BluetoothAdapter { * @return true to indicate adapter shutdown has begun, or false on immediate error * @hide */ + @UnsupportedAppUsage public boolean disable(boolean persist) { try { @@ -1097,6 +1160,7 @@ public final class BluetoothAdapter { * @return true to indicate that the config file was successfully cleared * @hide */ + @UnsupportedAppUsage public boolean factoryReset() { try { mServiceLock.readLock().lock(); @@ -1120,6 +1184,7 @@ public final class BluetoothAdapter { * @return the UUIDs supported by the local Bluetooth Adapter. * @hide */ + @UnsupportedAppUsage public ParcelUuid[] getUuids() { if (getState() != STATE_ON) { return null; @@ -1225,6 +1290,108 @@ public final class BluetoothAdapter { } /** + * Returns the Input/Output capability of the device for classic Bluetooth. + * + * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT}, + * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE}, + * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}. + * + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @IoCapability + public int getIoCapability() { + if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN; + try { + mServiceLock.readLock().lock(); + if (mService != null) return mService.getIoCapability(); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage(), e); + } finally { + mServiceLock.readLock().unlock(); + } + return BluetoothAdapter.IO_CAPABILITY_UNKNOWN; + } + + /** + * Sets the Input/Output capability of the device for classic Bluetooth. + * + * <p>Changing the Input/Output capability of a device only takes effect on restarting the + * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()} + * and {@link BluetoothAdapter#enable()} to see the changes. + * + * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT}, + * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, + * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}. + * + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + public boolean setIoCapability(@IoCapability int capability) { + if (getState() != STATE_ON) return false; + try { + mServiceLock.readLock().lock(); + if (mService != null) return mService.setIoCapability(capability); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage(), e); + } finally { + mServiceLock.readLock().unlock(); + } + return false; + } + + /** + * Returns the Input/Output capability of the device for BLE operations. + * + * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT}, + * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE}, + * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}. + * + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @IoCapability + public int getLeIoCapability() { + if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN; + try { + mServiceLock.readLock().lock(); + if (mService != null) return mService.getLeIoCapability(); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage(), e); + } finally { + mServiceLock.readLock().unlock(); + } + return BluetoothAdapter.IO_CAPABILITY_UNKNOWN; + } + + /** + * Sets the Input/Output capability of the device for BLE operations. + * + * <p>Changing the Input/Output capability of a device only takes effect on restarting the + * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()} + * and {@link BluetoothAdapter#enable()} to see the changes. + * + * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT}, + * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, + * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}. + * + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + public boolean setLeIoCapability(@IoCapability int capability) { + if (getState() != STATE_ON) return false; + try { + mServiceLock.readLock().lock(); + if (mService != null) return mService.setLeIoCapability(capability); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage(), e); + } finally { + mServiceLock.readLock().unlock(); + } + return false; + } + + /** * Get the current Bluetooth scan mode of the local Bluetooth adapter. * <p>The Bluetooth scan mode determines if the local adapter is * connectable and/or discoverable from remote Bluetooth devices. @@ -1286,6 +1453,7 @@ public final class BluetoothAdapter { * @return true if the scan mode was set, false otherwise * @hide */ + @UnsupportedAppUsage public boolean setScanMode(@ScanMode int mode, int duration) { if (getState() != STATE_ON) { return false; @@ -1304,6 +1472,7 @@ public final class BluetoothAdapter { } /** @hide */ + @UnsupportedAppUsage public boolean setScanMode(int mode) { if (getState() != STATE_ON) { return false; @@ -1313,6 +1482,7 @@ public final class BluetoothAdapter { } /** @hide */ + @UnsupportedAppUsage public int getDiscoverableTimeout() { if (getState() != STATE_ON) { return -1; @@ -1331,6 +1501,7 @@ public final class BluetoothAdapter { } /** @hide */ + @UnsupportedAppUsage public void setDiscoverableTimeout(int timeout) { if (getState() != STATE_ON) { return; @@ -1855,6 +2026,7 @@ public final class BluetoothAdapter { * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED} * @hide */ + @UnsupportedAppUsage public int getConnectionState() { if (getState() != STATE_ON) { return BluetoothAdapter.STATE_DISCONNECTED; @@ -1942,6 +2114,7 @@ public final class BluetoothAdapter { * permissions, or channel in use. * @hide */ + @UnsupportedAppUsage public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm, boolean min16DigitPin) throws IOException { BluetoothServerSocket socket = @@ -2054,6 +2227,7 @@ public final class BluetoothAdapter { * permissions, or channel in use. * @hide */ + @UnsupportedAppUsage public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid) throws IOException { return createNewRfcommSocketAndRecord(name, uuid, false, true); @@ -2597,6 +2771,7 @@ public final class BluetoothAdapter { return true; } + @UnsupportedAppUsage /*package*/ IBluetoothManager getBluetoothManager() { return mManagerService; } @@ -2604,6 +2779,7 @@ public final class BluetoothAdapter { private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>(); + @UnsupportedAppUsage /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) { synchronized (mProxyServiceStateCallbacks) { if (cb == null) { @@ -2792,7 +2968,7 @@ public final class BluetoothAdapter { /** * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen - * for incoming connections. + * for incoming connections. The supported Bluetooth transport is LE only. * <p>A remote device connecting to this socket will be authenticated and communication on this * socket will be encrypted. * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening @@ -2802,21 +2978,16 @@ public final class BluetoothAdapter { * closed, Bluetooth is turned off, or the application exits unexpectedly. * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is * defined and performed by the application. - * <p>Use {@link BluetoothDevice#createL2capCocSocket(int, int)} to connect to this server + * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server * socket from another Android device that is given the PSM value. * - * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE} * @return an L2CAP CoC BluetoothServerSocket * @throws IOException on error, for example Bluetooth not available, or insufficient * permissions, or unable to start this CoC - * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) - public BluetoothServerSocket listenUsingL2capCoc(int transport) + public BluetoothServerSocket listenUsingL2capChannel() throws IOException { - if (transport != BluetoothDevice.TRANSPORT_LE) { - throw new IllegalArgumentException("Unsupported transport: " + transport); - } BluetoothServerSocket socket = new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true, SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false); @@ -2830,7 +3001,7 @@ public final class BluetoothAdapter { throw new IOException("Error: Unable to assign PSM value"); } if (DBG) { - Log.d(TAG, "listenUsingL2capCoc: set assigned PSM to " + Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to " + assignedPsm); } socket.setChannel(assignedPsm); @@ -2839,10 +3010,23 @@ public final class BluetoothAdapter { } /** + * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new + * API name, listenUsingL2capChannel. + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public BluetoothServerSocket listenUsingL2capCoc(int transport) + throws IOException { + Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel"); + return listenUsingL2capChannel(); + } + + /** * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and - * assign a dynamic PSM value. This socket can be used to listen for incoming connections. + * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The + * supported Bluetooth transport is LE only. * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable - * to man-in-the-middle attacks. Use {@link #listenUsingL2capCoc}, if an encrypted and + * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and * authenticated communication channel is desired. * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening * {@link BluetoothServerSocket}. @@ -2852,21 +3036,16 @@ public final class BluetoothAdapter { * unexpectedly. * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is * defined and performed by the application. - * <p>Use {@link BluetoothDevice#createInsecureL2capCocSocket(int, int)} to connect to this - * server socket from another Android device that is given the PSM value. + * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server + * socket from another Android device that is given the PSM value. * - * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE} * @return an L2CAP CoC BluetoothServerSocket * @throws IOException on error, for example Bluetooth not available, or insufficient * permissions, or unable to start this CoC - * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) - public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport) + public BluetoothServerSocket listenUsingInsecureL2capChannel() throws IOException { - if (transport != BluetoothDevice.TRANSPORT_LE) { - throw new IllegalArgumentException("Unsupported transport: " + transport); - } BluetoothServerSocket socket = new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false, SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false); @@ -2880,11 +3059,24 @@ public final class BluetoothAdapter { throw new IOException("Error: Unable to assign PSM value"); } if (DBG) { - Log.d(TAG, "listenUsingInsecureL2capOn: set assigned PSM to " + Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to " + assignedPsm); } socket.setChannel(assignedPsm); return socket; } + + /** + * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new + * API name, listenUsingInsecureL2capChannel. + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport) + throws IOException { + Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, " + + "listenUsingInsecureL2capChannel"); + return listenUsingInsecureL2capChannel(); + } } diff --git a/framework/java/android/bluetooth/BluetoothClass.java b/framework/java/android/bluetooth/BluetoothClass.java index f22ea6e88e..3a78cbdd4d 100755 --- a/framework/java/android/bluetooth/BluetoothClass.java +++ b/framework/java/android/bluetooth/BluetoothClass.java @@ -16,6 +16,8 @@ package android.bluetooth; +import android.annotation.TestApi; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -63,6 +65,7 @@ public final class BluetoothClass implements Parcelable { private final int mClass; /** @hide */ + @UnsupportedAppUsage public BluetoothClass(int classInt) { mClass = classInt; } @@ -291,6 +294,7 @@ public final class BluetoothClass implements Parcelable { * * @hide */ + @TestApi public int getClassOfDevice() { return mClass; } @@ -322,8 +326,10 @@ public final class BluetoothClass implements Parcelable { } /** @hide */ + @UnsupportedAppUsage public static final int PROFILE_HEADSET = 0; /** @hide */ + @UnsupportedAppUsage public static final int PROFILE_A2DP = 1; /** @hide */ public static final int PROFILE_OPP = 2; @@ -346,6 +352,7 @@ public final class BluetoothClass implements Parcelable { * @return True if this device might support specified profile. * @hide */ + @UnsupportedAppUsage public boolean doesClassMatch(int profile) { if (profile == PROFILE_A2DP) { if (hasService(Service.RENDER)) { diff --git a/framework/java/android/bluetooth/BluetoothCodecConfig.java b/framework/java/android/bluetooth/BluetoothCodecConfig.java index e3a6e06472..79c0a3a207 100644 --- a/framework/java/android/bluetooth/BluetoothCodecConfig.java +++ b/framework/java/android/bluetooth/BluetoothCodecConfig.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -32,34 +33,58 @@ public final class BluetoothCodecConfig implements Parcelable { // Add an entry for each source codec here. // NOTE: The values should be same as those listed in the following file: // hardware/libhardware/include/hardware/bt_av.h + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_SBC = 0; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_AAC = 1; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_APTX = 2; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_LDAC = 4; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_MAX = 5; + @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; + @UnsupportedAppUsage public static final int CODEC_PRIORITY_DISABLED = -1; + @UnsupportedAppUsage public static final int CODEC_PRIORITY_DEFAULT = 0; + @UnsupportedAppUsage public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000; + @UnsupportedAppUsage public static final int SAMPLE_RATE_NONE = 0; + @UnsupportedAppUsage public static final int SAMPLE_RATE_44100 = 0x1 << 0; + @UnsupportedAppUsage public static final int SAMPLE_RATE_48000 = 0x1 << 1; + @UnsupportedAppUsage public static final int SAMPLE_RATE_88200 = 0x1 << 2; + @UnsupportedAppUsage public static final int SAMPLE_RATE_96000 = 0x1 << 3; + @UnsupportedAppUsage public static final int SAMPLE_RATE_176400 = 0x1 << 4; + @UnsupportedAppUsage public static final int SAMPLE_RATE_192000 = 0x1 << 5; + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_NONE = 0; + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_16 = 0x1 << 0; + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_24 = 0x1 << 1; + @UnsupportedAppUsage public static final int BITS_PER_SAMPLE_32 = 0x1 << 2; + @UnsupportedAppUsage public static final int CHANNEL_MODE_NONE = 0; + @UnsupportedAppUsage public static final int CHANNEL_MODE_MONO = 0x1 << 0; + @UnsupportedAppUsage public static final int CHANNEL_MODE_STEREO = 0x1 << 1; private final int mCodecType; @@ -72,6 +97,7 @@ public final class BluetoothCodecConfig implements Parcelable { private final long mCodecSpecific3; private final long mCodecSpecific4; + @UnsupportedAppUsage public BluetoothCodecConfig(int codecType, int codecPriority, int sampleRate, int bitsPerSample, int channelMode, long codecSpecific1, @@ -276,6 +302,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec type */ + @UnsupportedAppUsage public int getCodecType() { return mCodecType; } @@ -296,6 +323,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec priority */ + @UnsupportedAppUsage public int getCodecPriority() { return mCodecPriority; } @@ -307,6 +335,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @param codecPriority the codec priority */ + @UnsupportedAppUsage public void setCodecPriority(int codecPriority) { mCodecPriority = codecPriority; } @@ -324,6 +353,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec sample rate */ + @UnsupportedAppUsage public int getSampleRate() { return mSampleRate; } @@ -338,6 +368,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec bits per sample */ + @UnsupportedAppUsage public int getBitsPerSample() { return mBitsPerSample; } @@ -351,6 +382,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return the codec channel mode */ + @UnsupportedAppUsage public int getChannelMode() { return mChannelMode; } @@ -360,6 +392,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return a codec specific value1. */ + @UnsupportedAppUsage public long getCodecSpecific1() { return mCodecSpecific1; } @@ -369,6 +402,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return a codec specific value2 */ + @UnsupportedAppUsage public long getCodecSpecific2() { return mCodecSpecific2; } @@ -378,6 +412,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return a codec specific value3 */ + @UnsupportedAppUsage public long getCodecSpecific3() { return mCodecSpecific3; } @@ -387,6 +422,7 @@ public final class BluetoothCodecConfig implements Parcelable { * * @return a codec specific value4 */ + @UnsupportedAppUsage public long getCodecSpecific4() { return mCodecSpecific4; } diff --git a/framework/java/android/bluetooth/BluetoothCodecStatus.java b/framework/java/android/bluetooth/BluetoothCodecStatus.java index 3a05e7093d..78560d2de4 100644 --- a/framework/java/android/bluetooth/BluetoothCodecStatus.java +++ b/framework/java/android/bluetooth/BluetoothCodecStatus.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -37,6 +38,7 @@ public final class BluetoothCodecStatus implements Parcelable { * This extra represents the current codec status of the A2DP * profile. */ + @UnsupportedAppUsage public static final String EXTRA_CODEC_STATUS = "android.bluetooth.codec.extra.CODEC_STATUS"; @@ -137,6 +139,7 @@ public final class BluetoothCodecStatus implements Parcelable { * * @return the current codec configuration */ + @UnsupportedAppUsage public BluetoothCodecConfig getCodecConfig() { return mCodecConfig; } @@ -146,6 +149,7 @@ public final class BluetoothCodecStatus implements Parcelable { * * @return an array with the codecs local capabilities */ + @UnsupportedAppUsage public BluetoothCodecConfig[] getCodecsLocalCapabilities() { return mCodecsLocalCapabilities; } @@ -155,6 +159,7 @@ public final class BluetoothCodecStatus implements Parcelable { * * @return an array with the codecs selectable capabilities */ + @UnsupportedAppUsage public BluetoothCodecConfig[] getCodecsSelectableCapabilities() { return mCodecsSelectableCapabilities; } diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 3cf8074665..fc0c1dc438 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -21,6 +21,7 @@ import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Handler; import android.os.Parcel; @@ -115,6 +116,7 @@ public final class BluetoothDevice implements Parcelable { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_DISAPPEARED = "android.bluetooth.device.action.DISAPPEARED"; @@ -186,6 +188,7 @@ public final class BluetoothDevice implements Parcelable { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.device.action.ALIAS_CHANGED"; @@ -306,6 +309,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON"; /** @@ -346,6 +350,7 @@ public final class BluetoothDevice implements Parcelable { /** @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_SDP_RECORD = "android.bluetooth.device.action.SDP_RECORD"; @@ -390,6 +395,7 @@ public final class BluetoothDevice implements Parcelable { "android.bluetooth.device.action.PAIRING_REQUEST"; /** @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_PAIRING_CANCEL = "android.bluetooth.device.action.PAIRING_CANCEL"; @@ -481,6 +487,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final int UNBOND_REASON_AUTH_FAILED = 1; /** @@ -489,6 +496,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final int UNBOND_REASON_AUTH_REJECTED = 2; /** @@ -503,6 +511,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4; /** @@ -510,6 +519,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5; /** @@ -517,6 +527,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final int UNBOND_REASON_AUTH_TIMEOUT = 6; /** @@ -524,6 +535,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7; /** @@ -532,6 +544,7 @@ public final class BluetoothDevice implements Parcelable { * * @hide */ + @UnsupportedAppUsage public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8; /** @@ -610,6 +623,7 @@ public final class BluetoothDevice implements Parcelable { "android.bluetooth.device.extra.SDP_RECORD"; /** @hide */ + @UnsupportedAppUsage public static final String EXTRA_SDP_SEARCH_STATUS = "android.bluetooth.device.extra.SDP_SEARCH_STATUS"; /** @@ -720,6 +734,7 @@ public final class BluetoothDevice implements Parcelable { private final String mAddress; /*package*/ + @UnsupportedAppUsage static IBluetooth getService() { synchronized (BluetoothDevice.class) { if (sService == null) { @@ -763,6 +778,7 @@ public final class BluetoothDevice implements Parcelable { * @throws IllegalArgumentException address is invalid * @hide */ + @UnsupportedAppUsage /*package*/ BluetoothDevice(String address) { getService(); // ensures sService is initialized if (!BluetoothAdapter.checkBluetoothAddress(address)) { @@ -887,6 +903,7 @@ public final class BluetoothDevice implements Parcelable { * @return the Bluetooth alias, or null if no alias or there was a problem * @hide */ + @UnsupportedAppUsage public String getAlias() { final IBluetooth service = sService; if (service == null) { @@ -911,6 +928,7 @@ public final class BluetoothDevice implements Parcelable { * @return true on success, false on error * @hide */ + @UnsupportedAppUsage public boolean setAlias(String alias) { final IBluetooth service = sService; if (service == null) { @@ -934,6 +952,7 @@ public final class BluetoothDevice implements Parcelable { * @see #getAlias() * @see #getName() */ + @UnsupportedAppUsage public String getAliasName() { String name = getAlias(); if (name == null) { @@ -952,6 +971,7 @@ public final class BluetoothDevice implements Parcelable { * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) + @UnsupportedAppUsage public int getBatteryLevel() { final IBluetooth service = sService; if (service == null) { @@ -1010,6 +1030,7 @@ public final class BluetoothDevice implements Parcelable { * @throws IllegalArgumentException if an invalid transport was specified * @hide */ + @UnsupportedAppUsage public boolean createBond(int transport) { final IBluetooth service = sService; if (service == null) { @@ -1063,6 +1084,7 @@ public final class BluetoothDevice implements Parcelable { } /** @hide */ + @UnsupportedAppUsage public boolean isBondingInitiatedLocally() { final IBluetooth service = sService; if (service == null) { @@ -1355,6 +1377,7 @@ public final class BluetoothDevice implements Parcelable { } /** @hide */ + @UnsupportedAppUsage public boolean setPasskey(int passkey) { //TODO(BT) /* @@ -1395,6 +1418,7 @@ public final class BluetoothDevice implements Parcelable { } /** @hide */ + @UnsupportedAppUsage public boolean cancelPairingUserInput() { final IBluetooth service = sService; if (service == null) { @@ -1410,6 +1434,7 @@ public final class BluetoothDevice implements Parcelable { } /** @hide */ + @UnsupportedAppUsage public boolean isBluetoothDock() { // TODO(BT) /* @@ -1435,6 +1460,7 @@ public final class BluetoothDevice implements Parcelable { * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. * @hide */ + @UnsupportedAppUsage public int getPhonebookAccessPermission() { final IBluetooth service = sService; if (service == null) { @@ -1479,6 +1505,7 @@ public final class BluetoothDevice implements Parcelable { * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. * @hide */ + @UnsupportedAppUsage public int getMessageAccessPermission() { final IBluetooth service = sService; if (service == null) { @@ -1501,6 +1528,7 @@ public final class BluetoothDevice implements Parcelable { * @return Whether the value has been successfully set. * @hide */ + @UnsupportedAppUsage public boolean setMessageAccessPermission(int value) { final IBluetooth service = sService; if (service == null) { @@ -1543,6 +1571,7 @@ public final class BluetoothDevice implements Parcelable { * @return Whether the value has been successfully set. * @hide */ + @UnsupportedAppUsage public boolean setSimAccessPermission(int value) { final IBluetooth service = sService; if (service == null) { @@ -1581,6 +1610,7 @@ public final class BluetoothDevice implements Parcelable { * permissions * @hide */ + @UnsupportedAppUsage public BluetoothSocket createRfcommSocket(int channel) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); @@ -1733,6 +1763,7 @@ public final class BluetoothDevice implements Parcelable { * permissions. * @hide */ + @UnsupportedAppUsage public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); @@ -1752,6 +1783,7 @@ public final class BluetoothDevice implements Parcelable { * permissions. * @hide */ + @UnsupportedAppUsage public BluetoothSocket createScoSocket() throws IOException { if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); @@ -1769,6 +1801,7 @@ public final class BluetoothDevice implements Parcelable { * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin. * @hide */ + @UnsupportedAppUsage public static byte[] convertPinToBytes(String pin) { if (pin == null) { return null; @@ -1900,6 +1933,7 @@ public final class BluetoothDevice implements Parcelable { * operations. * @hide */ + @UnsupportedAppUsage public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, boolean opportunistic, int phy, Handler handler) { @@ -1929,8 +1963,8 @@ public final class BluetoothDevice implements Parcelable { /** * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can * be used to start a secure outgoing connection to the remote device with the same dynamic - * protocol/service multiplexer (PSM) value. - * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capCoc(int)} for + * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only. + * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capChannel()} for * peer-peer Bluetooth applications. * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection. * <p>Application using this API is responsible for obtaining PSM value from remote device. @@ -1941,59 +1975,71 @@ public final class BluetoothDevice implements Parcelable { * secure socket connection is not possible, use {@link createInsecureLeL2capCocSocket(int, * int)}. * - * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE} * @param psm dynamic PSM value from remote device * @return a CoC #BluetoothSocket ready for an outgoing connection * @throws IOException on error, for example Bluetooth not available, or insufficient * permissions - * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) - public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException { + public BluetoothSocket createL2capChannel(int psm) throws IOException { if (!isBluetoothEnabled()) { - Log.e(TAG, "createL2capCocSocket: Bluetooth is not enabled"); + Log.e(TAG, "createL2capChannel: Bluetooth is not enabled"); throw new IOException(); } - if (transport != BluetoothDevice.TRANSPORT_LE) { - throw new IllegalArgumentException("Unsupported transport: " + transport); - } - if (DBG) Log.d(TAG, "createL2capCocSocket: transport=" + transport + ", psm=" + psm); + if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm); return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm, null); } /** + * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new + * API name, createL2capChannel. + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException { + Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createL2capChannel"); + return createL2capChannel(psm); + } + + /** * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can * be used to start a secure outgoing connection to the remote device with the same dynamic - * protocol/service multiplexer (PSM) value. - * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingInsecureL2capCoc(int)} - * for peer-peer Bluetooth applications. + * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only. + * <p>This is designed to be used with {@link + * BluetoothAdapter#listenUsingInsecureL2capChannel()} for peer-peer Bluetooth applications. * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection. * <p>Application using this API is responsible for obtaining PSM value from remote device. * <p> The communication channel may not have an authenticated link key, i.e. it may be subject - * to man-in-the-middle attacks. Use {@link #createL2capCocSocket(int, int)} if an encrypted and + * to man-in-the-middle attacks. Use {@link #createL2capChannel(int)} if an encrypted and * authenticated communication channel is possible. * - * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE} * @param psm dynamic PSM value from remote device * @return a CoC #BluetoothSocket ready for an outgoing connection * @throws IOException on error, for example Bluetooth not available, or insufficient * permissions - * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) - public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException { + public BluetoothSocket createInsecureL2capChannel(int psm) throws IOException { if (!isBluetoothEnabled()) { - Log.e(TAG, "createInsecureL2capCocSocket: Bluetooth is not enabled"); + Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled"); throw new IOException(); } - if (transport != BluetoothDevice.TRANSPORT_LE) { - throw new IllegalArgumentException("Unsupported transport: " + transport); - } if (DBG) { - Log.d(TAG, "createInsecureL2capCocSocket: transport=" + transport + ", psm=" + psm); + Log.d(TAG, "createInsecureL2capChannel: psm=" + psm); } return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm, null); } + + /** + * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new + * API name, createInsecureL2capChannel. + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException { + Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createInsecureL2capChannel"); + return createInsecureL2capChannel(psm); + } } diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java index 77b65f0d1b..43f68f7e3d 100644 --- a/framework/java/android/bluetooth/BluetoothGatt.java +++ b/framework/java/android/bluetooth/BluetoothGatt.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Handler; import android.os.ParcelUuid; import android.os.RemoteException; @@ -41,16 +42,23 @@ public final class BluetoothGatt implements BluetoothProfile { private static final boolean DBG = true; private static final boolean VDBG = false; + @UnsupportedAppUsage private IBluetoothGatt mService; + @UnsupportedAppUsage private volatile BluetoothGattCallback mCallback; private Handler mHandler; + @UnsupportedAppUsage private int mClientIf; private BluetoothDevice mDevice; + @UnsupportedAppUsage private boolean mAutoConnect; + @UnsupportedAppUsage private int mAuthRetryState; private int mConnState; private final Object mStateLock = new Object(); + @UnsupportedAppUsage private Boolean mDeviceBusy = false; + @UnsupportedAppUsage private int mTransport; private int mPhy; private boolean mOpportunistic; @@ -810,6 +818,7 @@ public final class BluetoothGatt implements BluetoothProfile { /** * Unregister the current application and callbacks. */ + @UnsupportedAppUsage private void unregisterApp() { if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf); if (mService == null || mClientIf == 0) return; @@ -845,6 +854,7 @@ public final class BluetoothGatt implements BluetoothProfile { * automatically connect as soon as the remote device becomes available (true). * @return true, if the connection attempt was initiated successfully */ + @UnsupportedAppUsage /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, Handler handler) { if (DBG) { @@ -1407,6 +1417,7 @@ public final class BluetoothGatt implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public boolean refresh() { if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; diff --git a/framework/java/android/bluetooth/BluetoothGattCharacteristic.java b/framework/java/android/bluetooth/BluetoothGattCharacteristic.java index 243ad359a4..6d46b3a418 100644 --- a/framework/java/android/bluetooth/BluetoothGattCharacteristic.java +++ b/framework/java/android/bluetooth/BluetoothGattCharacteristic.java @@ -15,6 +15,7 @@ */ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; @@ -182,6 +183,7 @@ public class BluetoothGattCharacteristic implements Parcelable { * * @hide */ + @UnsupportedAppUsage protected int mInstance; /** @@ -218,6 +220,7 @@ public class BluetoothGattCharacteristic implements Parcelable { * * @hide */ + @UnsupportedAppUsage protected BluetoothGattService mService; /** @@ -381,6 +384,7 @@ public class BluetoothGattCharacteristic implements Parcelable { * * @hide */ + @UnsupportedAppUsage /*package*/ void setService(BluetoothGattService service) { mService = service; } @@ -464,6 +468,7 @@ public class BluetoothGattCharacteristic implements Parcelable { * * @hide */ + @UnsupportedAppUsage public void setKeySize(int keySize) { mKeySize = keySize; } diff --git a/framework/java/android/bluetooth/BluetoothGattDescriptor.java b/framework/java/android/bluetooth/BluetoothGattDescriptor.java index 217a5abf1f..3ffbb9e0c0 100644 --- a/framework/java/android/bluetooth/BluetoothGattDescriptor.java +++ b/framework/java/android/bluetooth/BluetoothGattDescriptor.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; @@ -100,6 +101,7 @@ public class BluetoothGattDescriptor implements Parcelable { * * @hide */ + @UnsupportedAppUsage protected int mInstance; /** @@ -114,6 +116,7 @@ public class BluetoothGattDescriptor implements Parcelable { * * @hide */ + @UnsupportedAppUsage protected BluetoothGattCharacteristic mCharacteristic; /** @@ -205,6 +208,7 @@ public class BluetoothGattDescriptor implements Parcelable { * * @hide */ + @UnsupportedAppUsage /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) { mCharacteristic = characteristic; } diff --git a/framework/java/android/bluetooth/BluetoothGattService.java b/framework/java/android/bluetooth/BluetoothGattService.java index ce1dc1ce63..8e740ee387 100644 --- a/framework/java/android/bluetooth/BluetoothGattService.java +++ b/framework/java/android/bluetooth/BluetoothGattService.java @@ -15,6 +15,7 @@ */ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; @@ -48,6 +49,7 @@ public class BluetoothGattService implements Parcelable { * * @hide */ + @UnsupportedAppUsage protected BluetoothDevice mDevice; /** @@ -265,6 +267,7 @@ public class BluetoothGattService implements Parcelable { * * @hide */ + @UnsupportedAppUsage public void setInstanceId(int instanceId) { mInstanceId = instanceId; } @@ -382,6 +385,7 @@ public class BluetoothGattService implements Parcelable { * * @hide */ + @UnsupportedAppUsage public void setAdvertisePreferred(boolean advertisePreferred) { mAdvertisePreferred = advertisePreferred; } diff --git a/framework/java/android/bluetooth/BluetoothHeadset.java b/framework/java/android/bluetooth/BluetoothHeadset.java index 0c91a2054b..636b1b9b13 100644 --- a/framework/java/android/bluetooth/BluetoothHeadset.java +++ b/framework/java/android/bluetooth/BluetoothHeadset.java @@ -22,6 +22,7 @@ import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.os.Binder; @@ -110,6 +111,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_ACTIVE_DEVICE_CHANGED = "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED"; @@ -401,6 +403,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * results once close() has been called. Multiple invocations of close() * are ok. */ + @UnsupportedAppUsage /*package*/ void close() { if (VDBG) log("close()"); @@ -602,6 +605,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @return priority of the device * @hide */ + @UnsupportedAppUsage public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); final IBluetoothHeadset service = mService; @@ -719,6 +723,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public int getAudioState(BluetoothDevice device) { if (VDBG) log("getAudioState"); final IBluetoothHeadset service = mService; @@ -846,6 +851,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @return false if there was some error such as there is no active headset * @hide */ + @UnsupportedAppUsage public boolean connectAudio() { final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { @@ -872,6 +878,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @return false if audio is not connected, or on error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean disconnectAudio() { final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { @@ -909,6 +916,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @UnsupportedAppUsage public boolean startScoUsingVirtualVoiceCall() { if (DBG) log("startScoUsingVirtualVoiceCall()"); final IBluetoothHeadset service = mService; @@ -938,6 +946,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @UnsupportedAppUsage public boolean stopScoUsingVirtualVoiceCall() { if (DBG) log("stopScoUsingVirtualVoiceCall()"); final IBluetoothHeadset service = mService; @@ -962,6 +971,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * * @hide */ + @UnsupportedAppUsage public void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type) { final IBluetoothHeadset service = mService; @@ -1060,6 +1070,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) + @UnsupportedAppUsage public boolean setActiveDevice(@Nullable BluetoothDevice device) { if (DBG) { Log.d(TAG, "setActiveDevice: " + device); @@ -1089,6 +1100,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ @RequiresPermission(android.Manifest.permission.BLUETOOTH) + @UnsupportedAppUsage public BluetoothDevice getActiveDevice() { if (VDBG) { Log.d(TAG, "getActiveDevice"); @@ -1163,6 +1175,7 @@ public final class BluetoothHeadset implements BluetoothProfile { } }; + @UnsupportedAppUsage private boolean isEnabled() { return mAdapter.getState() == BluetoothAdapter.STATE_ON; } diff --git a/framework/java/android/bluetooth/BluetoothHeadsetClient.java b/framework/java/android/bluetooth/BluetoothHeadsetClient.java index 397b90656f..ec18d42698 100644 --- a/framework/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/framework/java/android/bluetooth/BluetoothHeadsetClient.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -476,6 +477,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * @return <code>true</code> if command has been issued successfully; <code>false</code> * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent. */ + @UnsupportedAppUsage public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothHeadsetClient service = mService; @@ -498,6 +500,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * @return <code>true</code> if command has been issued successfully; <code>false</code> * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent. */ + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothHeadsetClient service = mService; @@ -720,6 +723,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * @return <code>true</code> if command has been issued successfully; <code>false</code> * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent. */ + @UnsupportedAppUsage public boolean acceptCall(BluetoothDevice device, int flag) { if (DBG) log("acceptCall()"); final IBluetoothHeadsetClient service = mService; @@ -766,6 +770,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * #EXTRA_AG_FEATURE_REJECT_CALL}. This method invocation will fail silently when feature is not * supported.</p> */ + @UnsupportedAppUsage public boolean rejectCall(BluetoothDevice device) { if (DBG) log("rejectCall()"); final IBluetoothHeadsetClient service = mService; @@ -943,6 +948,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * * Note: This is an internal function and shouldn't be exposed */ + @UnsupportedAppUsage public int getAudioState(BluetoothDevice device) { if (VDBG) log("getAudioState"); final IBluetoothHeadsetClient service = mService; diff --git a/framework/java/android/bluetooth/BluetoothHeadsetClientCall.java b/framework/java/android/bluetooth/BluetoothHeadsetClientCall.java index d46b2e3746..e02a2f4ae5 100644 --- a/framework/java/android/bluetooth/BluetoothHeadsetClientCall.java +++ b/framework/java/android/bluetooth/BluetoothHeadsetClientCall.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -143,6 +144,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * @return call id. */ + @UnsupportedAppUsage public int getId() { return mId; } @@ -162,6 +164,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * @return state of this particular phone call. */ + @UnsupportedAppUsage public int getState() { return mState; } @@ -171,6 +174,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * @return string representing phone number. */ + @UnsupportedAppUsage public String getNumber() { return mNumber; } @@ -189,6 +193,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * @return <code>true</code> if call is a multi party call, <code>false</code> otherwise. */ + @UnsupportedAppUsage public boolean isMultiParty() { return mMultiParty; } @@ -198,6 +203,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * @return <code>true</code> if its outgoing call, <code>false</code> otherwise. */ + @UnsupportedAppUsage public boolean isOutgoing() { return mOutgoing; } diff --git a/framework/java/android/bluetooth/BluetoothHearingAid.java b/framework/java/android/bluetooth/BluetoothHearingAid.java index 159e165d59..606f00a823 100644 --- a/framework/java/android/bluetooth/BluetoothHearingAid.java +++ b/framework/java/android/bluetooth/BluetoothHearingAid.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -108,6 +109,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { * receive. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage public static final String ACTION_ACTIVE_DEVICE_CHANGED = "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED"; @@ -401,6 +403,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { * @return false on immediate error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean setActiveDevice(@Nullable BluetoothDevice device) { if (DBG) log("setActiveDevice(" + device + ")"); try { @@ -432,6 +435,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) + @UnsupportedAppUsage public List<BluetoothDevice> getActiveDevices() { if (VDBG) log("getActiveDevices()"); try { diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 0fa1d5d629..98c23c600f 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -233,6 +234,7 @@ public final class BluetoothMap implements BluetoothProfile { * @param device Remote Bluetooth Device * @return false on error, true otherwise */ + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = mService; diff --git a/framework/java/android/bluetooth/BluetoothMapClient.java b/framework/java/android/bluetooth/BluetoothMapClient.java index 4f21d936e5..559a59b68b 100644 --- a/framework/java/android/bluetooth/BluetoothMapClient.java +++ b/framework/java/android/bluetooth/BluetoothMapClient.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -72,6 +73,8 @@ public final class BluetoothMapClient implements BluetoothProfile { /** Connection canceled before completion. */ public static final int RESULT_CANCELED = 2; + private static final int UPLOADING_FEATURE_BITMASK = 0x08; + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { @@ -358,6 +361,7 @@ public final class BluetoothMapClient implements BluetoothProfile { * @param deliveredIntent intent issued when message is delivered * @return true if the message is enqueued, false on error */ + @UnsupportedAppUsage public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message, PendingIntent sentIntent, PendingIntent deliveredIntent) { if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message); @@ -393,6 +397,23 @@ public final class BluetoothMapClient implements BluetoothProfile { return false; } + /** + * Returns the "Uploading" feature bit value from the SDP record's + * MapSupportedFeatures field (see Bluetooth MAP 1.4 spec, page 114). + * @param device The Bluetooth device to get this value for. + * @return Returns true if the Uploading bit value in SDP record's + * MapSupportedFeatures field is set. False is returned otherwise. + */ + public boolean isUploadingSupported(BluetoothDevice device) { + try { + return (mService != null && isEnabled() && isValidDevice(device)) + && ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage()); + } + return false; + } + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); diff --git a/framework/java/android/bluetooth/BluetoothPan.java b/framework/java/android/bluetooth/BluetoothPan.java index 9f401eb3ce..58be732960 100644 --- a/framework/java/android/bluetooth/BluetoothPan.java +++ b/framework/java/android/bluetooth/BluetoothPan.java @@ -18,6 +18,7 @@ package android.bluetooth; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -129,6 +130,7 @@ public final class BluetoothPan implements BluetoothProfile { * Create a BluetoothPan proxy object for interacting with the local * Bluetooth Service which handles the Pan profile */ + @UnsupportedAppUsage /*package*/ BluetoothPan(Context context, ServiceListener l) { mContext = context; mServiceListener = l; @@ -142,6 +144,7 @@ public final class BluetoothPan implements BluetoothProfile { doBind(); } + @UnsupportedAppUsage boolean doBind() { Intent intent = new Intent(IBluetoothPan.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); @@ -154,6 +157,7 @@ public final class BluetoothPan implements BluetoothProfile { return true; } + @UnsupportedAppUsage /*package*/ void close() { if (VDBG) log("close()"); @@ -236,6 +240,7 @@ public final class BluetoothPan implements BluetoothProfile { * @return false on immediate error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothPan service = mPanService; @@ -276,6 +281,7 @@ public final class BluetoothPan implements BluetoothProfile { * @return false on immediate error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothPan service = mPanService; @@ -348,6 +354,7 @@ public final class BluetoothPan implements BluetoothProfile { return BluetoothProfile.STATE_DISCONNECTED; } + @UnsupportedAppUsage public void setBluetoothTethering(boolean value) { if (DBG) log("setBluetoothTethering(" + value + ")"); final IBluetoothPan service = mPanService; @@ -360,6 +367,7 @@ public final class BluetoothPan implements BluetoothProfile { } } + @UnsupportedAppUsage public boolean isTetheringOn() { if (VDBG) log("isTetheringOn()"); final IBluetoothPan service = mPanService; @@ -392,14 +400,17 @@ public final class BluetoothPan implements BluetoothProfile { } }; + @UnsupportedAppUsage private boolean isEnabled() { return mAdapter.getState() == BluetoothAdapter.STATE_ON; } + @UnsupportedAppUsage private static boolean isValidDevice(BluetoothDevice device) { return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } + @UnsupportedAppUsage private static void log(String msg) { Log.d(TAG, msg); } diff --git a/framework/java/android/bluetooth/BluetoothPbap.java b/framework/java/android/bluetooth/BluetoothPbap.java index c60e9e075c..ae264e19bb 100644 --- a/framework/java/android/bluetooth/BluetoothPbap.java +++ b/framework/java/android/bluetooth/BluetoothPbap.java @@ -17,6 +17,7 @@ package android.bluetooth; import android.annotation.SdkConstant; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -281,6 +282,7 @@ public class BluetoothPbap implements BluetoothProfile { */ // TODO: This is currently being used by SettingsLib and will be used in the future. // TODO: Must specify target device. Implement this in the service. + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { log("disconnect()"); final IBluetoothPbap service = mService; diff --git a/framework/java/android/bluetooth/BluetoothProfile.java b/framework/java/android/bluetooth/BluetoothProfile.java index 6aeb94da11..9777b5cc6c 100644 --- a/framework/java/android/bluetooth/BluetoothProfile.java +++ b/framework/java/android/bluetooth/BluetoothProfile.java @@ -20,6 +20,7 @@ package android.bluetooth; import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.UnsupportedAppUsage; import java.util.List; @@ -85,6 +86,7 @@ public interface BluetoothProfile { * * @hide */ + @UnsupportedAppUsage int PAN = 5; /** @@ -122,6 +124,7 @@ public interface BluetoothProfile { * * @hide */ + @UnsupportedAppUsage int A2DP_SINK = 11; /** @@ -129,6 +132,7 @@ public interface BluetoothProfile { * * @hide */ + @UnsupportedAppUsage int AVRCP_CONTROLLER = 12; /** @@ -192,6 +196,7 @@ public interface BluetoothProfile { * * @hide **/ + @UnsupportedAppUsage int PRIORITY_AUTO_CONNECT = 1000; /** @@ -217,6 +222,7 @@ public interface BluetoothProfile { * * @hide */ + @UnsupportedAppUsage int PRIORITY_UNDEFINED = -1; /** diff --git a/framework/java/android/bluetooth/BluetoothSap.java b/framework/java/android/bluetooth/BluetoothSap.java index c51e39a741..1b732062f6 100644 --- a/framework/java/android/bluetooth/BluetoothSap.java +++ b/framework/java/android/bluetooth/BluetoothSap.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -280,6 +281,7 @@ public final class BluetoothSap implements BluetoothProfile { * @return false on error, true otherwise * @hide */ + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothSap service = mService; diff --git a/framework/java/android/bluetooth/BluetoothServerSocket.java b/framework/java/android/bluetooth/BluetoothServerSocket.java index ca29ef37a2..758c68db1c 100644 --- a/framework/java/android/bluetooth/BluetoothServerSocket.java +++ b/framework/java/android/bluetooth/BluetoothServerSocket.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.Handler; import android.os.ParcelUuid; import android.util.Log; @@ -69,6 +70,7 @@ public final class BluetoothServerSocket implements Closeable { private static final String TAG = "BluetoothServerSocket"; private static final boolean DBG = false; + @UnsupportedAppUsage /*package*/ final BluetoothSocket mSocket; private Handler mHandler; private int mMessage; @@ -201,12 +203,11 @@ public final class BluetoothServerSocket implements Closeable { /** * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the - * {@link BluetoothAdapter.listenUsingL2capCoc(int)} or {@link - * BluetoothAdapter.listenUsingInsecureL2capCoc(int)}. The returned value is undefined if this + * {@link BluetoothAdapter.listenUsingL2capChannel()} or {@link + * BluetoothAdapter.listenUsingInsecureL2capChannel()}. The returned value is undefined if this * method is called on non-L2CAP server sockets. * * @return the assigned PSM or LE_PSM value depending on transport - * @hide */ public int getPsm() { return mChannel; diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index 09a5b593e5..3a1e2f58c9 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.net.LocalSocket; import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; @@ -110,6 +111,7 @@ public final class BluetoothSocket implements Closeable { public static final int TYPE_L2CAP_LE = 4; /*package*/ static final int EBADFD = 77; + @UnsupportedAppUsage /*package*/ static final int EADDRINUSE = 98; /*package*/ static final int SEC_FLAG_ENCRYPT = 1; @@ -129,10 +131,13 @@ public final class BluetoothSocket implements Closeable { private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */ private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/ private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */ + @UnsupportedAppUsage private ParcelFileDescriptor mPfd; + @UnsupportedAppUsage private LocalSocket mSocket; private InputStream mSocketIS; private OutputStream mSocketOS; + @UnsupportedAppUsage private int mPort; /* RFCOMM channel or L2CAP psm */ private int mFd; private String mServiceName; @@ -517,6 +522,7 @@ public final class BluetoothSocket implements Closeable { * * @throws IOException if an i/o error occurs. */ + @UnsupportedAppUsage /*package*/ void flush() throws IOException { if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); if (VDBG) Log.d(TAG, "flush: " + mSocketOS); @@ -661,6 +667,10 @@ public final class BluetoothSocket implements Closeable { * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP} */ public int getConnectionType() { + if (mType == TYPE_L2CAP_LE) { + // Treat the LE CoC to be the same type as L2CAP. + return TYPE_L2CAP; + } return mType; } diff --git a/framework/java/android/bluetooth/BluetoothUuid.java b/framework/java/android/bluetooth/BluetoothUuid.java index 605dbd2199..fdbfec00e6 100644 --- a/framework/java/android/bluetooth/BluetoothUuid.java +++ b/framework/java/android/bluetooth/BluetoothUuid.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.os.ParcelUuid; import java.nio.ByteBuffer; @@ -37,16 +38,20 @@ public final class BluetoothUuid { * The following 128 bit values are calculated as: * uuid * 2^96 + BASE_UUID */ + @UnsupportedAppUsage public static final ParcelUuid AudioSink = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid AudioSource = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); + @UnsupportedAppUsage public static final ParcelUuid AdvAudioDist = ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB"); + @UnsupportedAppUsage 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"); + @UnsupportedAppUsage public static final ParcelUuid Handsfree = ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid Handsfree_AG = @@ -55,20 +60,24 @@ public final class BluetoothUuid { ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid AvrcpTarget = ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"); + @UnsupportedAppUsage public static final ParcelUuid ObexObjectPush = ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb"); public static final ParcelUuid Hid = ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb"); + @UnsupportedAppUsage public static final ParcelUuid Hogp = ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb"); public static final ParcelUuid PANU = ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB"); + @UnsupportedAppUsage public static final ParcelUuid NAP = ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid BNEP = ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid PBAP_PCE = ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB"); + @UnsupportedAppUsage public static final ParcelUuid PBAP_PSE = ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid MAP = @@ -92,10 +101,12 @@ public final class BluetoothUuid { /** Length of bytes for 128 bit UUID */ public static final int UUID_BYTES_128_BIT = 16; + @UnsupportedAppUsage public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, ObexObjectPush, PANU, NAP, MAP, MNS, MAS, SAP}; + @UnsupportedAppUsage public static boolean isAudioSource(ParcelUuid uuid) { return uuid.equals(AudioSource); } @@ -104,6 +115,7 @@ public final class BluetoothUuid { return uuid.equals(AudioSink); } + @UnsupportedAppUsage public static boolean isAdvAudioDist(ParcelUuid uuid) { return uuid.equals(AdvAudioDist); } @@ -120,6 +132,7 @@ public final class BluetoothUuid { return uuid.equals(AvrcpController); } + @UnsupportedAppUsage public static boolean isAvrcpTarget(ParcelUuid uuid) { return uuid.equals(AvrcpTarget); } @@ -162,6 +175,7 @@ public final class BluetoothUuid { * @param uuidArray - Array of ParcelUuids * @param uuid */ + @UnsupportedAppUsage public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) { if ((uuidArray == null || uuidArray.length == 0) && uuid == null) { return true; @@ -183,6 +197,7 @@ public final class BluetoothUuid { * @param uuidA - List of ParcelUuids * @param uuidB - List of ParcelUuids */ + @UnsupportedAppUsage public static boolean containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB) { if (uuidA == null && uuidB == null) return true; @@ -330,6 +345,7 @@ public final class BluetoothUuid { * @param parcelUuid * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. */ + @UnsupportedAppUsage public static boolean is16BitUuid(ParcelUuid parcelUuid) { UUID uuid = parcelUuid.getUuid(); if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { @@ -345,6 +361,7 @@ public final class BluetoothUuid { * @param parcelUuid * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise. */ + @UnsupportedAppUsage public static boolean is32BitUuid(ParcelUuid parcelUuid) { UUID uuid = parcelUuid.getUuid(); if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { diff --git a/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java index 0fb4ba1a87..13c5ff6909 100644 --- a/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -411,7 +411,14 @@ public final class BluetoothLeAdvertiser { try { gatt = mBluetoothManager.getBluetoothGatt(); } catch (RemoteException e) { - Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + Log.e(TAG, "Failed to get Bluetooth GATT - ", e); + postStartSetFailure(handler, callback, + AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + return; + } + + if (gatt == null) { + Log.e(TAG, "Bluetooth GATT is null"); postStartSetFailure(handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); return; diff --git a/framework/java/android/bluetooth/le/ScanFilter.java b/framework/java/android/bluetooth/le/ScanFilter.java index c3fae7d470..c5d435b761 100644 --- a/framework/java/android/bluetooth/le/ScanFilter.java +++ b/framework/java/android/bluetooth/le/ScanFilter.java @@ -58,6 +58,11 @@ public final class ScanFilter implements Parcelable { private final ParcelUuid mServiceUuidMask; @Nullable + private final ParcelUuid mServiceSolicitationUuid; + @Nullable + private final ParcelUuid mServiceSolicitationUuidMask; + + @Nullable private final ParcelUuid mServiceDataUuid; @Nullable private final byte[] mServiceData; @@ -75,12 +80,15 @@ public final class ScanFilter implements Parcelable { private ScanFilter(String name, String deviceAddress, ParcelUuid uuid, - ParcelUuid uuidMask, ParcelUuid serviceDataUuid, + ParcelUuid uuidMask, ParcelUuid solicitationUuid, + ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid, byte[] serviceData, byte[] serviceDataMask, int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask) { mDeviceName = name; mServiceUuid = uuid; mServiceUuidMask = uuidMask; + mServiceSolicitationUuid = solicitationUuid; + mServiceSolicitationUuidMask = solicitationUuidMask; mDeviceAddress = deviceAddress; mServiceDataUuid = serviceDataUuid; mServiceData = serviceData; @@ -113,6 +121,14 @@ public final class ScanFilter implements Parcelable { dest.writeParcelable(mServiceUuidMask, flags); } } + dest.writeInt(mServiceSolicitationUuid == null ? 0 : 1); + if (mServiceSolicitationUuid != null) { + dest.writeParcelable(mServiceSolicitationUuid, flags); + dest.writeInt(mServiceSolicitationUuidMask == null ? 0 : 1); + if (mServiceSolicitationUuidMask != null) { + dest.writeParcelable(mServiceSolicitationUuidMask, flags); + } + } dest.writeInt(mServiceDataUuid == null ? 0 : 1); if (mServiceDataUuid != null) { dest.writeParcelable(mServiceDataUuid, flags); @@ -172,6 +188,17 @@ public final class ScanFilter implements Parcelable { } } if (in.readInt() == 1) { + ParcelUuid solicitationUuid = in.readParcelable( + ParcelUuid.class.getClassLoader()); + builder.setServiceSolicitationUuid(solicitationUuid); + if (in.readInt() == 1) { + ParcelUuid solicitationUuidMask = in.readParcelable( + ParcelUuid.class.getClassLoader()); + builder.setServiceSolicitationUuid(solicitationUuid, + solicitationUuidMask); + } + } + if (in.readInt() == 1) { ParcelUuid servcieDataUuid = in.readParcelable(ParcelUuid.class.getClassLoader()); if (in.readInt() == 1) { @@ -231,6 +258,22 @@ public final class ScanFilter implements Parcelable { return mServiceUuidMask; } + /** + * Returns the filter set on the service Solicitation uuid. + */ + @Nullable + public ParcelUuid getServiceSolicitationUuid() { + return mServiceSolicitationUuid; + } + + /** + * Returns the filter set on the service Solicitation uuid mask. + */ + @Nullable + public ParcelUuid getServiceSolicitationUuidMask() { + return mServiceSolicitationUuidMask; + } + @Nullable public String getDeviceAddress() { return mDeviceAddress; @@ -288,7 +331,7 @@ public final class ScanFilter implements Parcelable { // Scan record is null but there exist filters on it. if (scanRecord == null && (mDeviceName != null || mServiceUuid != null || mManufacturerData != null - || mServiceData != null)) { + || mServiceData != null || mServiceSolicitationUuid != null)) { return false; } @@ -303,6 +346,13 @@ public final class ScanFilter implements Parcelable { return false; } + // solicitation UUID match. + if (mServiceSolicitationUuid != null && !matchesServiceSolicitationUuids( + mServiceSolicitationUuid, mServiceSolicitationUuidMask, + scanRecord.getServiceSolicitationUuids())) { + return false; + } + // Service data match if (mServiceDataUuid != null) { if (!matchesPartialData(mServiceData, mServiceDataMask, @@ -350,6 +400,36 @@ public final class ScanFilter implements Parcelable { return BitUtils.maskedEquals(data, uuid, mask); } + /** + * Check if the solicitation uuid pattern is contained in a list of parcel uuids. + * + */ + private static boolean matchesServiceSolicitationUuids(ParcelUuid solicitationUuid, + ParcelUuid parcelSolicitationUuidMask, List<ParcelUuid> solicitationUuids) { + if (solicitationUuid == null) { + return true; + } + if (solicitationUuids == null) { + return false; + } + + for (ParcelUuid parcelSolicitationUuid : solicitationUuids) { + UUID solicitationUuidMask = parcelSolicitationUuidMask == null + ? null : parcelSolicitationUuidMask.getUuid(); + if (matchesServiceUuid(solicitationUuid.getUuid(), solicitationUuidMask, + parcelSolicitationUuid.getUuid())) { + return true; + } + } + return false; + } + + // Check if the solicitation uuid pattern matches the particular service solicitation uuid. + private static boolean matchesServiceSolicitationUuid(UUID solicitationUuid, + UUID solicitationUuidMask, UUID data) { + return BitUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask); + } + // Check whether the data pattern matches the parsed data. private boolean matchesPartialData(byte[] data, byte[] dataMask, byte[] parsedData) { if (parsedData == null || parsedData.length < data.length) { @@ -376,6 +456,8 @@ public final class ScanFilter implements Parcelable { return "BluetoothLeScanFilter [mDeviceName=" + mDeviceName + ", mDeviceAddress=" + mDeviceAddress + ", mUuid=" + mServiceUuid + ", mUuidMask=" + mServiceUuidMask + + ", mServiceSolicitationUuid=" + mServiceSolicitationUuid + + ", mServiceSolicitationUuidMask=" + mServiceSolicitationUuidMask + ", mServiceDataUuid=" + Objects.toString(mServiceDataUuid) + ", mServiceData=" + Arrays.toString(mServiceData) + ", mServiceDataMask=" + Arrays.toString(mServiceDataMask) + ", mManufacturerId=" + mManufacturerId @@ -391,7 +473,8 @@ public final class ScanFilter implements Parcelable { mServiceDataUuid, Arrays.hashCode(mServiceData), Arrays.hashCode(mServiceDataMask), - mServiceUuid, mServiceUuidMask); + mServiceUuid, mServiceUuidMask, + mServiceSolicitationUuid, mServiceSolicitationUuidMask); } @Override @@ -412,7 +495,10 @@ public final class ScanFilter implements Parcelable { && Objects.deepEquals(mServiceData, other.mServiceData) && Objects.deepEquals(mServiceDataMask, other.mServiceDataMask) && Objects.equals(mServiceUuid, other.mServiceUuid) - && Objects.equals(mServiceUuidMask, other.mServiceUuidMask); + && Objects.equals(mServiceUuidMask, other.mServiceUuidMask) + && Objects.equals(mServiceSolicitationUuid, other.mServiceSolicitationUuid) + && Objects.equals(mServiceSolicitationUuidMask, + other.mServiceSolicitationUuidMask); } /** @@ -435,6 +521,9 @@ public final class ScanFilter implements Parcelable { private ParcelUuid mServiceUuid; private ParcelUuid mUuidMask; + private ParcelUuid mServiceSolicitationUuid; + private ParcelUuid mServiceSolicitationUuidMask; + private ParcelUuid mServiceDataUuid; private byte[] mServiceData; private byte[] mServiceDataMask; @@ -493,6 +582,36 @@ public final class ScanFilter implements Parcelable { return this; } + + /** + * Set filter on service solicitation uuid. + */ + public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid) { + mServiceSolicitationUuid = serviceSolicitationUuid; + return this; + } + + + /** + * Set filter on partial service Solicitation uuid. The {@code SolicitationUuidMask} is the + * bit mask for the {@code serviceSolicitationUuid}. Set any bit in the mask to 1 to + * indicate a match is needed for the bit in {@code serviceSolicitationUuid}, and 0 to + * ignore that bit. + * + * @throws IllegalArgumentException If {@code serviceSolicitationUuid} is {@code null} but + * {@code serviceSolicitationUuidMask} is not {@code null}. + */ + public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid, + ParcelUuid solicitationUuidMask) { + if (mServiceSolicitationUuidMask != null && mServiceSolicitationUuid == null) { + throw new IllegalArgumentException( + "SolicitationUuid is null while SolicitationUuidMask is not null!"); + } + mServiceSolicitationUuid = serviceSolicitationUuid; + mServiceSolicitationUuidMask = solicitationUuidMask; + return this; + } + /** * Set filtering on service data. * @@ -598,7 +717,8 @@ public final class ScanFilter implements Parcelable { */ public ScanFilter build() { return new ScanFilter(mDeviceName, mDeviceAddress, - mServiceUuid, mUuidMask, + mServiceUuid, mUuidMask, mServiceSolicitationUuid, + mServiceSolicitationUuidMask, mServiceDataUuid, mServiceData, mServiceDataMask, mManufacturerId, mManufacturerData, mManufacturerDataMask); } diff --git a/framework/java/android/bluetooth/le/ScanRecord.java b/framework/java/android/bluetooth/le/ScanRecord.java index f8aaba910b..7988008f03 100644 --- a/framework/java/android/bluetooth/le/ScanRecord.java +++ b/framework/java/android/bluetooth/le/ScanRecord.java @@ -17,6 +17,7 @@ package android.bluetooth.le; import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; import android.bluetooth.BluetoothUuid; import android.os.ParcelUuid; import android.util.ArrayMap; @@ -50,6 +51,9 @@ public final class ScanRecord { private static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16; private static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20; private static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21; + private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT = 0x14; + private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F; + private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15; private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; // Flags of the advertising data. @@ -57,6 +61,8 @@ public final class ScanRecord { @Nullable private final List<ParcelUuid> mServiceUuids; + @Nullable + private final List<ParcelUuid> mServiceSolicitationUuids; private final SparseArray<byte[]> mManufacturerSpecificData; @@ -88,6 +94,15 @@ public final class ScanRecord { } /** + * Returns a list of service solicitation UUIDs within the advertisement that are used to + * identify the Bluetooth GATT services. + */ + @Nullable + public List<ParcelUuid> getServiceSolicitationUuids() { + return mServiceSolicitationUuids; + } + + /** * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific * data. */ @@ -117,7 +132,7 @@ public final class ScanRecord { */ @Nullable public byte[] getServiceData(ParcelUuid serviceDataUuid) { - if (serviceDataUuid == null) { + if (serviceDataUuid == null || mServiceData == null) { return null; } return mServiceData.get(serviceDataUuid); @@ -150,10 +165,12 @@ public final class ScanRecord { } private ScanRecord(List<ParcelUuid> serviceUuids, + List<ParcelUuid> serviceSolicitationUuids, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, int advertiseFlags, int txPowerLevel, String localName, byte[] bytes) { + mServiceSolicitationUuids = serviceSolicitationUuids; mServiceUuids = serviceUuids; mManufacturerSpecificData = manufacturerData; mServiceData = serviceData; @@ -174,6 +191,7 @@ public final class ScanRecord { * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response. * @hide */ + @UnsupportedAppUsage public static ScanRecord parseFromBytes(byte[] scanRecord) { if (scanRecord == null) { return null; @@ -182,6 +200,7 @@ public final class ScanRecord { int currentPos = 0; int advertiseFlag = -1; List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); + List<ParcelUuid> serviceSolicitationUuids = new ArrayList<ParcelUuid>(); String localName = null; int txPowerLevel = Integer.MIN_VALUE; @@ -218,6 +237,18 @@ public final class ScanRecord { parseServiceUuid(scanRecord, currentPos, dataLength, BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids); break; + case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT: + parseServiceSolicitationUuid(scanRecord, currentPos, dataLength, + BluetoothUuid.UUID_BYTES_16_BIT, serviceSolicitationUuids); + break; + case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT: + parseServiceSolicitationUuid(scanRecord, currentPos, dataLength, + BluetoothUuid.UUID_BYTES_32_BIT, serviceSolicitationUuids); + break; + case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT: + parseServiceSolicitationUuid(scanRecord, currentPos, dataLength, + BluetoothUuid.UUID_BYTES_128_BIT, serviceSolicitationUuids); + break; case DATA_TYPE_LOCAL_NAME_SHORT: case DATA_TYPE_LOCAL_NAME_COMPLETE: localName = new String( @@ -263,19 +294,23 @@ public final class ScanRecord { if (serviceUuids.isEmpty()) { serviceUuids = null; } - return new ScanRecord(serviceUuids, manufacturerData, serviceData, - advertiseFlag, txPowerLevel, localName, scanRecord); + if (serviceSolicitationUuids.isEmpty()) { + serviceSolicitationUuids = null; + } + return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData, + serviceData, advertiseFlag, txPowerLevel, localName, scanRecord); } catch (Exception e) { Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); // As the record is invalid, ignore all the parsed results for this packet // and return an empty record with raw scanRecord bytes in results - return new ScanRecord(null, null, null, -1, Integer.MIN_VALUE, null, scanRecord); + return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, scanRecord); } } @Override public String toString() { return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids + + ", mServiceSolicitationUuids=" + mServiceSolicitationUuids + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString( mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) @@ -295,6 +330,20 @@ public final class ScanRecord { return currentPos; } + /** + * Parse service Solicitation UUIDs. + */ + private static int parseServiceSolicitationUuid(byte[] scanRecord, int currentPos, + int dataLength, int uuidLength, List<ParcelUuid> serviceSolicitationUuids) { + while (dataLength > 0) { + byte[] uuidBytes = extractBytes(scanRecord, currentPos, uuidLength); + serviceSolicitationUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes)); + dataLength -= uuidLength; + currentPos += uuidLength; + } + return currentPos; + } + // Helper method to extract bytes from byte array. private static byte[] extractBytes(byte[] scanRecord, int start, int length) { byte[] bytes = new byte[length]; |