am b2df0b60: Merge "Remove BluetoothAdapterCallback. Simplify leScan Api" into jb-mr2-dev

* commit 'b2df0b60d0995c760fc7ee3776caa0fc7f84066a':
  Remove BluetoothAdapterCallback. Simplify leScan Api
This commit is contained in:
Matthew Xie
2013-04-18 14:03:55 -07:00
committed by Android Git Automerger
4 changed files with 262 additions and 233 deletions

View File

@@ -20,7 +20,6 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.ParcelUuid;
@@ -30,11 +29,14 @@ import android.util.Log;
import android.util.Pair;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
@@ -357,9 +359,7 @@ public final class BluetoothAdapter {
private final IBluetoothManager mManagerService;
private IBluetooth mService;
private Handler mServiceRecordHandler;
private BluetoothAdapterCallback mCallback;
private int mClientIf;
private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients;
/**
* Get a handle to the default local Bluetooth adapter.
@@ -394,7 +394,7 @@ public final class BluetoothAdapter {
mService = managerService.registerAdapter(mManagerCallback);
} catch (RemoteException e) {Log.e(TAG, "", e);}
mManagerService = managerService;
mServiceRecordHandler = null;
mLeScanClients = new HashMap<LeScanCallback, GattCallbackWrapper>();
}
/**
@@ -1409,72 +1409,38 @@ public final class BluetoothAdapter {
}
/**
* Register an callback to receive async results, such as LE scan result.
* Callback interface used to deliver LE scan results.
*
* <p>This is an asynchronous call. The callback
* {@link BluetoothAdapterCallback#onCallbackRegistration}
* is used to notify success or failure if the function returns true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param callback BluetootAdapter callback handler that will receive asynchronous callbacks.
* @return If true, the callback will be called to notify success or failure,
* false on immediate error
* @see #startLeScan(LeScanCallback)
* @see #startLeScan(UUID[], LeScanCallback)
*/
public boolean registerCallback(BluetoothAdapterCallback callback) {
try {
IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
mCallback = callback;
UUID uuid = UUID.randomUUID();
if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);
iGatt.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
return true;
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
}
}
/**
* Unregister the registered callback.
*/
public boolean unRegisterCallback(BluetoothAdapterCallback callback) {
if (callback != mCallback) return false;
try {
IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
iGatt.unregisterClient(mClientIf);
return true;
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
}
public interface LeScanCallback {
/**
* Callback reporting an LE device found during a device scan initiated
* by the {@link BluetoothAdapter#startLeScan} function.
*
* @param device Identifies the remote device
* @param rssi The RSSI value for the remote device as reported by the
* Bluetooth hardware. 0 if no RSSI value is available.
* @param scanRecord The content of the advertisement record offered by
* the remote device.
*/
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
}
/**
* Starts a scan for Bluetooth LE devices.
*
* <p>Results of the scan are reported using the
* {@link BluetoothAdapterCallback#onLeScan} callback.
* {@link LeScanCallback#onLeScan} callback.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param callback the callback LE scan results are delivered
* @return true, if the scan was started successfully
*/
public boolean startLeScan() {
if (DBG) Log.d(TAG, "startLeScan()");
if (mClientIf == 0) return false;
try {
IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
iGatt.startScan(mClientIf, false);
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
}
return true;
public boolean startLeScan(LeScanCallback callback) {
return startLeScan(null, callback);
}
/**
@@ -1482,155 +1448,281 @@ public final class BluetoothAdapter {
* advertise given services.
*
* <p>Devices which advertise all specified services are reported using the
* {@link BluetoothAdapterCallback#onLeScan} callback.
* {@link LeScanCallback#onLeScan} callback.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @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
*/
public boolean startLeScan(UUID[] serviceUuids) {
if (DBG) Log.d(TAG, "startLeScan() - with UUIDs");
if (mClientIf == 0) return false;
public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) {
if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids);
try {
IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
ParcelUuid[] uuids = new ParcelUuid[serviceUuids.length];
for(int i = 0; i != uuids.length; ++i) {
uuids[i] = new ParcelUuid(serviceUuids[i]);
}
iGatt.startScanWithUuids(mClientIf, false, uuids);
} catch (RemoteException e) {
Log.e(TAG,"",e);
if (callback == null) {
if (DBG) Log.e(TAG, "startLeScan: null callback");
return false;
}
return true;
synchronized(mLeScanClients) {
if (mLeScanClients.containsKey(callback)) {
if (DBG) Log.e(TAG, "LE Scan has already started");
return false;
}
try {
IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
UUID uuid = UUID.randomUUID();
GattCallbackWrapper wrapper = new GattCallbackWrapper(this, callback, serviceUuids);
iGatt.registerClient(new ParcelUuid(uuid), wrapper);
if (wrapper.scanStarted()) {
mLeScanClients.put(callback, wrapper);
return true;
}
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
}
return false;
}
/**
* Stops an ongoing Bluetooth LE device scan.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param callback used to identify which scan to stop
* must be the same handle used to start the scan
*/
public void stopLeScan() {
if (DBG) Log.d(TAG, "stopScan()");
if (mClientIf == 0) return;
try {
IBluetoothGatt iGatt = (IBluetoothGatt) mManagerService.getBluetoothGatt();
iGatt.stopScan(mClientIf, false);
} catch (RemoteException e) {
Log.e(TAG,"",e);
public void stopLeScan(LeScanCallback callback) {
if (DBG) Log.d(TAG, "stopLeScan()");
GattCallbackWrapper wrapper;
synchronized(mLeScanClients) {
wrapper = mLeScanClients.remove(callback);
if (wrapper == null) return;
}
wrapper.stopLeScan();
}
/**
* Bluetooth GATT interface callbacks
*/
private final IBluetoothGattCallback mBluetoothGattCallback =
new IBluetoothGattCallback.Stub() {
/**
* Application interface registered - app is ready to go
*/
public void onClientRegistered(int status, int clientIf) {
if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
+ " clientIf=" + clientIf);
mClientIf = clientIf;
mCallback.onCallbackRegistration(status == BluetoothGatt.GATT_SUCCESS ?
BluetoothAdapterCallback.CALLBACK_REGISTERED :
BluetoothAdapterCallback.CALLBACK_REGISTRATION_FAILURE);
}
private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub {
private static final int LE_CALLBACK_REG_TIMEOUT = 2000;
private static final int LE_CALLBACK_REG_WAIT_COUNT = 5;
public void onClientConnectionState(int status, int clientIf,
boolean connected, String address) {
// no op
}
private final LeScanCallback mLeScanCb;
// mLeHandle 0: not registered
// -1: scan stopped
// >0: registered and scan started
private int mLeHandle;
private final UUID[] mScanFilter;
private WeakReference<BluetoothAdapter> mBluetoothAdapter;
/**
* Callback reporting an LE scan result.
* @hide
*/
public void onScanResult(String address, int rssi, byte[] advData) {
if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter,
LeScanCallback leScanCb, UUID[] uuid) {
mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter);
mLeScanCb = leScanCb;
mScanFilter = uuid;
mLeHandle = 0;
}
try {
mCallback.onLeScan(getRemoteDevice(address), rssi, advData);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
public boolean scanStarted() {
boolean started = false;
synchronized(this) {
if (mLeHandle == -1) return false;
int count = 0;
// wait for callback registration and LE scan to start
while (mLeHandle == 0 && count < LE_CALLBACK_REG_WAIT_COUNT) {
try {
wait(LE_CALLBACK_REG_TIMEOUT);
} catch (InterruptedException e) {
Log.e(TAG, "Callback reg wait interrupted: " + e);
}
count++;
}
started = (mLeHandle > 0);
}
return started;
}
public void onGetService(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid) {
// no op
public void stopLeScan() {
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.stopScan(mLeHandle, false);
iGatt.unregisterClient(mLeHandle);
} catch (RemoteException e) {
Log.e(TAG, "Failed to stop scan and unregister" + e);
}
} else {
Log.e(TAG, "stopLeScan, BluetoothAdapter is null");
}
mLeHandle = -1;
notifyAll();
}
}
public void onGetIncludedService(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int inclSrvcType, int inclSrvcInstId,
ParcelUuid inclSrvcUuid) {
// no op
/**
* Application interface registered - app is ready to go
*/
public void onClientRegistered(int status, int clientIf) {
if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status +
" clientIf=" + clientIf);
synchronized(this) {
if (mLeHandle == -1) {
if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled");
}
if (status == BluetoothGatt.GATT_SUCCESS) {
mLeHandle = clientIf;
IBluetoothGatt iGatt = null;
try {
BluetoothAdapter adapter = mBluetoothAdapter.get();
if (adapter != null) {
iGatt = adapter.getBluetoothManager().getBluetoothGatt();
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);
}
} else {
Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
mLeHandle = -1;
}
} catch (RemoteException e) {
Log.e(TAG, "fail to start le scan: " + e);
mLeHandle = -1;
}
if (mLeHandle == -1) {
// registration succeeded but start scan failed
if (iGatt != null) {
try {
iGatt.unregisterClient(mLeHandle);
} catch (RemoteException e) {
Log.e(TAG, "fail to unregister callback: " + mLeHandle +
" error: " + e);
}
}
}
} else {
// registration failed
mLeHandle = -1;
}
notifyAll();
}
}
public void onGetCharacteristic(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
int charProps) {
// no op
public void onClientConnectionState(int status, int clientIf,
boolean connected, String address) {
// no op
}
/**
* Callback reporting an LE scan result.
* @hide
*/
public void onScanResult(String address, int rssi, byte[] advData) {
if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
// Check null in case the scan has been stopped
synchronized(this) {
if (mLeHandle <= 0) return;
}
public void onGetDescriptor(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
ParcelUuid descUuid) {
// no op
try {
BluetoothAdapter adapter = mBluetoothAdapter.get();
if (adapter == null) {
Log.d(TAG, "onScanResult, BluetoothAdapter null");
return;
}
mLeScanCb.onLeScan(adapter.getRemoteDevice(address), rssi, advData);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
}
public void onSearchComplete(String address, int status) {
// no op
}
public void onGetService(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid) {
// no op
}
public void onCharacteristicRead(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid, byte[] value) {
// no op
}
public void onGetIncludedService(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int inclSrvcType, int inclSrvcInstId,
ParcelUuid inclSrvcUuid) {
// no op
}
public void onCharacteristicWrite(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid) {
// no op
}
public void onGetCharacteristic(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
int charProps) {
// no op
}
public void onNotify(String address, int srvcType,
public void onGetDescriptor(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
ParcelUuid descUuid) {
// no op
}
public void onSearchComplete(String address, int status) {
// no op
}
public void onCharacteristicRead(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid, byte[] value) {
// no op
}
public void onCharacteristicWrite(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid) {
// no op
}
public void onNotify(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
byte[] value) {
// no op
}
// no op
}
public void onDescriptorRead(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
ParcelUuid descrUuid, byte[] value) {
// no op
}
public void onDescriptorRead(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
ParcelUuid descrUuid, byte[] value) {
// no op
}
public void onDescriptorWrite(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
ParcelUuid descrUuid) {
// no op
}
public void onDescriptorWrite(String address, int status, int srvcType,
int srvcInstId, ParcelUuid srvcUuid,
int charInstId, ParcelUuid charUuid,
ParcelUuid descrUuid) {
// no op
}
public void onExecuteWrite(String address, int status) {
// no op
}
public void onExecuteWrite(String address, int status) {
// no op
}
public void onReadRemoteRssi(String address, int rssi, int status) {
// no op
}
};
public void onReadRemoteRssi(String address, int rssi, int status) {
// no op
}
}
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright (C) 2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth;
import android.bluetooth.BluetoothDevice;
/**
* This abstract class is used to implement {@link BluetoothAdapter} callbacks.
*/
public abstract class BluetoothAdapterCallback {
/**
* Indicates the callback has been registered successfully
*/
public static final int CALLBACK_REGISTERED = 0;
/**
* Indicates the callback registration has failed
*/
public static final int CALLBACK_REGISTRATION_FAILURE = 1;
/**
* Callback to inform change in registration state of the application.
*
* @param status Returns {@link #CALLBACK_REGISTERED} if the application
* was successfully registered.
*/
public void onCallbackRegistration(int status) {
}
/**
* Callback reporting an LE device found during a device scan initiated
* by the {@link BluetoothAdapter#startLeScan} function.
*
* @param device Identifies the remote device
* @param rssi The RSSI value for the remote device as reported by the
* Bluetooth hardware. 0 if no RSSI value is available.
* @param scanRecord The content of the advertisement record offered by
* the remote device.
*/
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
}
}

View File

@@ -127,7 +127,7 @@ public final class BluetoothManager {
try {
IBluetoothManager managerService = mAdapter.getBluetoothManager();
IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
IBluetoothGatt iGatt = managerService.getBluetoothGatt();
if (iGatt == null) return connectedDevices;
connectedDevices = iGatt.getDevicesMatchingConnectionStates(
@@ -172,7 +172,7 @@ public final class BluetoothManager {
try {
IBluetoothManager managerService = mAdapter.getBluetoothManager();
IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
IBluetoothGatt iGatt = managerService.getBluetoothGatt();
if (iGatt == null) return devices;
devices = iGatt.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
@@ -203,7 +203,7 @@ public final class BluetoothManager {
try {
IBluetoothManager managerService = mAdapter.getBluetoothManager();
IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
IBluetoothGatt iGatt = managerService.getBluetoothGatt();
if (iGatt == null) {
Log.e(TAG, "Fail to get GATT Server connection");
return null;