diff options
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothAdapter.java')
| -rw-r--r-- | framework/java/android/bluetooth/BluetoothAdapter.java | 344 |
1 files changed, 108 insertions, 236 deletions
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 646be0666f..faf864550d 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2009-2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,15 @@ package android.bluetooth; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.bluetooth.le.BluetoothLeAdvertiser; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; import android.content.Context; -import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.Message; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ServiceManager; @@ -37,9 +40,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.UUID; @@ -216,22 +219,6 @@ public final class BluetoothAdapter { "android.bluetooth.adapter.action.SCAN_MODE_CHANGED"; /** - * Broadcast Action: Indicate BLE Advertising is started. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED = - "android.bluetooth.adapter.action.ADVERTISING_STARTED"; - - /** - * Broadcast Action: Indicated BLE Advertising is stopped. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED = - "android.bluetooth.adapter.action.ADVERTISING_STOPPED"; - - /** * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} * intents to request the current scan mode. Possible values are: * {@link #SCAN_MODE_NONE}, @@ -400,8 +387,6 @@ public final class BluetoothAdapter { private IBluetooth mService; private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients; - private BluetoothAdvScanData mBluetoothAdvScanData = null; - private GattCallbackWrapper mAdvertisingGattCallback; private final Handler mHandler; // Handler to post the advertise callback to run on main thread. private final Object mLock = new Object(); @@ -478,126 +463,19 @@ public final class BluetoothAdapter { } /** - * Returns a {@link BluetoothAdvScanData} object representing advertising data. - * Data will be reset when bluetooth service is turned off. - * @hide + * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations. */ - public BluetoothAdvScanData getAdvScanData() { - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - if (iGatt == null) { - // BLE is not supported - Log.e(TAG, "failed to start, iGatt null"); - return null; - } - if (mBluetoothAdvScanData == null) { - mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD); - } - return mBluetoothAdvScanData; - } catch (RemoteException e) { - Log.e(TAG, "failed to get advScanData, error: " + e); - return null; - } - } - - /** - * Interface for BLE advertising callback. - * - * @hide - */ - public interface AdvertiseCallback { - /** - * Callback when advertise starts. - * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure. - */ - void onAdvertiseStart(int status); - /** - * Callback when advertise stops. - * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure. - */ - void onAdvertiseStop(int status); - } - - /** - * Start BLE advertising using current {@link BluetoothAdvScanData}. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} - * - * @param callback - {@link AdvertiseCallback} - * @return true if BLE advertising succeeds, false otherwise. - * @hide - */ - public boolean startAdvertising(final AdvertiseCallback callback) { - if (getState() != STATE_ON) return false; - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - if (iGatt == null) { - // BLE is not supported. - return false; - } - // Restart/reset advertising packets if advertising is in progress. - if (isAdvertising()) { - // Invalid advertising callback. - if (mAdvertisingGattCallback == null || mAdvertisingGattCallback.mLeHandle == -1) { - Log.e(TAG, "failed to restart advertising, invalid callback"); - return false; - } - iGatt.startAdvertising(mAdvertisingGattCallback.mLeHandle); - // Run the callback from main thread. - mHandler.post(new Runnable() { - @Override - public void run() { - // callback with status success. - callback.onAdvertiseStart(ADVERTISE_CALLBACK_SUCCESS); - } - }); - return true; - } - UUID uuid = UUID.randomUUID(); - GattCallbackWrapper wrapper = - new GattCallbackWrapper(this, null, null, callback); - iGatt.registerClient(new ParcelUuid(uuid), wrapper); - if (!wrapper.advertiseStarted()) { - return false; - } - synchronized (mLock) { - mAdvertisingGattCallback = wrapper; - } - return true; - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; - } + public BluetoothLeAdvertiser getBluetoothLeAdvertiser() { + // TODO: Return null if this feature is not supported by hardware. + return new BluetoothLeAdvertiser(mManagerService); } /** - * Stop BLE advertising. The callback has to be the same one used for start advertising. - * - * @param callback - {@link AdvertiseCallback} - * @return true if BLE advertising stops, false otherwise. - * @hide + * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations. */ - public boolean stopAdvertising(AdvertiseCallback callback) { - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - if (iGatt == null) { - // BLE is not supported - return false; - } - if (mAdvertisingGattCallback == null) { - // no callback. - return false; - } - // Make sure same callback is used for start and stop advertising. - if (callback != mAdvertisingGattCallback.mAdvertiseCallback) { - Log.e(TAG, "must use the same callback for star/stop advertising"); - return false; - } - mAdvertisingGattCallback.stopAdvertising(); - return true; - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; - } + public BluetoothLeScanner getBluetoothLeScanner() { + // TODO: Return null if BLE scan is not supported by hardware. + return new BluetoothLeScanner(mManagerService); } /** @@ -1012,18 +890,46 @@ public final class BluetoothAdapter { } /** - * Returns whether BLE is currently advertising. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. + * Return true if the multi advertisement is supported by the chipset * - * @hide + * @return true if Multiple Advertisement feature is supported */ - public boolean isAdvertising() { + public boolean isMultipleAdvertisementSupported() { if (getState() != STATE_ON) return false; try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - return iGatt.isAdvertising(); + return mService.isMultiAdvertisementSupported(); } catch (RemoteException e) { - Log.e(TAG, "", e); + Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e); + } + return false; + } + + /** + * Return true if offloaded filters are supported + * + * @return true if chipset supports on-chip filtering + */ + public boolean isOffloadedFilteringSupported() { + if (getState() != STATE_ON) return false; + try { + return mService.isOffloadedFilteringSupported(); + } catch (RemoteException e) { + Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e); + } + return false; + } + + /** + * Return true if offloaded scan batching is supported + * + * @return true if chipset supports on-chip scan batching + */ + public boolean isOffloadedScanBatchingSupported() { + if (getState() != STATE_ON) return false; + try { + return mService.isOffloadedScanBatchingSupported(); + } catch (RemoteException e) { + Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e); } return false; } @@ -1363,6 +1269,12 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.A2DP) { BluetoothA2dp a2dp = new BluetoothA2dp(context, listener); return true; + } else if (profile == BluetoothProfile.A2DP_SINK) { + BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener); + return true; + } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) { + BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener); + return true; } else if (profile == BluetoothProfile.INPUT_DEVICE) { BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener); return true; @@ -1375,6 +1287,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.MAP) { BluetoothMap map = new BluetoothMap(context, listener); return true; + } else if (profile == BluetoothProfile.HEADSET_CLIENT) { + BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener); + return true; } else { return false; } @@ -1403,6 +1318,14 @@ public final class BluetoothAdapter { BluetoothA2dp a2dp = (BluetoothA2dp)proxy; a2dp.close(); break; + case BluetoothProfile.A2DP_SINK: + BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy; + a2dpSink.close(); + break; + case BluetoothProfile.AVRCP_CONTROLLER: + BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy; + avrcp.close(); + break; case BluetoothProfile.INPUT_DEVICE: BluetoothInputDevice iDev = (BluetoothInputDevice)proxy; iDev.close(); @@ -1427,6 +1350,10 @@ public final class BluetoothAdapter { BluetoothMap map = (BluetoothMap)proxy; map.close(); break; + case BluetoothProfile.HEADSET_CLIENT: + BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy; + headsetClient.close(); + break; } } @@ -1452,8 +1379,6 @@ public final class BluetoothAdapter { if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); synchronized (mManagerCallback) { mService = null; - // Reset bluetooth adv scan data when Gatt service is down. - mBluetoothAdvScanData = null; for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ try { if (cb != null) { @@ -1651,7 +1576,10 @@ public final class BluetoothAdapter { * * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully + * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} + * instead. */ + @Deprecated public boolean startLeScan(LeScanCallback callback) { return startLeScan(null, callback); } @@ -1668,7 +1596,10 @@ public final class BluetoothAdapter { * @param serviceUuids Array of services to look for * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully + * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} + * instead. */ + @Deprecated public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) { if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids); @@ -1711,7 +1642,9 @@ public final class BluetoothAdapter { * * @param callback used to identify which scan to stop * must be the same handle used to start the scan + * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead. */ + @Deprecated public void stopLeScan(LeScanCallback callback) { if (DBG) Log.d(TAG, "stopLeScan()"); GattCallbackWrapper wrapper; @@ -1729,7 +1662,6 @@ public final class BluetoothAdapter { private static final int LE_CALLBACK_REG_TIMEOUT = 2000; private static final int LE_CALLBACK_REG_WAIT_COUNT = 5; - private final AdvertiseCallback mAdvertiseCallback; private final LeScanCallback mLeScanCb; // mLeHandle 0: not registered @@ -1745,27 +1677,12 @@ public final class BluetoothAdapter { mLeScanCb = leScanCb; mScanFilter = uuid; mLeHandle = 0; - mAdvertiseCallback = null; - } - - public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb, - UUID[] uuid, AdvertiseCallback callback) { - mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter); - mLeScanCb = leScanCb; - mScanFilter = uuid; - mLeHandle = 0; - mAdvertiseCallback = callback; } public boolean scanStarted() { return waitForRegisteration(LE_CALLBACK_REG_WAIT_COUNT); } - public boolean advertiseStarted() { - // Wait for registeration callback. - return waitForRegisteration(1); - } - private boolean waitForRegisteration(int maxWaitCount) { boolean started = false; synchronized(this) { @@ -1785,27 +1702,6 @@ public final class BluetoothAdapter { return started; } - public void stopAdvertising() { - synchronized (this) { - if (mLeHandle <= 0) { - Log.e(TAG, "Error state, mLeHandle: " + mLeHandle); - return; - } - BluetoothAdapter adapter = mBluetoothAdapter.get(); - if (adapter != null) { - try { - IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt(); - iGatt.stopAdvertising(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to stop advertising" + e); - } - } else { - Log.e(TAG, "stopAdvertising, BluetoothAdapter is null"); - } - notifyAll(); - } - } - public void stopLeScan() { synchronized(this) { if (mLeHandle <= 0) { @@ -1847,18 +1743,14 @@ public final class BluetoothAdapter { BluetoothAdapter adapter = mBluetoothAdapter.get(); if (adapter != null) { iGatt = adapter.getBluetoothManager().getBluetoothGatt(); - if (mAdvertiseCallback != null) { - iGatt.startAdvertising(mLeHandle); + if (mScanFilter == null) { + iGatt.startScan(mLeHandle, false); } else { - if (mScanFilter == null) { - iGatt.startScan(mLeHandle, false); - } else { - ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; - for(int i = 0; i != uuids.length; ++i) { - uuids[i] = new ParcelUuid(mScanFilter[i]); - } - iGatt.startScanWithUuids(mLeHandle, false, uuids); - } + ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length]; + for(int i = 0; i != uuids.length; ++i) { + uuids[i] = new ParcelUuid(mScanFilter[i]); + } + iGatt.startScanWithUuids(mLeHandle, false, uuids); } } else { Log.e(TAG, "onClientRegistered, BluetoothAdapter null"); @@ -1987,52 +1879,32 @@ public final class BluetoothAdapter { } public void onAdvertiseStateChange(int advertiseState, int status) { - Log.d(TAG, "on advertise call back, state: " + advertiseState + " status: " + status); - if (advertiseState == STATE_ADVERTISE_STARTED) { - if (status == ADVERTISE_CALLBACK_SUCCESS) { - mAdvertiseCallback.onAdvertiseStart(status); - } else { - // If status is unsuccessful and advertise state is started, it means stop - // advertising fails. - mAdvertiseCallback.onAdvertiseStop(status); - } - } else { - synchronized (this) { - if (status == ADVERTISE_CALLBACK_SUCCESS) { - BluetoothAdapter adapter = mBluetoothAdapter.get(); - if (adapter != null) { - try { - IBluetoothGatt iGatt = - adapter.getBluetoothManager().getBluetoothGatt(); - Log.d(TAG, "unregistering client " + mLeHandle); - iGatt.unregisterClient(mLeHandle); - // Reset advertise app handle. - mLeHandle = -1; - adapter.mAdvertisingGattCallback = null; - } catch (RemoteException e) { - Log.e(TAG, "Failed to unregister client" + e); - } - } else { - Log.e(TAG, "cannot unregister client, BluetoothAdapter is null"); - } - } - } - if (status == ADVERTISE_CALLBACK_SUCCESS) { - mAdvertiseCallback.onAdvertiseStop(status); - } else{ - // If status is unsuccesful and advertise state is stopped, it means start - // advertising fails. - mAdvertiseCallback.onAdvertiseStart(status); - } - } } - /** - * Callback reporting LE ATT MTU. - * @hide - */ + @Override + public void onMultiAdvertiseCallback(int status) { + // no op + } + + @Override public void onConfigureMTU(String address, int mtu, int status) { // no op } + + @Override + public void onConnectionCongested(String address, boolean congested) { + // no op + } + + @Override + public void onBatchScanResults(List<ScanResult> results) { + // no op + } + + @Override + public void onFoundOrLost(boolean onFound, String address,int rssi, + byte[] advData) { + // no op + } } } |
